@Test public void testMoveThrowsUnknownRegionException() throws IOException { TableName tableName = TableName.valueOf("testMoveThrowsUnknownRegionException"); HTableDescriptor htd = new HTableDescriptor(tableName); HColumnDescriptor hcd = new HColumnDescriptor("value"); htd.addFamily(hcd); admin.createTable(htd, null); try { HRegionInfo hri = new HRegionInfo( tableName, Bytes.toBytes("A"), Bytes.toBytes("Z")); admin.move(hri.getEncodedNameAsBytes(), null); fail("Region should not be moved since it is fake"); } catch (IOException ioe) { assertTrue(ioe instanceof UnknownRegionException); } finally { TEST_UTIL.deleteTable(tableName); } }
@Override public void assign(final byte [] regionName)throws IOException { checkInitialized(); Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); if (cpHost != null) { if (cpHost.preAssign(pair.getFirst())) { return; } } assignRegion(pair.getFirst()); if (cpHost != null) { cpHost.postAssign(pair.getFirst()); } }
@Override public void unassign(final byte [] regionName, final boolean force) throws IOException { checkInitialized(); Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); HRegionInfo hri = pair.getFirst(); if (cpHost != null) { if (cpHost.preUnassign(hri, force)) { return; } } if (force) { this.assignmentManager.regionOffline(hri); assignRegion(hri); } else { this.assignmentManager.unassign(hri, force); } if (cpHost != null) { cpHost.postUnassign(hri, force); } }
@Test (timeout=300000) public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception { final String name = this.name.getMethodName(); byte[] tableName = Bytes.toBytes(name); createTableWithDefaultConf(tableName); RegionInfo info = null; HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(tableName)); List<RegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); for (RegionInfo regionInfo : onlineRegions) { if (!regionInfo.isMetaRegion()) { if (regionInfo.getRegionNameAsString().contains(name)) { info = regionInfo; try { admin.unassign(Bytes.toBytes("sample"), true); } catch (UnknownRegionException nsre) { // expected, ignore it } } } } onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); assertTrue("The region should be present in online regions list.", onlineRegions.contains(info)); }
@Test public void testMoveThrowsUnknownRegionException() throws IOException { final TableName tableName = TableName.valueOf(name.getMethodName()); HTableDescriptor htd = new HTableDescriptor(tableName); HColumnDescriptor hcd = new HColumnDescriptor("value"); htd.addFamily(hcd); admin.createTable(htd, null); try { RegionInfo hri = RegionInfoBuilder.newBuilder(tableName) .setStartKey(Bytes.toBytes("A")) .setEndKey(Bytes.toBytes("Z")) .build(); admin.move(hri.getEncodedNameAsBytes(), null); fail("Region should not be moved since it is fake"); } catch (IOException ioe) { assertTrue(ioe instanceof UnknownRegionException); } finally { TEST_UTIL.deleteTable(tableName); } }
@Override public Future<Void> splitRegionAsync(byte[] regionName, byte[] splitPoint) throws IOException { byte[] encodedNameofRegionToSplit = HRegionInfo.isEncodedRegionName(regionName) ? regionName : Bytes.toBytes(HRegionInfo.encodeRegionName(regionName)); Pair<RegionInfo, ServerName> pair = getRegion(regionName); if (pair != null) { if (pair.getFirst() != null && pair.getFirst().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) { throw new IllegalArgumentException ("Can't invoke split on non-default regions directly"); } } else { throw new UnknownRegionException ( "Can't invoke merge on unknown region " + Bytes.toStringBinary(encodedNameofRegionToSplit)); } return splitRegionAsync(pair.getFirst(), splitPoint); }
@Override public void unassign(final byte [] regionName, final boolean force) throws IOException { Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); HRegionInfo hri = pair.getFirst(); if (cpHost != null) { if (cpHost.preUnassign(hri, force)) { return; } } if (force) { this.assignmentManager.clearRegionFromTransition(hri); assignRegion(hri); } else { this.assignmentManager.unassign(hri, force); } if (cpHost != null) { cpHost.postUnassign(hri, force); } }
/** * Move the region <code>r</code> to <code>dest</code>. * @param encodedRegionName The encoded region name; i.e. the hash that makes * up the region name suffix: e.g. if regionname is * <code>TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396.</code>, * then the encoded region name is: <code>527db22f95c8a9e0116f0cc13c680396</code>. * @param destServerName The servername of the destination regionserver. If * passed the empty byte array we'll assign to a random server. A server name * is made of host, port and startcode. Here is an example: * <code> host187.example.com,60020,1289493121758</code> * @throws UnknownRegionException Thrown if we can't find a region named * <code>encodedRegionName</code> * @throws ZooKeeperConnectionException * @throws MasterNotRunningException */ public void move(final byte [] encodedRegionName, final byte [] destServerName) throws UnknownRegionException, MasterNotRunningException, ZooKeeperConnectionException { MasterAdminKeepAliveConnection master = connection.getKeepAliveMasterAdmin(); try { MoveRegionRequest request = RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName); master.moveRegion(null,request); } catch (ServiceException se) { IOException ioe = ProtobufUtil.getRemoteException(se); if (ioe instanceof UnknownRegionException) { throw (UnknownRegionException)ioe; } LOG.error("Unexpected exception: " + se + " from calling HMaster.moveRegion"); } catch (DeserializationException de) { LOG.error("Could not parse destination server name: " + de); } finally { master.close(); } }
/** * Special method, only used by hbck. */ @Override public OfflineRegionResponse offlineRegion(RpcController controller, OfflineRegionRequest request) throws ServiceException { final byte [] regionName = request.getRegion().getValue().toByteArray(); RegionSpecifierType type = request.getRegion().getType(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } try { Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName)); HRegionInfo hri = pair.getFirst(); this.assignmentManager.regionOffline(hri); } catch (IOException ioe) { throw new ServiceException(ioe); } return OfflineRegionResponse.newBuilder().build(); }
@Override public AssignRegionResponse assignRegion(RpcController controller, AssignRegionRequest req) throws ServiceException { try { final byte [] regionName = req.getRegion().getValue().toByteArray(); RegionSpecifierType type = req.getRegion().getType(); AssignRegionResponse arr = AssignRegionResponse.newBuilder().build(); master.checkInitialized(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } RegionStates regionStates = master.assignmentManager.getRegionStates(); HRegionInfo regionInfo = regionStates.getRegionInfo(regionName); if (regionInfo == null) throw new UnknownRegionException(Bytes.toString(regionName)); if (master.cpHost != null) { if (master.cpHost.preAssign(regionInfo)) { return arr; } } LOG.info(master.getClientIdAuditPrefix() + " assign " + regionInfo.getRegionNameAsString()); master.assignmentManager.assign(regionInfo, true, true); if (master.cpHost != null) { master.cpHost.postAssign(regionInfo); } return arr; } catch (IOException ioe) { throw new ServiceException(ioe); } }
/** * Offline specified region from master's in-memory state. It will not attempt to * reassign the region as in unassign. * * This is a special method that should be used by experts or hbck. * */ @Override public OfflineRegionResponse offlineRegion(RpcController controller, OfflineRegionRequest request) throws ServiceException { final byte [] regionName = request.getRegion().getValue().toByteArray(); RegionSpecifierType type = request.getRegion().getType(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } try { master.checkInitialized(); Pair<HRegionInfo, ServerName> pair = MetaTableAccessor.getRegion(master.getConnection(), regionName); if (pair == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName)); HRegionInfo hri = pair.getFirst(); if (master.cpHost != null) { master.cpHost.preRegionOffline(hri); } LOG.info(master.getClientIdAuditPrefix() + " offline " + hri.getRegionNameAsString()); master.assignmentManager.regionOffline(hri); if (master.cpHost != null) { master.cpHost.postRegionOffline(hri); } } catch (IOException ioe) { throw new ServiceException(ioe); } return OfflineRegionResponse.newBuilder().build(); }
@Override public UnassignRegionResponse unassignRegion(RpcController controller, UnassignRegionRequest req) throws ServiceException { try { final byte [] regionName = req.getRegion().getValue().toByteArray(); RegionSpecifierType type = req.getRegion().getType(); final boolean force = req.getForce(); UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build(); master.checkInitialized(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } Pair<HRegionInfo, ServerName> pair = MetaTableAccessor.getRegion(master.getConnection(), regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); HRegionInfo hri = pair.getFirst(); if (master.cpHost != null) { if (master.cpHost.preUnassign(hri, force)) { return urr; } } LOG.debug(master.getClientIdAuditPrefix() + " unassign " + hri.getRegionNameAsString() + " in current location if it is online and reassign.force=" + force); master.assignmentManager.unassign(hri, force); if (master.assignmentManager.getRegionStates().isRegionOffline(hri)) { LOG.debug("Region " + hri.getRegionNameAsString() + " is not online on any region server, reassigning it."); master.assignRegion(hri); } if (master.cpHost != null) { master.cpHost.postUnassign(hri, force); } return urr; } catch (IOException ioe) { throw new ServiceException(ioe); } }
@Override public void move(final byte[] encodedRegionName, final byte[] destServerName) throws UnknownRegionException { Pair<HRegionInfo, ServerName> p = this.assignmentManager.getAssignment(encodedRegionName); if (p == null) throw new UnknownRegionException(Bytes.toStringBinary(encodedRegionName)); ServerName dest = null; if (destServerName == null || destServerName.length == 0) { LOG.info("Passed destination servername is null or empty so choosing a server at random"); List<ServerName> destServers = this.serverManager.getOnlineServersList(); destServers.remove(p.getSecond()); // If i have only one RS then destination can be null. dest = balancer.randomAssignment(destServers); } else { dest = new ServerName(Bytes.toString(destServerName)); } // Now we can do the move RegionPlan rp = new RegionPlan(p.getFirst(), p.getSecond(), dest); try { checkInitialized(); if (this.cpHost != null) { if (this.cpHost.preMove(p.getFirst(), p.getSecond(), dest)) { return; } } LOG.info("Added move plan " + rp + ", running balancer"); this.assignmentManager.balance(rp); if (this.cpHost != null) { this.cpHost.postMove(p.getFirst(), p.getSecond(), dest); } } catch (IOException ioe) { UnknownRegionException ure = new UnknownRegionException( Bytes.toStringBinary(encodedRegionName)); ure.initCause(ioe); throw ure; } }
/** * Special method, only used by hbck. */ @Override public void offline(final byte[] regionName) throws IOException { Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName)); HRegionInfo hri = pair.getFirst(); this.assignmentManager.regionOffline(hri); }
@Override public AssignRegionResponse assignRegion(RpcController controller, AssignRegionRequest req) throws ServiceException { try { final byte [] regionName = req.getRegion().getValue().toByteArray(); RegionSpecifierType type = req.getRegion().getType(); AssignRegionResponse arr = AssignRegionResponse.newBuilder().build(); checkInitialized(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } HRegionInfo regionInfo = assignmentManager.getRegionStates().getRegionInfo(regionName); if (regionInfo == null) throw new UnknownRegionException(Bytes.toString(regionName)); if (cpHost != null) { if (cpHost.preAssign(regionInfo)) { return arr; } } LOG.info(getClientIdAuditPrefix() + " assign " + regionInfo.getRegionNameAsString()); assignmentManager.assign(regionInfo, true, true); if (cpHost != null) { cpHost.postAssign(regionInfo); } return arr; } catch (IOException ioe) { throw new ServiceException(ioe); } }
@Override public UnassignRegionResponse unassignRegion(RpcController controller, UnassignRegionRequest req) throws ServiceException { try { final byte [] regionName = req.getRegion().getValue().toByteArray(); RegionSpecifierType type = req.getRegion().getType(); final boolean force = req.getForce(); UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build(); checkInitialized(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); HRegionInfo hri = pair.getFirst(); if (cpHost != null) { if (cpHost.preUnassign(hri, force)) { return urr; } } LOG.debug(getClientIdAuditPrefix() + " unassign " + hri.getRegionNameAsString() + " in current location if it is online and reassign.force=" + force); this.assignmentManager.unassign(hri, force); if (this.assignmentManager.getRegionStates().isRegionOffline(hri)) { LOG.debug("Region " + hri.getRegionNameAsString() + " is not online on any region server, reassigning it."); assignRegion(hri); } if (cpHost != null) { cpHost.postUnassign(hri, force); } return urr; } catch (IOException ioe) { throw new ServiceException(ioe); } }
/** * Offline specified region from master's in-memory state. It will not attempt to * reassign the region as in unassign. * * This is a special method that should be used by experts or hbck. * */ @Override public OfflineRegionResponse offlineRegion(RpcController controller, OfflineRegionRequest request) throws ServiceException { final byte [] regionName = request.getRegion().getValue().toByteArray(); RegionSpecifierType type = request.getRegion().getType(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } try { Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName)); HRegionInfo hri = pair.getFirst(); if (cpHost != null) { cpHost.preRegionOffline(hri); } LOG.info(getClientIdAuditPrefix() + " offline " + hri.getRegionNameAsString()); this.assignmentManager.regionOffline(hri); if (cpHost != null) { cpHost.postRegionOffline(hri); } } catch (IOException ioe) { throw new ServiceException(ioe); } return OfflineRegionResponse.newBuilder().build(); }
/** * Merge two regions. Asynchronous operation. * @param encodedNameOfRegionA encoded name of region a * @param encodedNameOfRegionB encoded name of region b * @param forcible true if do a compulsory merge, otherwise we will only merge * two adjacent regions * @throws IOException */ public void mergeRegions(final byte[] encodedNameOfRegionA, final byte[] encodedNameOfRegionB, final boolean forcible) throws IOException { MasterKeepAliveConnection master = connection .getKeepAliveMasterService(); try { DispatchMergingRegionsRequest request = RequestConverter .buildDispatchMergingRegionsRequest(encodedNameOfRegionA, encodedNameOfRegionB, forcible); master.dispatchMergingRegions(null, request); } catch (ServiceException se) { IOException ioe = ProtobufUtil.getRemoteException(se); if (ioe instanceof UnknownRegionException) { throw (UnknownRegionException) ioe; } if (ioe instanceof MergeRegionException) { throw (MergeRegionException) ioe; } LOG.error("Unexpected exception: " + se + " from calling HMaster.dispatchMergingRegions"); } catch (DeserializationException de) { LOG.error("Could not parse destination server name: " + de); } finally { master.close(); } }
private void collocateRowToDifferentRS(HBaseAdmin admin, HTable table, String rowKey) throws IOException, UnknownRegionException, MasterNotRunningException, ZooKeeperConnectionException { HRegionInfo regionInfo = table.getRegionLocation(rowKey).getRegionInfo(); int originServerNum = UTIL.getMiniHBaseCluster().getServerWith(regionInfo.getRegionName()); int targetServerNum = 3 - 1 - originServerNum; HRegionServer targetServer = UTIL.getMiniHBaseCluster().getRegionServer(targetServerNum); admin.move(regionInfo.getEncodedNameAsBytes(), Bytes.toBytes(targetServer.getServerName().getServerName())); Threads.sleep(10000); }
@Override public AssignRegionResponse assignRegion(RpcController controller, AssignRegionRequest req) throws ServiceException { try { master.checkInitialized(); final RegionSpecifierType type = req.getRegion().getType(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } final byte[] regionName = req.getRegion().getValue().toByteArray(); final RegionInfo regionInfo = master.getAssignmentManager().getRegionInfo(regionName); if (regionInfo == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName)); final AssignRegionResponse arr = AssignRegionResponse.newBuilder().build(); if (master.cpHost != null) { master.cpHost.preAssign(regionInfo); } LOG.info(master.getClientIdAuditPrefix() + " assign " + regionInfo.getRegionNameAsString()); master.getAssignmentManager().assign(regionInfo); if (master.cpHost != null) { master.cpHost.postAssign(regionInfo); } return arr; } catch (IOException ioe) { throw new ServiceException(ioe); } }
/** * Offline specified region from master's in-memory state. It will not attempt to * reassign the region as in unassign. * * This is a special method that should be used by experts or hbck. * */ @Override public OfflineRegionResponse offlineRegion(RpcController controller, OfflineRegionRequest request) throws ServiceException { try { master.checkInitialized(); final RegionSpecifierType type = request.getRegion().getType(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } final byte[] regionName = request.getRegion().getValue().toByteArray(); final RegionInfo hri = master.getAssignmentManager().getRegionInfo(regionName); if (hri == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName)); if (master.cpHost != null) { master.cpHost.preRegionOffline(hri); } LOG.info(master.getClientIdAuditPrefix() + " offline " + hri.getRegionNameAsString()); master.getAssignmentManager().offlineRegion(hri); if (master.cpHost != null) { master.cpHost.postRegionOffline(hri); } } catch (IOException ioe) { throw new ServiceException(ioe); } return OfflineRegionResponse.newBuilder().build(); }
@Override public UnassignRegionResponse unassignRegion(RpcController controller, UnassignRegionRequest req) throws ServiceException { try { final byte [] regionName = req.getRegion().getValue().toByteArray(); RegionSpecifierType type = req.getRegion().getType(); final boolean force = req.getForce(); UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build(); master.checkInitialized(); if (type != RegionSpecifierType.REGION_NAME) { LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME + " actual: " + type); } Pair<RegionInfo, ServerName> pair = MetaTableAccessor.getRegion(master.getConnection(), regionName); if (Bytes.equals(RegionInfoBuilder.FIRST_META_REGIONINFO.getRegionName(),regionName)) { pair = new Pair<>(RegionInfoBuilder.FIRST_META_REGIONINFO, master.getMetaTableLocator().getMetaRegionLocation(master.getZooKeeper())); } if (pair == null) { throw new UnknownRegionException(Bytes.toString(regionName)); } RegionInfo hri = pair.getFirst(); if (master.cpHost != null) { master.cpHost.preUnassign(hri, force); } LOG.debug(master.getClientIdAuditPrefix() + " unassign " + hri.getRegionNameAsString() + " in current location if it is online and reassign.force=" + force); master.getAssignmentManager().unassign(hri); if (master.cpHost != null) { master.cpHost.postUnassign(hri, force); } return urr; } catch (IOException ioe) { throw new ServiceException(ioe); } }
/** * Get the region location for the passed region name. The region name may be a full region name * or encoded region name. If the region does not found, then it'll throw an * UnknownRegionException wrapped by a {@link CompletableFuture} * @param regionNameOrEncodedRegionName * @return region location, wrapped by a {@link CompletableFuture} */ @VisibleForTesting CompletableFuture<HRegionLocation> getRegionLocation(byte[] regionNameOrEncodedRegionName) { if (regionNameOrEncodedRegionName == null) { return failedFuture(new IllegalArgumentException("Passed region name can't be null")); } try { CompletableFuture<Optional<HRegionLocation>> future; if (RegionInfo.isEncodedRegionName(regionNameOrEncodedRegionName)) { future = AsyncMetaTableAccessor.getRegionLocationWithEncodedName(metaTable, regionNameOrEncodedRegionName); } else { future = AsyncMetaTableAccessor.getRegionLocation(metaTable, regionNameOrEncodedRegionName); } CompletableFuture<HRegionLocation> returnedFuture = new CompletableFuture<>(); future.whenComplete((location, err) -> { if (err != null) { returnedFuture.completeExceptionally(err); return; } if (!location.isPresent() || location.get().getRegion() == null) { returnedFuture.completeExceptionally(new UnknownRegionException( "Invalid region name or encoded region name: " + Bytes.toStringBinary(regionNameOrEncodedRegionName))); } else { returnedFuture.complete(location.get()); } }); return returnedFuture; } catch (IOException e) { return failedFuture(e); } }
@Override public void move(final byte[] encodedRegionName, final byte[] destServerName) throws UnknownRegionException { Pair<HRegionInfo, ServerName> p = this.assignmentManager.getAssignment(encodedRegionName); if (p == null) throw new UnknownRegionException(Bytes.toStringBinary(encodedRegionName)); HRegionInfo hri = p.getFirst(); ServerName dest = null; if (destServerName == null || destServerName.length == 0) { LOG.info("Passed destination servername is null/empty so " + "choosing a server at random"); this.assignmentManager.clearRegionPlan(hri); // Unassign will reassign it elsewhere choosing random server. this.assignmentManager.unassign(hri); } else { dest = new ServerName(Bytes.toString(destServerName)); try { if (this.cpHost != null) { if (this.cpHost.preMove(p.getFirst(), p.getSecond(), dest)) { return; } } RegionPlan rp = new RegionPlan(p.getFirst(), p.getSecond(), dest); LOG.info("Added move plan " + rp + ", running balancer"); this.assignmentManager.balance(rp); if (this.cpHost != null) { this.cpHost.postMove(p.getFirst(), p.getSecond(), dest); } } catch (IOException ioe) { UnknownRegionException ure = new UnknownRegionException( Bytes.toStringBinary(encodedRegionName)); ure.initCause(ioe); throw ure; } } }