Example #1
0
  /**
   * Get the HRegionInfo from cache, if not there, from the hbase:meta table. Be careful. Does RPC.
   * Do not hold a lock or synchronize when you call this method.
   *
   * @param regionName
   * @return HRegionInfo for the region
   */
  @SuppressWarnings("deprecation")
  protected HRegionInfo getRegionInfo(final byte[] regionName) {
    String encodedName = HRegionInfo.encodeRegionName(regionName);
    RegionState regionState = getRegionState(encodedName);
    if (regionState != null) {
      return regionState.getRegion();
    }

    try {
      Pair<HRegionInfo, ServerName> p =
          MetaTableAccessor.getRegion(server.getConnection(), regionName);
      HRegionInfo hri = p == null ? null : p.getFirst();
      if (hri != null) {
        createRegionState(hri);
      }
      return hri;
    } catch (IOException e) {
      server.abort(
          "Aborting because error occoured while reading "
              + Bytes.toStringBinary(regionName)
              + " from hbase:meta",
          e);
      return null;
    }
  }
Example #2
0
 /**
  * A table is deleted. Remove its regions from all internal maps. We loop through all regions
  * assuming we don't delete tables too much.
  */
 public void tableDeleted(final TableName tableName) {
   Set<HRegionInfo> regionsToDelete = new HashSet<HRegionInfo>();
   synchronized (this) {
     for (RegionState state : regionStates.values()) {
       HRegionInfo region = state.getRegion();
       if (region.getTable().equals(tableName)) {
         regionsToDelete.add(region);
       }
     }
   }
   for (HRegionInfo region : regionsToDelete) {
     deleteRegion(region);
   }
 }
Example #3
0
 /**
  * Gets current state of all regions of the table. This method looks at the in-memory state. It
  * does not go to <code>hbase:meta</code>. Method guaranteed to return keys for all states in
  * {@link org.apache.hadoop.hbase.master.RegionState.State}
  *
  * @param tableName
  * @return Online regions from <code>tableName</code>
  */
 public synchronized Map<RegionState.State, List<HRegionInfo>> getRegionByStateOfTable(
     TableName tableName) {
   Map<RegionState.State, List<HRegionInfo>> tableRegions =
       new HashMap<State, List<HRegionInfo>>();
   for (State state : State.values()) {
     tableRegions.put(state, new ArrayList<HRegionInfo>());
   }
   Map<String, RegionState> indexMap = regionStatesTableIndex.get(tableName);
   if (indexMap == null) return tableRegions;
   for (RegionState regionState : indexMap.values()) {
     tableRegions.get(regionState.getState()).add(regionState.getRegion());
   }
   return tableRegions;
 }
Example #4
0
 /**
  * A region is offline, won't be in transition any more. Its state should be the specified
  * expected state, which can only be Split/Merged/Offline/null(=Offline)/SplittingNew/MergingNew.
  */
 public void regionOffline(final HRegionInfo hri, final State expectedState) {
   Preconditions.checkArgument(
       expectedState == null || RegionState.isUnassignable(expectedState),
       "Offlined region should not be " + expectedState);
   if (isRegionInState(hri, State.SPLITTING_NEW, State.MERGING_NEW)) {
     // Remove it from all region maps
     deleteRegion(hri);
     return;
   }
   State newState = expectedState == null ? State.OFFLINE : expectedState;
   updateRegionState(hri, newState);
   String encodedName = hri.getEncodedName();
   synchronized (this) {
     regionsInTransition.remove(encodedName);
     ServerName oldServerName = regionAssignments.remove(hri);
     if (oldServerName != null && serverHoldings.containsKey(oldServerName)) {
       if (newState == State.MERGED
           || newState == State.SPLIT
           || hri.isMetaRegion()
           || tableStateManager.isTableState(
               hri.getTable(), TableState.State.DISABLED, TableState.State.DISABLING)) {
         // Offline the region only if it's merged/split, or the table is disabled/disabling.
         // Otherwise, offline it from this server only when it is online on a different server.
         LOG.info("Offlined " + hri.getShortNameToLog() + " from " + oldServerName);
         removeFromServerHoldings(oldServerName, hri);
         removeFromReplicaMapping(hri);
       } else {
         // Need to remember it so that we can offline it from this
         // server when it is online on a different server.
         oldAssignments.put(encodedName, oldServerName);
       }
     }
   }
 }
Example #5
0
 static boolean isOneOfStates(RegionState regionState, State... states) {
   State s = regionState != null ? regionState.getState() : null;
   for (State state : states) {
     if (s == state) return true;
   }
   return false;
 }
