@Override protected boolean waitInitialized(MasterProcedureEnv env) { if (TableName.isMetaTableName(getTableName())) { return false; } // First we need meta to be loaded, and second, if meta is not online then we will likely to // fail when updating meta so we wait until it is assigned. AssignmentManager am = env.getAssignmentManager(); return am.waitMetaLoaded(this) || am.waitMetaAssigned(this, getRegion()); }
public static TransitRegionStateProcedure unassign(MasterProcedureEnv env, RegionInfo region) { return setOwner(env, new TransitRegionStateProcedure(env, region, null, false, RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE, RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED)); }
private boolean isOpening(RegionStateNode regionNode, ServerName serverName, TransitionCode code) { if (!regionNode.isInState(State.OPENING)) { LOG.warn("Received report {} transition from {} for {}, pid={}, but the region is not in" + " OPENING state, should be a retry, ignore", code, serverName, regionNode, getProcId()); return false; } if (getCurrentState() != REGION_STATE_TRANSITION_CONFIRM_OPENED) { LOG.warn( "Received report {} transition from {} for {}, pid={}," + " but the TRSP is not in {} state, should be a retry, ignore", code, serverName, regionNode, getProcId(), REGION_STATE_TRANSITION_CONFIRM_OPENED); return false; } return true; }
private void openRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException { ServerName loc = regionNode.getRegionLocation(); if (loc == null) { LOG.warn("No location specified for {}, jump back to state {} to get one", getRegion(), RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE); setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE); return; } env.getAssignmentManager().regionOpening(regionNode); addChildProcedure(new OpenRegionProcedure(getRegion(), loc)); setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED); }
@Override protected Flow executeFromState(MasterProcedureEnv env, RegionStateTransitionState state) throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { RegionStateNode regionNode = getRegionStateNode(env); if (regionNode.getProcedure() != this) { switch (state) { case REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE: queueAssign(env, regionNode); return Flow.HAS_MORE_STATE; case REGION_STATE_TRANSITION_OPEN: openRegion(env, regionNode); return Flow.HAS_MORE_STATE; case REGION_STATE_TRANSITION_CONFIRM_OPENED: return confirmOpened(env, regionNode); case REGION_STATE_TRANSITION_CLOSE: closeRegion(env, regionNode); return Flow.HAS_MORE_STATE; case REGION_STATE_TRANSITION_CONFIRM_CLOSED: return confirmClosed(env, regionNode); default: throw new UnsupportedOperationException("unhandled state=" + state); "by other Procedure or operator intervention", backoff / 1000, this, regionNode.toShortString(), e); setTimeout(Math.toIntExact(backoff)); setState(ProcedureProtos.ProcedureState.WAITING_TIMEOUT); skipPersistence(); throw new ProcedureSuspendedException();
RegionStateNode regionNode = regionNodes.get(i); TransitRegionStateProcedure proc = TransitRegionStateProcedure.unassign(env, regionNode.getRegionInfo()); if (regionNode.getProcedure() != null) { throw new HBaseIOException(
@VisibleForTesting static int compare(TransitRegionStateProcedure left, TransitRegionStateProcedure right) { if (left.getRegion().isMetaRegion()) { if (right.getRegion().isMetaRegion()) { return RegionInfo.COMPARATOR.compare(left.getRegion(), right.getRegion()); } return -1; } else if (right.getRegion().isMetaRegion()) { return +1; } if (left.getRegion().getTable().isSystemTable()) { if (right.getRegion().getTable().isSystemTable()) { return RegionInfo.COMPARATOR.compare(left.getRegion(), right.getRegion()); } return -1; } else if (right.getRegion().getTable().isSystemTable()) { return +1; } return RegionInfo.COMPARATOR.compare(left.getRegion(), right.getRegion()); }
public long assign(RegionInfo regionInfo, ServerName sn) throws IOException { // TODO: should we use getRegionStateNode? RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo); TransitRegionStateProcedure proc; regionNode.lock(); try { preTransitCheck(regionNode, STATES_EXPECTED_ON_ASSIGN); proc = TransitRegionStateProcedure.assign(getProcedureEnvironment(), regionInfo, sn); regionNode.setProcedure(proc); } finally { regionNode.unlock(); } ProcedureSyncWait.submitAndWaitProcedure(master.getMasterProcedureExecutor(), proc); return proc.getProcId(); }
private void reportTransitionOpen(MasterProcedureEnv env, RegionStateNode regionNode, ServerName serverName, long openSeqNum) throws IOException { if (!isOpening(regionNode, serverName, TransitionCode.OPENED)) { return; "Received report {} transition from {} for {}, pid={} but the new openSeqNum {}" + " is less than the current one {}, should be a retry, ignore", TransitionCode.OPENED, serverName, regionNode, getProcId(), openSeqNum, regionNode.getOpenSeqNum()); return; " should be a retry, ignore", TransitionCode.OPENED, serverName, regionNode, getProcId()); return; if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED) { ServerCrashProcedure.updateProgress(env, getParentProcId());
public long unassign(RegionInfo regionInfo) throws IOException { RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo); if (regionNode == null) { throw new UnknownRegionException("No RegionState found for " + regionInfo.getEncodedName()); } TransitRegionStateProcedure proc; regionNode.lock(); try { preTransitCheck(regionNode, STATES_EXPECTED_ON_UNASSIGN_OR_MOVE); proc = TransitRegionStateProcedure.unassign(getProcedureEnvironment(), regionInfo); regionNode.setProcedure(proc); } finally { regionNode.unlock(); } ProcedureSyncWait.submitAndWaitProcedure(master.getMasterProcedureExecutor(), proc); return proc.getProcId(); }
out.print( regionStateNode.getState() ); out.write("</td>\n <td>"); out.print( regionStateNode.getProcedure().getProcId() ); out.write("</td>\n <td>"); out.print( escapeXml(regionStateNode.getProcedure().getState().toString() + (regionStateNode.getProcedure().isBypass() ? "(Bypassed)" : "")) ); out.write("</td>\n </tr>\n "); for (RegionStateNode regionStateNode : rit) { out.write("\n "); out.print( regionStateNode.getProcedure().getProcId() ); out.write("<br>\n ");
@Test public void testRecoveryAndDoubleExecutionUnassignAndAssign() throws Exception { HMaster master = UTIL.getMiniHBaseCluster().getMaster(); MasterProcedureEnv env = master.getMasterProcedureExecutor().getEnvironment(); HRegion region = UTIL.getMiniHBaseCluster().getRegions(tableName).get(0); RegionInfo regionInfo = region.getRegionInfo(); long openSeqNum = region.getOpenSeqNum(); TransitRegionStateProcedure unassign = TransitRegionStateProcedure.unassign(env, regionInfo); testRecoveryAndDoubleExcution(unassign); AssignmentManager am = master.getAssignmentManager(); assertTrue(am.getRegionStates().getRegionState(regionInfo).isClosed()); TransitRegionStateProcedure assign = TransitRegionStateProcedure.assign(env, regionInfo, null); testRecoveryAndDoubleExcution(assign); HRegion region2 = UTIL.getMiniHBaseCluster().getRegions(tableName).get(0); long openSeqNum2 = region2.getOpenSeqNum(); // confirm that the region is successfully opened assertTrue(openSeqNum2 > openSeqNum); } }
continue; proc = TransitRegionStateProcedure.reopen(env, regionNode.getRegionInfo()); regionNode.setProcedure(proc); } finally {
private void reportTransitionFailedOpen(MasterProcedureEnv env, RegionStateNode regionNode, ServerName serverName) { if (!isOpening(regionNode, serverName, TransitionCode.FAILED_OPEN)) { return; } // there is no openSeqNum for FAILED_OPEN, so we will check the target server instead if (!regionNode.getRegionLocation().equals(serverName)) { LOG.warn( "Received report {} transition from {} for {}, pid={}," + " but the region is not on it, should be a retry, ignore", TransitionCode.FAILED_OPEN, regionNode, serverName, getProcId()); return; } // just wake up the procedure and see if we can retry // Notice that, even if we arrive here, this call could still be a retry, as we may retry // opening on the same server again. And the assumption here is that, once the region state is // OPENING, and the TRSP state is REGION_STATE_TRANSITION_CONFIRM_OPENED, the TRSP must have // been suspended on the procedure event, so after the waking operation here, the TRSP will be // executed and try to schedule new OpenRegionProcedure again. Once there is a successful open // then we are done, so the TRSP will not be stuck. // TODO: maybe we could send the procedure id of the OpenRegionProcedure to the region server // and let the region server send it back when done, so it will be easy to detect whether this // is a retry. regionNode.getProcedureEvent().wake(env.getProcedureScheduler()); }
setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE); return Flow.HAS_MORE_STATE; setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE); throw new HBaseIOException("Failed to close region"); if (!RegionReplicaUtil.isDefaultReplica(getRegion()) && lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) { regionNode.unsetProcedure(this); setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE); return Flow.HAS_MORE_STATE;
if (regionNode.getProcedure() != null) { LOG.info("{} found RIT {}; {}", this, regionNode.getProcedure(), regionNode); regionNode.getProcedure().serverCrashed(env, regionNode, getServerName()); } else { if (env.getMasterServices().getTableStateManager().isTableState(regionNode.getTable(), continue; TransitRegionStateProcedure proc = TransitRegionStateProcedure.assign(env, region, null); regionNode.setProcedure(proc); addChildProcedure(proc);
IdLock procExecLock = procExec.getProcExecutionLock(); IdLock.Entry lockEntry = procExecLock.getLockEntry(proc.getProcId() + 2); () -> proc.getCurrentStateId() == REGION_STATE_TRANSITION_CONFIRM_OPENED_VALUE);
private TransitRegionStateProcedure createMoveRegionProcedure(RegionInfo regionInfo, ServerName targetServer) throws HBaseIOException { RegionStateNode regionNode = this.regionStates.getRegionStateNode(regionInfo); if (regionNode == null) { throw new UnknownRegionException("No RegionState found for " + regionInfo.getEncodedName()); } TransitRegionStateProcedure proc; regionNode.lock(); try { preTransitCheck(regionNode, STATES_EXPECTED_ON_UNASSIGN_OR_MOVE); regionNode.checkOnline(); proc = TransitRegionStateProcedure.move(getProcedureEnvironment(), regionInfo, targetServer); regionNode.setProcedure(proc); } finally { regionNode.unlock(); } return proc; }
.map(regionNode -> { TransitRegionStateProcedure proc = TransitRegionStateProcedure.assign(env, regionNode.getRegionInfo(), targetServer); regionNode.lock(); try {