diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java index 6d10327..3dd6a4f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java @@ -1066,7 +1066,7 @@ public class AssignmentManager extends ZooKeeperListener { // Close it without updating the internal region states, // so as not to create double assignments in unlucky scenarios // mentioned in OpenRegionHandler#process - unassign(regionState.getRegion(), null, -1, null, false, sn); + assignOrUnassignAfterhandleRegion(regionState, sn, expectedVersion); } return; } @@ -4223,4 +4223,86 @@ public class AssignmentManager extends ZooKeeperListener { public LoadBalancer getBalancer() { return this.balancer; } + + /** + * Close it without updating the internal region states, so as not to create double assignments in + * unlucky scenarios mentioned in OpenRegionHandler#process + */ + private void assignOrUnassignAfterhandleRegion(RegionState regionState, ServerName sn, + int expectedVersion) { + State state = regionState.getState(); + ServerName oldServer = regionState.getServerName(); + if (state.equals(State.OPEN)) {// state is opend in memory + try { + Boolean isonline = + serverManager.isRegionOnline(oldServer, regionState.getRegion().getRegionName());// Region + // is + // online or + // not in + // old + // ServerName + if (!isonline) {// isonline is false, region is not in + // oldServer,delete zk node ,update servername + LOG.debug("fiberhome: " + regionState.getRegion().getRegionNameAsString() + + " is not online in old Server, delete zk node ,update regionState"); + Boolean isonline_new = + serverManager.isRegionOnline(sn, regionState.getRegion().getRegionName()); + if (isonline_new) { + regionStates.updateRegionState(regionState.getRegion(), State.OPEN, sn); + new OpenedRegionHandler(server, this, regionState.getRegion(), sn, expectedVersion) + .process(); + } else { + unassign(regionState.getRegion(), null, -1, null, false, sn); + } + } else if (isonline && oldServer.equals(sn)) { + LOG.debug("fiberhome: " + regionState.getRegion().getRegionNameAsString() + + " is online in old Server, and old Server equals new Server, so don't do anything"); + new OpenedRegionHandler(server, this, regionState.getRegion(), sn, expectedVersion) + .process(); + // isonline is true, region is in + // oldServer,sn==oldserver,nothing + } else {// sn!=oldserver,double assignments,so unassign + // HBase-authority handle logic + + unassign(regionState.getRegion(), null, -1, null, false, sn); + } + } catch (IOException e) { + LOG.warn("fiberhome: " + "assignOrNotAfterhandleRegion error", e); + // HBase-authority handle logic + unassign(regionState.getRegion(), null, -1, null, false, sn); + } + } else if (state.equals(State.OFFLINE)) {// state is OFFLINE in memory + try { + Boolean isonline = + serverManager.isRegionOnline(sn, regionState.getRegion().getRegionName());// Region is + // online or + // not + // in new ServerName + // region + if (isonline) {// region is online in new Server, delete zk node + // ,update regionState + LOG.debug("fiberhome: " + regionState.getRegion().getRegionNameAsString() + + " is online in new Server, delete zk node ,update regionState"); + regionStates.updateRegionState(regionState.getRegion(), State.OPEN, sn); + new OpenedRegionHandler(server, this, regionState.getRegion(), sn, expectedVersion) + .process(); + } else {// re-assign + LOG.debug("fiberhome: " + regionState.getRegion().getRegionNameAsString() + + " is not online in new Server, so re-assign"); + if (getZKTable().isEnabledTable(regionState.getRegion().getTable())) { + assign(regionState.getRegion(), true); + } else { + unassign(regionState.getRegion(), null, -1, null, false, sn); + } + } + } catch (IOException e) { + LOG.warn("fiberhome: " + "assignOrNotAfterhandleRegion error", e); + // HBase-authority handle logic + unassign(regionState.getRegion(), null, -1, null, false, sn); + } + } else { + // HBase-authority handle logic + unassign(regionState.getRegion(), null, -1, null, false, sn); + } + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java index 6b2b00b..0f9ea74 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java @@ -40,6 +40,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ClockOutOfSyncException; import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.NotServingRegionException; import org.apache.hadoop.hbase.RegionLoad; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.ServerLoad; @@ -56,6 +57,8 @@ import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.RequestConverter; import org.apache.hadoop.hbase.protobuf.ResponseConverter; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService; +import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest; +import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionResponse; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.ServerInfo; @@ -1039,4 +1042,26 @@ public class ServerManager { deadservers.cleanAllPreviousInstances(serverName); } } + + /** + * isRegionOnline + */ + public boolean isRegionOnline(final ServerName server, byte[] regionName) throws IOException { + AdminService.BlockingInterface admin = getRsAdmin(server); + if (admin == null) { + LOG.warn("Attempting to send OPEN RPC to server " + server.toString() + + " failed because no RPC connection found to this server"); + return false; + } + GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(regionName); + try { + GetRegionInfoResponse response = admin.getRegionInfo(null, request); + if (response == null) return false; + HRegionInfo.convert(response.getRegionInfo()); + return true; + } catch (ServiceException se) { + if (ProtobufUtil.getRemoteException(se) instanceof NotServingRegionException) return false; + throw ProtobufUtil.getRemoteException(se); + } + } }