Example #6
0
 /**
  * At cluster clean re/start, mark all user regions closed except those of tables that are
  * excluded, such as disabled/disabling/enabling tables. All user regions and their previous
  * locations are returned.
  */
 synchronized Map<HRegionInfo, ServerName> closeAllUserRegions(Set<TableName> excludedTables) {
   boolean noExcludeTables = excludedTables == null || excludedTables.isEmpty();
   Set<HRegionInfo> toBeClosed = new HashSet<HRegionInfo>(regionStates.size());
   for (RegionState state : regionStates.values()) {
     HRegionInfo hri = state.getRegion();
     if (state.isSplit() || hri.isSplit()) {
       continue;
     }
     TableName tableName = hri.getTable();
     if (!TableName.META_TABLE_NAME.equals(tableName)
         && (noExcludeTables || !excludedTables.contains(tableName))) {
       toBeClosed.add(hri);
     }
   }
   Map<HRegionInfo, ServerName> allUserRegions =
       new HashMap<HRegionInfo, ServerName>(toBeClosed.size());
   for (HRegionInfo hri : toBeClosed) {
     RegionState regionState = updateRegionState(hri, State.CLOSED);
     allUserRegions.put(hri, regionState.getServerName());
   }
   return allUserRegions;
 }
Example #7
0
 private RegionState putRegionState(RegionState regionState) {
   HRegionInfo hri = regionState.getRegion();
   String encodedName = hri.getEncodedName();
   TableName table = hri.getTable();
   RegionState oldState = regionStates.put(encodedName, regionState);
   Map<String, RegionState> map = regionStatesTableIndex.get(table);
   if (map == null) {
     map = new HashMap<String, RegionState>();
     regionStatesTableIndex.put(table, map);
   }
   map.put(encodedName, regionState);
   return oldState;
 }
Example #8
0
 @Override
 public int compare(RegionState l, RegionState r) {
   return Long.compare(l.getStamp(), r.getStamp());
 }
Example #9
0
  /** A server is offline, all regions on it are dead. */
  public List<HRegionInfo> serverOffline(final ServerName sn) {
    // Offline all regions on this server not already in transition.
    List<HRegionInfo> rits = new ArrayList<HRegionInfo>();
    Set<HRegionInfo> regionsToCleanIfNoMetaEntry = new HashSet<HRegionInfo>();
    // Offline regions outside the loop and synchronized block to avoid
    // ConcurrentModificationException and deadlock in case of meta anassigned,
    // but RegionState a blocked.
    Set<HRegionInfo> regionsToOffline = new HashSet<HRegionInfo>();
    synchronized (this) {
      Set<HRegionInfo> assignedRegions = serverHoldings.get(sn);
      if (assignedRegions == null) {
        assignedRegions = new HashSet<HRegionInfo>();
      }

      for (HRegionInfo region : assignedRegions) {
        // Offline open regions, no need to offline if SPLIT/MERGED/OFFLINE
        if (isRegionOnline(region)) {
          regionsToOffline.add(region);
        } else if (isRegionInState(region, State.SPLITTING, State.MERGING)) {
          LOG.debug("Offline splitting/merging region " + getRegionState(region));
          regionsToOffline.add(region);
        }
      }

      for (RegionState state : regionsInTransition.values()) {
        HRegionInfo hri = state.getRegion();
        if (assignedRegions.contains(hri)) {
          // Region is open on this region server, but in transition.
          // This region must be moving away from this server, or splitting/merging.
          // SSH will handle it, either skip assigning, or re-assign.
          LOG.info("Transitioning " + state + " will be handled by ServerCrashProcedure for " + sn);
        } else if (sn.equals(state.getServerName())) {
          // Region is in transition on this region server, and this
          // region is not open on this server. So the region must be
          // moving to this server from another one (i.e. opening or
          // pending open on this server, was open on another one.
          // Offline state is also kind of pending open if the region is in
          // transition. The region could be in failed_close state too if we have
          // tried several times to open it while this region server is not reachable)
          if (isOneOfStates(
              state,
              State.OPENING,
              State.PENDING_OPEN,
              State.FAILED_OPEN,
              State.FAILED_CLOSE,
              State.OFFLINE)) {
            LOG.info(
                "Found region in " + state + " to be reassigned by ServerCrashProcedure for " + sn);
            rits.add(hri);
          } else if (isOneOfStates(state, State.SPLITTING_NEW)) {
            regionsToCleanIfNoMetaEntry.add(state.getRegion());
          } else {
            LOG.warn("THIS SHOULD NOT HAPPEN: unexpected " + state);
          }
        }
      }
      this.notifyAll();
    }

    for (HRegionInfo hri : regionsToOffline) {
      regionOffline(hri);
    }

    cleanIfNoMetaEntry(regionsToCleanIfNoMetaEntry);
    return rits;
  }
Example #10
0
 /** Update a region state. It will be put in transition if not already there. */
 public RegionState updateRegionState(final HRegionInfo hri, final State state) {
   RegionState regionState = getRegionState(hri.getEncodedName());
   return updateRegionState(hri, state, regionState == null ? null : regionState.getServerName());
 }
Example #11
0
 /** @return True if hbase:meta table region is in transition. */
 public synchronized boolean isMetaRegionInTransition() {
   for (RegionState state : regionsInTransition.values()) {
     if (state.getRegion().isMetaRegion()) return true;
   }
   return false;
 }
Example #12
0
  /** 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;
  }