use of org.apache.hadoop.hbase.HRegionInfo in project hbase by apache.
the class AssignmentManager method waitForAssignment.
/**
* Waits until the specified region has completed assignment, or the deadline is reached.
* @param regionSet set of region to wait on. the set is modified and the assigned regions removed
* @param waitTillAllAssigned true if we should wait all the regions to be assigned
* @param deadline the timestamp after which the wait is aborted
* @return true if all the regions are assigned false otherwise.
* @throws InterruptedException
*/
protected boolean waitForAssignment(final Collection<HRegionInfo> regionSet, final boolean waitTillAllAssigned, final long deadline) throws InterruptedException {
// We're not synchronizing on regionsInTransition now because we don't use any iterator.
while (!regionSet.isEmpty() && !server.isStopped() && deadline > System.currentTimeMillis()) {
int failedOpenCount = 0;
Iterator<HRegionInfo> regionInfoIterator = regionSet.iterator();
while (regionInfoIterator.hasNext()) {
HRegionInfo hri = regionInfoIterator.next();
if (regionStates.isRegionOnline(hri) || regionStates.isRegionInState(hri, State.SPLITTING, State.SPLIT, State.MERGING, State.MERGED)) {
regionInfoIterator.remove();
} else if (regionStates.isRegionInState(hri, State.FAILED_OPEN)) {
failedOpenCount++;
}
}
if (!waitTillAllAssigned) {
// No need to wait, let assignment going on asynchronously
break;
}
if (!regionSet.isEmpty()) {
if (failedOpenCount == regionSet.size()) {
// all the regions we are waiting had an error on open.
break;
}
regionStates.waitForUpdate(100);
}
}
return regionSet.isEmpty();
}
use of org.apache.hadoop.hbase.HRegionInfo in project hbase by apache.
the class AssignmentManager method onRegionTransition.
/**
* Try to update some region states. If the state machine prevents
* such update, an error message is returned to explain the reason.
*
* It's expected that in each transition there should have just one
* region for opening/closing, 3 regions for splitting/merging.
* These regions should be on the server that requested the change.
*
* Region state machine. Only these transitions
* are expected to be triggered by a region server.
*
* On the state transition:
* (1) Open/Close should be initiated by master
* (a) Master sets the region to pending_open/pending_close
* in memory and hbase:meta after sending the request
* to the region server
* (b) Region server reports back to the master
* after open/close is done (either success/failure)
* (c) If region server has problem to report the status
* to master, it must be because the master is down or some
* temporary network issue. Otherwise, the region server should
* abort since it must be a bug. If the master is not accessible,
* the region server should keep trying until the server is
* stopped or till the status is reported to the (new) master
* (d) If region server dies in the middle of opening/closing
* a region, SSH picks it up and finishes it
* (e) If master dies in the middle, the new master recovers
* the state during initialization from hbase:meta. Region server
* can report any transition that has not been reported to
* the previous active master yet
* (2) Split/merge is initiated by region servers
* (a) To split a region, a region server sends a request
* to master to try to set a region to splitting, together with
* two daughters (to be created) to splitting new. If approved
* by the master, the splitting can then move ahead
* (b) To merge two regions, a region server sends a request to
* master to try to set the new merged region (to be created) to
* merging_new, together with two regions (to be merged) to merging.
* If it is ok with the master, the merge can then move ahead
* (c) Once the splitting/merging is done, the region server
* reports the status back to the master either success/failure.
* (d) Other scenarios should be handled similarly as for
* region open/close
*/
public String onRegionTransition(final ServerName serverName, final RegionStateTransition transition) {
TransitionCode code = transition.getTransitionCode();
HRegionInfo hri = HRegionInfo.convert(transition.getRegionInfo(0));
Lock lock = locker.acquireLock(hri.getEncodedName());
try {
RegionState current = regionStates.getRegionState(hri);
if (LOG.isDebugEnabled()) {
LOG.debug("Got transition " + code + " for " + (current != null ? current.toString() : hri.getShortNameToLog()) + " from " + serverName);
}
String errorMsg = null;
switch(code) {
case OPENED:
errorMsg = onRegionOpen(current, hri, serverName, transition);
break;
case FAILED_OPEN:
errorMsg = onRegionFailedOpen(current, hri, serverName);
break;
case CLOSED:
errorMsg = onRegionClosed(current, hri, serverName);
break;
case READY_TO_SPLIT:
try {
regionStateListener.onRegionSplit(hri);
errorMsg = onRegionReadyToSplit(current, hri, serverName, transition);
} catch (IOException exp) {
if (exp instanceof QuotaExceededException) {
server.getRegionNormalizer().planSkipped(hri, PlanType.SPLIT);
}
errorMsg = StringUtils.stringifyException(exp);
}
break;
case SPLIT_PONR:
errorMsg = onRegionSplitPONR(current, hri, serverName, transition);
break;
case SPLIT:
errorMsg = onRegionSplit(current, hri, serverName, transition);
break;
case SPLIT_REVERTED:
errorMsg = onRegionSplitReverted(current, hri, serverName, transition);
if (org.apache.commons.lang.StringUtils.isEmpty(errorMsg)) {
try {
regionStateListener.onRegionSplitReverted(hri);
} catch (IOException exp) {
LOG.warn(StringUtils.stringifyException(exp));
}
}
break;
case READY_TO_MERGE:
errorMsg = onRegionReadyToMerge(current, hri, serverName, transition);
break;
case MERGE_PONR:
errorMsg = onRegionMergePONR(current, hri, serverName, transition);
break;
case MERGED:
try {
errorMsg = onRegionMerged(current, hri, serverName, transition);
regionStateListener.onRegionMerged(hri);
} catch (IOException exp) {
errorMsg = StringUtils.stringifyException(exp);
}
break;
case MERGE_REVERTED:
errorMsg = onRegionMergeReverted(current, hri, serverName, transition);
break;
default:
errorMsg = "Unexpected transition code " + code;
}
if (errorMsg != null) {
LOG.info("Could not transition region from " + current + " on " + code + " by " + serverName + ": " + errorMsg);
}
return errorMsg;
} finally {
lock.unlock();
}
}
use of org.apache.hadoop.hbase.HRegionInfo in project hbase by apache.
the class AssignmentManager method onRegionSplitPONR.
private String onRegionSplitPONR(final RegionState current, final HRegionInfo hri, final ServerName serverName, final RegionStateTransition transition) {
// splitting_new state. To check RPC retry, we use server holding info.
if (current == null || !current.isSplittingOnServer(serverName)) {
return hri.getShortNameToLog() + " is not splitting on " + serverName;
}
final HRegionInfo a = HRegionInfo.convert(transition.getRegionInfo(1));
final HRegionInfo b = HRegionInfo.convert(transition.getRegionInfo(2));
RegionState rs_a = regionStates.getRegionState(a);
RegionState rs_b = regionStates.getRegionState(b);
// states, if so, they must be lost together
if (rs_a == null && rs_b == null) {
rs_a = regionStates.createRegionState(a, State.SPLITTING_NEW, serverName, null);
rs_b = regionStates.createRegionState(b, State.SPLITTING_NEW, serverName, null);
}
if (rs_a == null || !rs_a.isSplittingNewOnServer(serverName) || rs_b == null || !rs_b.isSplittingNewOnServer(serverName)) {
return "Some daughter is not known to be splitting on " + serverName + ", a=" + rs_a + ", b=" + rs_b;
}
// Just return in case of retrying
if (!regionStates.isRegionOnServer(hri, serverName)) {
return null;
}
try {
regionStates.splitRegion(hri, a, b, serverName);
processFavoredNodesForDaughters(hri, a, b);
} catch (IOException ioe) {
LOG.info("Failed to record split region " + hri.getShortNameToLog());
return "Failed to record the splitting in meta";
}
return null;
}
use of org.apache.hadoop.hbase.HRegionInfo in project hbase by apache.
the class AssignmentManager method cleanOutCrashedServerReferences.
/**
* Clean out crashed server removing any assignments.
* @param sn Server that went down.
* @return list of regions in transition on this server
*/
public List<HRegionInfo> cleanOutCrashedServerReferences(final ServerName sn) {
// Clean out any existing assignment plans for this server
synchronized (this.regionPlans) {
for (Iterator<Map.Entry<String, RegionPlan>> i = this.regionPlans.entrySet().iterator(); i.hasNext(); ) {
Map.Entry<String, RegionPlan> e = i.next();
ServerName otherSn = e.getValue().getDestination();
// The name will be null if the region is planned for a random assign.
if (otherSn != null && otherSn.equals(sn)) {
// Use iterator's remove else we'll get CME
i.remove();
}
}
}
List<HRegionInfo> rits = regionStates.serverOffline(sn);
for (Iterator<HRegionInfo> it = rits.iterator(); it.hasNext(); ) {
HRegionInfo hri = it.next();
String encodedName = hri.getEncodedName();
// We need a lock on the region as we could update it
Lock lock = locker.acquireLock(encodedName);
try {
RegionState regionState = regionStates.getRegionTransitionState(encodedName);
if (regionState == null || (regionState.getServerName() != null && !regionState.isOnServer(sn)) || !RegionStates.isOneOfStates(regionState, State.PENDING_OPEN, State.OPENING, State.FAILED_OPEN, State.FAILED_CLOSE, State.OFFLINE)) {
LOG.info("Skip " + regionState + " since it is not opening/failed_close" + " on the dead server any more: " + sn);
it.remove();
} else {
if (tableStateManager.isTableState(hri.getTable(), TableState.State.DISABLED, TableState.State.DISABLING)) {
regionStates.regionOffline(hri);
it.remove();
continue;
}
// Mark the region offline and assign it again by SSH
regionStates.updateRegionState(hri, State.OFFLINE);
}
} finally {
lock.unlock();
}
}
return rits;
}
use of org.apache.hadoop.hbase.HRegionInfo in project hbase by apache.
the class AssignmentManager method onRegionReadyToMerge.
private String onRegionReadyToMerge(final RegionState current, final HRegionInfo hri, final ServerName serverName, final RegionStateTransition transition) {
// If the region is in merge_new state, it could be an RPC retry.
if (current != null && !current.isMergingNewOnServer(serverName)) {
return "Merging daughter region already exists, p=" + current;
}
if (!((HMaster) server).getSplitOrMergeTracker().isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {
return "merge switch is off!";
}
// Just return in case of retrying
if (current != null) {
return null;
}
final HRegionInfo a = HRegionInfo.convert(transition.getRegionInfo(1));
final HRegionInfo b = HRegionInfo.convert(transition.getRegionInfo(2));
Set<String> encodedNames = new HashSet<>(2);
encodedNames.add(a.getEncodedName());
encodedNames.add(b.getEncodedName());
Map<String, Lock> locks = locker.acquireLocks(encodedNames);
try {
RegionState rs_a = regionStates.getRegionState(a);
RegionState rs_b = regionStates.getRegionState(b);
if (rs_a == null || !rs_a.isOpenedOnServer(serverName) || rs_b == null || !rs_b.isOpenedOnServer(serverName)) {
return "Some daughter is not in a state to merge on " + serverName + ", a=" + rs_a + ", b=" + rs_b;
}
regionStates.updateRegionState(a, State.MERGING);
regionStates.updateRegionState(b, State.MERGING);
regionStates.createRegionState(hri, State.MERGING_NEW, serverName, null);
return null;
} finally {
for (Lock lock : locks.values()) {
lock.unlock();
}
}
}
Aggregations