diff --git a/hbase-protocol-shaded/src/main/protobuf/MasterProcedure.proto b/hbase-protocol-shaded/src/main/protobuf/MasterProcedure.proto index 2cdebb1..626530f 100644 --- a/hbase-protocol-shaded/src/main/protobuf/MasterProcedure.proto +++ b/hbase-protocol-shaded/src/main/protobuf/MasterProcedure.proto @@ -286,9 +286,9 @@ enum SplitTableRegionState { SPLIT_TABLE_REGION_PRE_OPERATION = 2; SPLIT_TABLE_REGION_CLOSE_PARENT_REGION = 3; SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS = 4; - SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR = 5; + SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_META = 5; SPLIT_TABLE_REGION_UPDATE_META = 6; - SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR = 7; + SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_META = 7; SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS = 8; SPLIT_TABLE_REGION_POST_OPERATION = 9; } diff --git a/hbase-protocol-shaded/src/main/protobuf/RegionServerStatus.proto b/hbase-protocol-shaded/src/main/protobuf/RegionServerStatus.proto index 1cd4376..ff30e8f 100644 --- a/hbase-protocol-shaded/src/main/protobuf/RegionServerStatus.proto +++ b/hbase-protocol-shaded/src/main/protobuf/RegionServerStatus.proto @@ -105,13 +105,12 @@ message RegionStateTransition { READY_TO_SPLIT = 3; READY_TO_MERGE = 4; - SPLIT_PONR = 5; - MERGE_PONR = 6; - SPLIT = 7; - MERGED = 8; - SPLIT_REVERTED = 9; - MERGE_REVERTED = 10; + SPLIT = 5; + MERGED = 6; + + SPLIT_REVERTED = 7; + MERGE_REVERTED = 8; } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index 87b9679..2065ea3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -696,25 +696,25 @@ public interface MasterObserver extends Coprocessor { final RegionInfo regionInfoB) throws IOException {} /** - * This will be called before PONR step as part of split transaction. Calling + * This will be called before update META step as part of split transaction. Calling * {@link org.apache.hadoop.hbase.coprocessor.ObserverContext#bypass()} rollback the split * @param ctx the environment to interact with the framework and master * @param splitKey * @param metaEntries */ - default void preSplitRegionBeforePONRAction( + default void preSplitRegionBeforeMETAAction( final ObserverContext ctx, final byte[] splitKey, final List metaEntries) throws IOException {} /** - * This will be called after PONR step as part of split transaction + * This will be called after update META step as part of split transaction * Calling {@link org.apache.hadoop.hbase.coprocessor.ObserverContext#bypass()} has no * effect in this hook. * @param ctx the environment to interact with the framework and master */ - default void preSplitRegionAfterPONRAction( + default void preSplitRegionAfterMETAAction( final ObserverContext ctx) throws IOException {} @@ -745,7 +745,7 @@ public interface MasterObserver extends Coprocessor { final RegionInfo mergedRegion) throws IOException {} /** - * This will be called before PONR step as part of regions merge transaction. Calling + * This will be called before update META step as part of regions merge transaction. Calling * {@link org.apache.hadoop.hbase.coprocessor.ObserverContext#bypass()} rollback the merge * @param ctx the environment to interact with the framework and master * @param metaEntries mutations to execute on hbase:meta atomically with regions merge updates. @@ -757,7 +757,7 @@ public interface MasterObserver extends Coprocessor { @MetaMutationAnnotation List metaEntries) throws IOException {} /** - * This will be called after PONR step as part of regions merge transaction. + * This will be called after META step as part of regions merge transaction. * @param ctx the environment to interact with the framework and master */ default void postMergeRegionsCommitAction( diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index 30d8015..40667e1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -910,13 +910,13 @@ public class MasterCoprocessorHost } /** - * This will be called before PONR step as part of split table region procedure. + * This will be called before update META step as part of split table region procedure. * @param splitKey * @param metaEntries * @param user the user * @throws IOException */ - public boolean preSplitBeforePONRAction( + public boolean preSplitBeforeMETAAction( final byte[] splitKey, final List metaEntries, final User user) throws IOException { @@ -924,22 +924,22 @@ public class MasterCoprocessorHost @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { - oserver.preSplitRegionBeforePONRAction(ctx, splitKey, metaEntries); + oserver.preSplitRegionBeforeMETAAction(ctx, splitKey, metaEntries); } }); } /** - * This will be called after PONR step as part of split table region procedure. + * This will be called after update META step as part of split table region procedure. * @param user the user * @throws IOException */ - public void preSplitAfterPONRAction(final User user) throws IOException { + public void preSplitAfterMETAAction(final User user) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation(user) { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { - oserver.preSplitRegionAfterPONRAction(ctx); + oserver.preSplitRegionAfterMETAAction(ctx); } }); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java index f96c1a5..eed431b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java @@ -753,7 +753,6 @@ public class AssignmentManager implements ServerListener { transition.hasOpenSeqNum() ? transition.getOpenSeqNum() : HConstants.NO_SEQNUM); break; case READY_TO_SPLIT: - case SPLIT_PONR: case SPLIT: case SPLIT_REVERTED: assert transition.getRegionInfoCount() == 3 : transition; @@ -764,7 +763,6 @@ public class AssignmentManager implements ServerListener { parent, splitA, splitB); break; case READY_TO_MERGE: - case MERGE_PONR: case MERGED: case MERGE_REVERTED: assert transition.getRegionInfoCount() == 3 : transition; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java index f67aa5b..979eb0c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.java @@ -152,7 +152,8 @@ public class SplitTableRegionProcedure } if(bestSplitRow == null || bestSplitRow.length == 0) { - throw new DoNotRetryIOException("Region not splittable because bestSplitPoint = null"); + throw new DoNotRetryIOException("Region not splittable because bestSplitPoint = null, " + + "maybe table is too small for auto split. For force split, try specifying split row"); } if (Bytes.equals(regionToSplit.getStartKey(), bestSplitRow)) { @@ -211,18 +212,18 @@ public class SplitTableRegionProcedure break; case SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS: createDaughterRegions(env); - setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR); + setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_META); break; - case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR: - preSplitRegionBeforePONR(env); + case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_META: + preSplitRegionBeforeMETA(env); setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_UPDATE_META); break; case SPLIT_TABLE_REGION_UPDATE_META: updateMetaForDaughterRegions(env); - setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR); + setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_META); break; - case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: - preSplitRegionAfterPONR(env); + case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_META: + preSplitRegionAfterMETA(env); setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS); break; case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: @@ -261,11 +262,11 @@ public class SplitTableRegionProcedure switch (state) { case SPLIT_TABLE_REGION_POST_OPERATION: case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: - case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: + case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_META: case SPLIT_TABLE_REGION_UPDATE_META: // PONR throw new UnsupportedOperationException(this + " unhandled state=" + state); - case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR: + case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_META: break; case SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS: // Doing nothing, as re-open parent region would clean up daughter region directories. @@ -299,7 +300,7 @@ public class SplitTableRegionProcedure switch (state) { case SPLIT_TABLE_REGION_POST_OPERATION: case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: - case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: + case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_META: case SPLIT_TABLE_REGION_UPDATE_META: // It is not safe to rollback if we reach to these states. return false; @@ -691,12 +692,12 @@ public class SplitTableRegionProcedure * Post split region actions before the Point-of-No-Return step * @param env MasterProcedureEnv **/ - private void preSplitRegionBeforePONR(final MasterProcedureEnv env) + private void preSplitRegionBeforeMETA(final MasterProcedureEnv env) throws IOException, InterruptedException { final List metaEntries = new ArrayList(); final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost(); if (cpHost != null) { - if (cpHost.preSplitBeforePONRAction(getSplitRow(), metaEntries, getUser())) { + if (cpHost.preSplitBeforeMETAAction(getSplitRow(), metaEntries, getUser())) { throw new IOException("Coprocessor bypassing region " + getParentRegion().getRegionNameAsString() + " split."); } @@ -727,11 +728,11 @@ public class SplitTableRegionProcedure * Pre split region actions after the Point-of-No-Return step * @param env MasterProcedureEnv **/ - private void preSplitRegionAfterPONR(final MasterProcedureEnv env) + private void preSplitRegionAfterMETA(final MasterProcedureEnv env) throws IOException, InterruptedException { final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost(); if (cpHost != null) { - cpHost.preSplitAfterPONRAction(getUser()); + cpHost.preSplitAfterMETAAction(getUser()); } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java index 1e36b0b..7e11cd2 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java @@ -1424,14 +1424,14 @@ public class TestMasterObserver { } @Override - public void preSplitRegionBeforePONRAction( + public void preSplitRegionBeforeMETAAction( final ObserverContext ctx, final byte[] splitKey, final List metaEntries) throws IOException { } @Override - public void preSplitRegionAfterPONRAction( + public void preSplitRegionAfterMETAAction( final ObserverContext ctx) throws IOException { } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestMergeTableRegionsProcedure.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestMergeTableRegionsProcedure.java index dcc0702..25918b1 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestMergeTableRegionsProcedure.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestMergeTableRegionsProcedure.java @@ -272,6 +272,35 @@ public class TestMergeTableRegionsProcedure { MasterProcedureTestingUtility.testRollbackAndDoubleExecution(procExec, procId, numberOfSteps); } + @Test + public void testMergeWithoutPONR() throws Exception { + final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution"); + final ProcedureExecutor procExec = getMasterProcedureExecutor(); + + List tableRegions = createTable(tableName); + + ProcedureTestingUtility.waitNoProcedureRunning(procExec); + ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); + + HRegionInfo[] regionsToMerge = new HRegionInfo[2]; + regionsToMerge[0] = tableRegions.get(0); + regionsToMerge[1] = tableRegions.get(1); + + long procId = procExec.submitProcedure( + new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true)); + + // Execute until step 9 of split procedure + // NOTE: step 9 is after step MERGE_TABLE_REGIONS_UPDATE_META + MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, 9, false); + + // Unset Toggle Kill and make ProcExec work correctly + ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false); + MasterProcedureTestingUtility.restartMasterProcedureExecutor(procExec); + ProcedureTestingUtility.waitProcedure(procExec, procId); + + assertRegionCount(tableName, initialRegionCount - 1); + } + private List createTable(final TableName tableName) throws Exception { HTableDescriptor desc = new HTableDescriptor(tableName); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSplitTableRegionProcedure.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSplitTableRegionProcedure.java index ae08f12..29a1fa5 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSplitTableRegionProcedure.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSplitTableRegionProcedure.java @@ -415,6 +415,39 @@ public class TestSplitTableRegionProcedure { assertEquals(splitFailedCount, splitProcMetrics.getFailedCounter().getCount()); } + @Test + public void testSplitWithoutPONR() throws Exception { + final TableName tableName = TableName.valueOf(name.getMethodName()); + final ProcedureExecutor procExec = getMasterProcedureExecutor(); + + HRegionInfo [] regions = MasterProcedureTestingUtility.createTable( + procExec, tableName, null, ColumnFamilyName1, ColumnFamilyName2); + insertData(tableName); + int splitRowNum = startRowNum + rowCount / 2; + byte[] splitKey = Bytes.toBytes("" + splitRowNum); + + assertTrue("not able to find a splittable region", regions != null); + assertTrue("not able to find a splittable region", regions.length == 1); + ProcedureTestingUtility.waitNoProcedureRunning(procExec); + ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); + + // Split region of the table + long procId = procExec.submitProcedure( + new SplitTableRegionProcedure(procExec.getEnvironment(), regions[0], splitKey)); + + // Execute until step 7 of split procedure + // NOTE: the 7 (number after SPLIT_TABLE_REGION_UPDATE_META step) + MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, 7, false); + + // Unset Toggle Kill and make ProcExec work correctly + ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false); + MasterProcedureTestingUtility.restartMasterProcedureExecutor(procExec); + ProcedureTestingUtility.waitProcedure(procExec, procId); + + // Even split failed after step 4, it should still works fine + verify(tableName, splitRowNum); + } + private void insertData(final TableName tableName) throws IOException, InterruptedException { Table t = UTIL.getConnection().getTable(tableName); Put p; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java index 1ca8518..6eebe36 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.java @@ -366,7 +366,7 @@ public class MasterProcedureTestingUtility { * finish. * @see #testRecoveryAndDoubleExecution(ProcedureExecutor, long) */ - private static void testRecoveryAndDoubleExecution( + public static void testRecoveryAndDoubleExecution( final ProcedureExecutor procExec, final long procId, final int numSteps, final boolean expectExecRunning) throws Exception { ProcedureTestingUtility.waitProcedure(procExec, procId); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java index c2c3171..e57c0c7 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java @@ -276,7 +276,7 @@ public class TestSplitTransactionOnCluster { latch = new CountDownLatch(1); } @Override - public void preSplitRegionBeforePONRAction( + public void preSplitRegionBeforeMETAAction( final ObserverContext ctx, final byte[] splitKey, final List metaEntries) throws IOException {