public MergeTableRegionsProcedure createMergeProcedure(final RegionInfo regionToMergeA, final RegionInfo regionToMergeB) throws IOException { return new MergeTableRegionsProcedure(getProcedureEnvironment(), regionToMergeA,regionToMergeB); }
switch (state) { case MERGE_TABLE_REGIONS_PREPARE: if (!prepareMergeRegion(env)) { assert isFailed() : "Merge region should have an exception here"; return Flow.NO_MORE_STATE; setNextState(MergeTableRegionsState.MERGE_TABLE_REGIONS_PRE_MERGE_OPERATION); break; case MERGE_TABLE_REGIONS_PRE_MERGE_OPERATION: preMergeRegions(env); setNextState(MergeTableRegionsState.MERGE_TABLE_REGIONS_CLOSE_REGIONS); break; case MERGE_TABLE_REGIONS_CLOSE_REGIONS: addChildProcedure(createUnassignProcedures(env)); setNextState(MergeTableRegionsState.MERGE_TABLE_REGIONS_CHECK_CLOSED_REGIONS); break; case MERGE_TABLE_REGIONS_CHECK_CLOSED_REGIONS: checkClosedRegions(env); setNextState(MergeTableRegionsState.MERGE_TABLE_REGIONS_CREATE_MERGED_REGION); break; case MERGE_TABLE_REGIONS_CREATE_MERGED_REGION: removeNonDefaultReplicas(env); createMergedRegion(env); setNextState(MergeTableRegionsState.MERGE_TABLE_REGIONS_WRITE_MAX_SEQUENCE_ID_FILE); break; case MERGE_TABLE_REGIONS_WRITE_MAX_SEQUENCE_ID_FILE: writeMaxSequenceIdFile(env); setNextState(MergeTableRegionsState.MERGE_TABLE_REGIONS_PRE_MERGE_COMMIT_OPERATION); break;
public MergeTableRegionsProcedure(final MasterProcedureEnv env, final RegionInfo[] regionsToMerge, final boolean forcible) throws IOException { super(env); // Check daughter regions and make sure that we have valid daughter regions // before doing the real work. This check calls the super method #checkOnline also. checkRegionsToMerge(env, regionsToMerge, forcible); // WARN: make sure there is no parent region of the two merging regions in // hbase:meta If exists, fixing up daughters would cause daughter regions(we // have merged one) online again when we restart master, so we should clear // the parent region to prevent the above case // Since HBASE-7721, we don't need fix up daughters any more. so here do nothing this.regionsToMerge = regionsToMerge; this.mergedRegion = createMergedRegionInfo(regionsToMerge); preflightChecks(env, true); this.forcible = forcible; }
protected void rollbackState(final MasterProcedureEnv env, final MergeTableRegionsState state) throws IOException { if (isTraceEnabled()) { LOG.trace(this + " rollback state=" + state); case MERGE_TABLE_REGIONS_CREATE_MERGED_REGION: case MERGE_TABLE_REGIONS_WRITE_MAX_SEQUENCE_ID_FILE: cleanupMergedRegion(env); break; case MERGE_TABLE_REGIONS_CHECK_CLOSED_REGIONS: break; case MERGE_TABLE_REGIONS_CLOSE_REGIONS: rollbackCloseRegionsForMerge(env); break; case MERGE_TABLE_REGIONS_PRE_MERGE_OPERATION: postRollBackMergeRegions(env); break; case MERGE_TABLE_REGIONS_PREPARE: + RegionInfo.getShortNameToLog(regionsToMerge) + " in table " + getTableName(), e); throw e;
new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true); long procId = procExec.submitProcedure(proc); ProcedureTestingUtility.waitProcedure(procExec, procId); proc.getMergedRegion().getRegionName()); assertTrue(pair.getFirst() != null && pair.getSecond() != null); while (pair != null && pair.getFirst() != null && pair.getSecond() != null) { pair = MetaTableAccessor.getRegionsFromMergeQualifier(UTIL.getConnection(), proc.getMergedRegion().getRegionName());
private static RegionInfo createMergedRegionInfo(final RegionInfo[] regionsToMerge) { return createMergedRegionInfo(regionsToMerge[0], regionsToMerge[1]); }
private static void checkRegionsToMerge(MasterProcedureEnv env, final RegionInfo[] regionsToMerge, final boolean forcible) throws MergeRegionException { // For now, we only merge 2 regions. // It could be extended to more than 2 regions in the future. if (regionsToMerge == null || regionsToMerge.length != 2) { throw new MergeRegionException("Expected to merge 2 regions, got: " + Arrays.toString(regionsToMerge)); } checkRegionsToMerge(env, regionsToMerge[0], regionsToMerge[1], forcible); }
/** * One time checks. */ private static void checkRegionsToMerge(MasterProcedureEnv env, final RegionInfo regionToMergeA, final RegionInfo regionToMergeB, final boolean forcible) throws MergeRegionException { if (!regionToMergeA.getTable().equals(regionToMergeB.getTable())) { throw new MergeRegionException("Can't merge regions from two different tables: " + regionToMergeA + ", " + regionToMergeB); } if (regionToMergeA.getReplicaId() != RegionInfo.DEFAULT_REPLICA_ID || regionToMergeB.getReplicaId() != RegionInfo.DEFAULT_REPLICA_ID) { throw new MergeRegionException("Can't merge non-default replicas"); } try { checkOnline(env, regionToMergeA); checkOnline(env, regionToMergeB); } catch (DoNotRetryRegionException dnrre) { throw new MergeRegionException(dnrre); } if (!RegionInfo.areAdjacent(regionToMergeA, regionToMergeB)) { String msg = "Unable to merge non-adjacent regions " + regionToMergeA.getShortNameToLog() + ", " + regionToMergeB.getShortNameToLog() + " where forcible = " + forcible; LOG.warn(msg); if (!forcible) { throw new MergeRegionException(msg); } } }
new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true); long procId = procExec.submitProcedure(proc); ProcedureTestingUtility.waitProcedure(procExec, procId); proc.getMergedRegion().getRegionName()); assertTrue(pair.getFirst() != null && pair.getSecond() != null); while (pair != null && pair.getFirst() != null && pair.getSecond() != null) { pair = MetaTableAccessor.getRegionsFromMergeQualifier(UTIL.getConnection(), proc.getMergedRegion().getRegionName());
@Override protected void run() throws IOException { getMaster().getMasterCoprocessorHost().preMergeRegions(regionsToMerge); LOG.info(getClientIdAuditPrefix() + " Merge regions " + regionsToMerge[0].getEncodedName() + " and " + regionsToMerge[1].getEncodedName()); submitProcedure(new MergeTableRegionsProcedure(procedureExecutor.getEnvironment(), regionsToMerge, forcible)); getMaster().getMasterCoprocessorHost().postMergeRegions(regionsToMerge); }
@Test public void testRecoveryAndDoubleExecution() throws Exception { final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution"); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); List<RegionInfo> tableRegions = createTable(tableName); ProcedureTestingUtility.waitNoProcedureRunning(procExec); ProcedureTestingUtility.setKillIfHasParent(procExec, false); ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); RegionInfo[] regionsToMerge = new RegionInfo[2]; regionsToMerge[0] = tableRegions.get(0); regionsToMerge[1] = tableRegions.get(1); long procId = procExec.submitProcedure( new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true)); // Restart the executor and execute the step twice MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId); ProcedureTestingUtility.assertProcNotFailed(procExec, procId); assertRegionCount(tableName, initialRegionCount - 1); }
@Test public void testRollbackAndDoubleExecution() throws Exception { final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution"); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); List<RegionInfo> tableRegions = createTable(tableName); ProcedureTestingUtility.waitNoProcedureRunning(procExec); ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); RegionInfo[] regionsToMerge = new RegionInfo[2]; regionsToMerge[0] = tableRegions.get(0); regionsToMerge[1] = tableRegions.get(1); long procId = procExec.submitProcedure( new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true)); // Failing before MERGE_TABLE_REGIONS_UPDATE_META we should trigger the rollback // NOTE: the 8 (number of MERGE_TABLE_REGIONS_UPDATE_META step) is // hardcoded, so you have to look at this test at least once when you add a new step. int lastStep = 8; MasterProcedureTestingUtility.testRollbackAndDoubleExecution(procExec, procId, lastStep, true); assertEquals(initialRegionCount, UTIL.getAdmin().getRegions(tableName).size()); UTIL.waitUntilAllRegionsAssigned(tableName); List<HRegion> regions = UTIL.getMiniHBaseCluster().getRegions(tableName); assertEquals(initialRegionCount, regions.size()); }
@Test public void testMergeWithoutPONR() throws Exception { final TableName tableName = TableName.valueOf("testMergeWithoutPONR"); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); List<RegionInfo> tableRegions = createTable(tableName); ProcedureTestingUtility.waitNoProcedureRunning(procExec); ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); RegionInfo[] regionsToMerge = new RegionInfo[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); }
.getMaster().getMasterProcedureExecutor(); List<RegionInfo> regionInfos = admin.getRegions(TABLE_NAME); MergeTableRegionsProcedure mergeTableRegionsProcedure = new MergeTableRegionsProcedure( env, regionInfos.get(0), regionInfos.get(1)); executor.submitProcedure(mergeTableRegionsProcedure);
@Test public void test() throws Exception { TableDescriptor tableDescriptor = client.getDescriptor(); ProcedureExecutor<MasterProcedureEnv> executor = UTIL.getMiniHBaseCluster().getMaster() .getMasterProcedureExecutor(); MasterProcedureEnv env = executor.getEnvironment(); List<RegionInfo> regionInfos = admin.getRegions(TABLE_NAME); MergeTableRegionsProcedure mergeTableRegionsProcedure = new MergeTableRegionsProcedure( UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor() .getEnvironment(), regionInfos.get(0), regionInfos.get(1)); ModifyTableProcedure modifyTableProcedure = new ModifyTableProcedure(env, tableDescriptor); long procModify = executor.submitProcedure(modifyTableProcedure); UTIL.waitFor(30000, () -> executor.getProcedures().stream() .filter(p -> p instanceof ModifyTableProcedure) .map(p -> (ModifyTableProcedure) p) .anyMatch(p -> TABLE_NAME.equals(p.getTableName()))); long proc = executor.submitProcedure(mergeTableRegionsProcedure); UTIL.waitFor(3000000, () -> UTIL.getMiniHBaseCluster().getMaster() .getMasterProcedureExecutor().isFinished(procModify)); Assert.assertEquals("Modify Table procedure should success!", ProcedureProtos.ProcedureState.SUCCESS, modifyTableProcedure.getState()); }
long procId1 = procExec.submitProcedure(new MergeTableRegionsProcedure( procExec.getEnvironment(), regionsToMerge1, true)); long procId2 = procExec.submitProcedure(new MergeTableRegionsProcedure( procExec.getEnvironment(), regionsToMerge2, true)); ProcedureTestingUtility.waitProcedure(procExec, procId1);
@Test public void test() throws Exception { List<RegionInfo> regionInfos = admin.getRegions(TABLE_NAME); MergeTableRegionsProcedure mergeTableRegionsProcedure = new MergeTableRegionsProcedure( UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor() .getEnvironment(), regionInfos.get(0), regionInfos.get(1)); long procID = UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor() .submitProcedure(mergeTableRegionsProcedure); mergeCommitArrive.await(); UTIL.getMiniHBaseCluster().stopMaster(0); UTIL.getMiniHBaseCluster().startMaster(); //wait until master initialized UTIL.waitFor(30000, () -> UTIL.getMiniHBaseCluster().getMaster() != null && UTIL .getMiniHBaseCluster().getMaster().isInitialized()); UTIL.waitFor(30000, () -> UTIL.getMiniHBaseCluster().getMaster() .getMasterProcedureExecutor().isFinished(procID)); Assert.assertTrue("Found region RIT, that's impossible!", UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager() .getRegionsInTransition().size() == 0); }
@Test public void testRecoveryAndDoubleExecution() throws Exception { final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution"); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); List<RegionInfo> tableRegions = createTable(tableName); ProcedureTestingUtility.waitNoProcedureRunning(procExec); ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); RegionInfo[] regionsToMerge = new RegionInfo[2]; regionsToMerge[0] = tableRegions.get(0); regionsToMerge[1] = tableRegions.get(1); long procId = procExec.submitProcedure( new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true)); // Restart the executor and execute the step twice MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId); ProcedureTestingUtility.assertProcNotFailed(procExec, procId); assertRegionCount(tableName, initialRegionCount - 1); }
@Test public void testRollbackAndDoubleExecution() throws Exception { final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution"); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); List<RegionInfo> tableRegions = createTable(tableName); ProcedureTestingUtility.waitNoProcedureRunning(procExec); ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); RegionInfo[] regionsToMerge = new RegionInfo[2]; regionsToMerge[0] = tableRegions.get(0); regionsToMerge[1] = tableRegions.get(1); long procId = procExec.submitProcedure( new MergeTableRegionsProcedure(procExec.getEnvironment(), regionsToMerge, true)); // Failing before MERGE_TABLE_REGIONS_UPDATE_META we should trigger the rollback // NOTE: the 8 (number of MERGE_TABLE_REGIONS_UPDATE_META step) is // hardcoded, so you have to look at this test at least once when you add a new step. int lastStep = 8; MasterProcedureTestingUtility.testRollbackAndDoubleExecution(procExec, procId, lastStep, true); assertEquals(initialRegionCount, UTIL.getAdmin().getRegions(tableName).size()); UTIL.waitUntilAllRegionsAssigned(tableName); List<HRegion> regions = UTIL.getMiniHBaseCluster().getRegions(tableName); assertEquals(initialRegionCount, regions.size()); }
@Test public void testMergeWithoutPONR() throws Exception { final TableName tableName = TableName.valueOf("testMergeWithoutPONR"); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); List<RegionInfo> tableRegions = createTable(tableName); ProcedureTestingUtility.waitNoProcedureRunning(procExec); ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); RegionInfo[] regionsToMerge = new RegionInfo[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); }