/** * Add a region to RegionStates with the specified state. If the region is already in * RegionStates, this call has no effect, and the original state is returned. * * @param hri the region info to create a state for * @param newState the state to the region in set to * @param serverName the server the region is transitioning on * @param lastHost the last server that hosts the region * @return the current state */ public synchronized RegionState createRegionState( final HRegionInfo hri, State newState, ServerName serverName, ServerName lastHost) { if (newState == null || (newState == State.OPEN && serverName == null)) { newState = State.OFFLINE; } if (hri.isOffline() && hri.isSplit()) { newState = State.SPLIT; serverName = null; } String encodedName = hri.getEncodedName(); RegionState regionState = regionStates.get(encodedName); if (regionState != null) { LOG.warn( "Tried to create a state for a region already in RegionStates, " + "used existing: " + regionState + ", ignored new: " + newState); } else { regionState = new RegionState(hri, newState, serverName); putRegionState(regionState); if (newState == State.OPEN) { if (!serverName.equals(lastHost)) { LOG.warn( "Open region's last host " + lastHost + " should be the same as the current one " + serverName + ", ignored the last and used the current one"); lastHost = serverName; } lastAssignments.put(encodedName, lastHost); regionAssignments.put(hri, lastHost); } else if (!isOneOfStates(regionState, State.MERGED, State.SPLIT, State.OFFLINE)) { regionsInTransition.put(encodedName, regionState); } if (lastHost != null && newState != State.SPLIT) { addToServerHoldings(lastHost, hri); if (newState != State.OPEN) { oldAssignments.put(encodedName, lastHost); } } } return regionState; }
/** Update a region state. It will be put in transition if not already there. */ private RegionState updateRegionState( final HRegionInfo hri, final RegionState.State state, final ServerName serverName, long openSeqNum) { if (state == RegionState.State.FAILED_CLOSE || state == RegionState.State.FAILED_OPEN) { LOG.warn( "Failed to open/close " + hri.getShortNameToLog() + " on " + serverName + ", set to " + state); } String encodedName = hri.getEncodedName(); RegionState regionState = new RegionState(hri, state, System.currentTimeMillis(), serverName); RegionState oldState = getRegionState(encodedName); if (!regionState.equals(oldState)) { LOG.info("Transition " + oldState + " to " + regionState); // Persist region state before updating in-memory info, if needed regionStateStore.updateRegionState(openSeqNum, regionState, oldState); } synchronized (this) { regionsInTransition.put(encodedName, regionState); putRegionState(regionState); // For these states, region should be properly closed. // There should be no log splitting issue. if ((state == State.CLOSED || state == State.MERGED || state == State.SPLIT) && lastAssignments.containsKey(encodedName)) { ServerName last = lastAssignments.get(encodedName); if (last.equals(serverName)) { lastAssignments.remove(encodedName); } else { LOG.warn(encodedName + " moved to " + state + " on " + serverName + ", expected " + last); } } // Once a region is opened, record its last assignment right away. if (serverName != null && state == State.OPEN) { ServerName last = lastAssignments.get(encodedName); if (!serverName.equals(last)) { lastAssignments.put(encodedName, serverName); if (last != null && isServerDeadAndNotProcessed(last)) { LOG.warn( encodedName + " moved to " + serverName + ", while it's previous host " + last + " is dead but not processed yet"); } } } // notify the change this.notifyAll(); } return regionState; }