public OpenRegionResponse openRegion(final RpcController controller,
final OpenRegionRequest request) throws ServiceException {
try {
checkOpen();
} catch (IOException ie) {
throw new ServiceException(ie);
}
requestCount.increment();
OpenRegionResponse.Builder builder = OpenRegionResponse.newBuilder();
final int regionCount = request.getOpenInfoCount();
final Map<TableName, HTableDescriptor> htds =
new HashMap<TableName, HTableDescriptor>(regionCount);
final boolean isBulkAssign = regionCount > 1;
for (RegionOpenInfo regionOpenInfo : request.getOpenInfoList()) {
final HRegionInfo region = HRegionInfo.convert(regionOpenInfo.getRegion());
int versionOfOfflineNode = -1;
if (regionOpenInfo.hasVersionOfOfflineNode()) {
versionOfOfflineNode = regionOpenInfo.getVersionOfOfflineNode();
}
HTableDescriptor htd;
try {
final HRegion onlineRegion = getFromOnlineRegions(region.getEncodedName());
if (onlineRegion != null) {
//Check if the region can actually be opened.
if (onlineRegion.getCoprocessorHost() != null) {
onlineRegion.getCoprocessorHost().preOpen();
}
// See HBASE-5094. Cross check with hbase:meta if still this RS is owning
// the region.
Pair<HRegionInfo, ServerName> p = MetaReader.getRegion(
this.catalogTracker, region.getRegionName());
if (this.getServerName().equals(p.getSecond())) {
Boolean closing = regionsInTransitionInRS.get(region.getEncodedNameAsBytes());
// Map regionsInTransitionInRSOnly has an entry for a region only if the region
// is in transition on this RS, so here closing can be null. If not null, it can
// be true or false. True means the region is opening on this RS; while false
// means the region is closing. Only return ALREADY_OPENED if not closing (i.e.
// not in transition any more, or still transition to open.
if (!Boolean.FALSE.equals(closing)
&& getFromOnlineRegions(region.getEncodedName()) != null) {
LOG.warn("Attempted open of " + region.getEncodedName()
+ " but already online on this server");
builder.addOpeningState(RegionOpeningState.ALREADY_OPENED);
continue;
}
} else {
LOG.warn("The region " + region.getEncodedName() + " is online on this server" +
" but hbase:meta does not have this server - continue opening.");
removeFromOnlineRegions(onlineRegion, null);
}
}
LOG.info("Open " + region.getRegionNameAsString());
htd = htds.get(region.getTable());
if (htd == null) {
htd = this.tableDescriptors.get(region.getTable());
htds.put(region.getTable(), htd);
}
final Boolean previous = this.regionsInTransitionInRS.putIfAbsent(
region.getEncodedNameAsBytes(), Boolean.TRUE);
if (Boolean.FALSE.equals(previous)) {
// There is a close in progress. We need to mark this open as failed in ZK.
OpenRegionHandler.
tryTransitionFromOfflineToFailedOpen(this, region, versionOfOfflineNode);
throw new RegionAlreadyInTransitionException("Received OPEN for the region:" +
region.getRegionNameAsString() + " , which we are already trying to CLOSE ");
}
if (Boolean.TRUE.equals(previous)) {
// An open is in progress. This is supported, but let's log this.
LOG.info("Receiving OPEN for the region:" +
region.getRegionNameAsString() + " , which we are already trying to OPEN" +
" - ignoring this new request for this region.");
}
// We are opening this region. If it moves back and forth for whatever reason, we don't
// want to keep returning the stale moved record while we are opening/if we close again.
removeFromMovedRegions(region.getEncodedName());
if (previous == null) {
// check if the region to be opened is marked in recovering state in ZK
if (this.distributedLogReplay
&& SplitLogManager.isRegionMarkedRecoveringInZK(this.getZooKeeper(),
region.getEncodedName())) {
this.recoveringRegions.put(region.getEncodedName(), null);
}
// If there is no action in progress, we can submit a specific handler.
// Need to pass the expected version in the constructor.
if (region.isMetaRegion()) {
this.service.submit(new OpenMetaHandler(this, this, region, htd,
versionOfOfflineNode));
} else {
updateRegionFavoredNodesMapping(region.getEncodedName(),
regionOpenInfo.getFavoredNodesList());
this.service.submit(new OpenRegionHandler(this, this, region, htd,
versionOfOfflineNode));
}
}
builder.addOpeningState(RegionOpeningState.OPENED);
} catch (KeeperException zooKeeperEx) {
LOG.error("Can't retrieve recovering state from zookeeper", zooKeeperEx);
throw new ServiceException(zooKeeperEx);
} catch (IOException ie) {
LOG.warn("Failed opening region " + region.getRegionNameAsString(), ie);
if (isBulkAssign) {
builder.addOpeningState(RegionOpeningState.FAILED_OPENING);
} else {
throw new ServiceException(ie);
}
}
}
return builder.build();