/** * Add the assign operation to the assignment queue. * The pending assignment operation will be processed, * and each region will be assigned by a server using the balancer. */ protected void queueAssign(final RegionStateNode regionNode) { regionNode.getProcedureEvent().suspend(); // TODO: quick-start for meta and the other sys-tables? assignQueueLock.lock(); try { pendingAssignQueue.add(regionNode); if (regionNode.isSystemTable() || pendingAssignQueue.size() == 1 || pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) { assignQueueFullCond.signal(); } } finally { assignQueueLock.unlock(); } }
private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions, final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException { final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()]; final long st = System.currentTimeMillis(); if (plan == null) { throw new HBaseIOException("unable to compute plans for regions=" + regions.size()); } if (plan.isEmpty()) return; int evcount = 0; for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) { final ServerName server = entry.getKey(); for (RegionInfo hri: entry.getValue()) { final RegionStateNode regionNode = regions.get(hri); regionNode.setRegionLocation(server); events[evcount++] = regionNode.getProcedureEvent(); } } ProcedureEvent.wakeEvents(getProcedureScheduler(), events); final long et = System.currentTimeMillis(); if (LOG.isTraceEnabled()) { LOG.trace("ASSIGN ACCEPT " + events.length + " -> " + StringUtils.humanTimeDiff(et - st)); } }
@Override public void remoteCallFailed(MasterProcedureEnv env, ServerName remote, IOException exception) { RegionStateNode regionNode = getRegionNode(env); regionNode.lock(); try { ProcedureEvent<?> event = regionNode.getProcedureEvent(); if (event.isReady()) { LOG.warn( "The procedure event of procedure {} for region {} to server {} is not suspended, " + "usually this should not happen, but anyway let's skip the following wake up code, ", this, region, targetServer); return; } LOG.warn("The remote operation {} for region {} to server {} failed", this, region, targetServer, exception); event.wake(env.getProcedureScheduler()); } finally { regionNode.unlock(); } }
public void serverCrashed(MasterProcedureEnv env, RegionStateNode regionNode, ServerName serverName) throws IOException { // Notice that, in this method, we do not change the procedure state, instead, we update the // region state in hbase:meta. This is because that, the procedure state change will not be // persisted until the region is woken up and finish one step, if we crash before that then the // information will be lost. So here we will update the region state in hbase:meta, and when the // procedure is woken up, it will process the error and jump to the correct procedure state. RegionStateTransitionState currentState = getCurrentState(); switch (currentState) { case REGION_STATE_TRANSITION_CLOSE: case REGION_STATE_TRANSITION_CONFIRM_CLOSED: case REGION_STATE_TRANSITION_CONFIRM_OPENED: // for these 3 states, the region may still be online on the crashed server env.getAssignmentManager().regionClosed(regionNode, false); if (currentState != RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE) { regionNode.getProcedureEvent().wake(env.getProcedureScheduler()); } break; default: // If the procedure is in other 2 states, then actually we should not arrive here, as we // know that the region is not online on any server, so we need to do nothing... But anyway // let's add a log here LOG.warn("{} received unexpected server crash call for region {} from {}", this, regionNode, serverName); } }
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()); }
regionNode.getProcedureEvent().wake(env.getProcedureScheduler());
ProcedureEvent<?> event = regionNode.getProcedureEvent(); try { env.getRemoteDispatcher().addOperationToNode(targetServer, this);
private void queueAssign(MasterProcedureEnv env, RegionStateNode regionNode) throws ProcedureSuspendedException { // Here the assumption is that, the region must be in CLOSED state, so the region location // will be null. And if we fail to open the region and retry here, the forceNewPlan will be // true, and also we will set the region location to null. boolean retain = false; if (!forceNewPlan) { if (assignCandidate != null) { retain = assignCandidate.equals(regionNode.getLastHost()); regionNode.setRegionLocation(assignCandidate); } else if (regionNode.getLastHost() != null) { retain = true; LOG.info("Setting lastHost as the region location {}", regionNode.getLastHost()); regionNode.setRegionLocation(regionNode.getLastHost()); } } LOG.info("Starting {}; {}; forceNewPlan={}, retain={}", this, regionNode.toShortString(), forceNewPlan, retain); env.getAssignmentManager().queueAssign(regionNode); setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_OPEN); if (regionNode.getProcedureEvent().suspendIfNotReady(this)) { throw new ProcedureSuspendedException(); } }
regionNode.getProcedureEvent().wake(env.getProcedureScheduler());