/** * Process the response for this call. You need to have the lock on * {@link org.apache.hadoop.hbase.ipc.RpcServer.Connection#responseWriteLock} * * @param call the call * @return true if we proceed the call fully, false otherwise. * @throws IOException */ private boolean processResponse(final Call call) throws IOException { boolean error = true; try { // Send as much data as we can in the non-blocking fashion long numBytes = channelWrite(call.connection.channel, call.response); if (numBytes < 0) { throw new HBaseIOException("Error writing on the socket " + "for the call:" + call.toShortString()); } error = false; } finally { if (error) { LOG.debug(getName() + call.toShortString() + ": output error -- closing"); closeConnection(call.connection); } } if (!call.response.hasRemaining()) { call.done(); return true; } else { return false; // Socket can't take more, we will have to come back. } }
@Test (timeout=180000) public void testTruncatePerms() throws Exception { try { List<UserPermission> existingPerms = AccessControlClient.getUserPermissions( systemUserConnection, TEST_TABLE.getNameAsString()); assertTrue(existingPerms != null); assertTrue(existingPerms.size() > 1); TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE); TEST_UTIL.truncateTable(TEST_TABLE); TEST_UTIL.waitTableAvailable(TEST_TABLE); List<UserPermission> perms = AccessControlClient.getUserPermissions( systemUserConnection, TEST_TABLE.getNameAsString()); assertTrue(perms != null); assertEquals(existingPerms.size(), perms.size()); } catch (Throwable e) { throw new HBaseIOException(e); } }
@Test public void testNoNormalizationIfTooFewRegions() throws HBaseIOException { TableName testTable = TableName.valueOf("testSplitOfSmallRegion"); List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb")); hris.add(hri1); regionSizes.put(hri1.getRegionName(), 10); HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc")); hris.add(hri2); regionSizes.put(hri2.getRegionName(), 15); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); assertTrue(plans == null); }
@Test public void testNoNormalizationOnNormalizedCluster() throws HBaseIOException { TableName testTable = TableName.valueOf("testSplitOfSmallRegion"); List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb")); hris.add(hri1); regionSizes.put(hri1.getRegionName(), 10); HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc")); hris.add(hri2); regionSizes.put(hri2.getRegionName(), 15); HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd")); hris.add(hri3); regionSizes.put(hri3.getRegionName(), 8); HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee")); hris.add(hri4); regionSizes.put(hri4.getRegionName(), 10); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); assertTrue(plans == null); }
/** * Two responsibilities * - if the call is already completed (by another replica) stops the retries. * - set the location to the right region, depending on the replica. */ @Override public void prepare(final boolean reload) throws IOException { if (controller.isCanceled()) return; if (Thread.interrupted()) { throw new InterruptedIOException(); } if (reload || location == null) { RegionLocations rl = getRegionLocations(false, id, cConnection, tableName, get.getRow()); location = id < rl.size() ? rl.getRegionLocation(id) : null; } if (location == null || location.getServerName() == null) { // With this exception, there will be a retry. The location can be null for a replica // when the table is created or after a split. throw new HBaseIOException("There is no location for replica id #" + id); } ServerName dest = location.getServerName(); setStub(cConnection.getClient(dest)); }
@Override public void prepare(boolean reload) throws IOException { if (Thread.interrupted()) { throw new InterruptedIOException(); } if (reload || location == null) { location = getLocation(!reload); } if (location == null) { // With this exception, there will be a retry. throw new HBaseIOException(getExceptionMessage()); } this.setStub(connection.getAdmin(location.getServerName())); }
/** * Process the response for this call. You need to have the lock on * {@link org.apache.hadoop.hbase.ipc.RpcServer.Connection#responseWriteLock} * * @param call the call * @return true if we proceed the call fully, false otherwise. * @throws IOException */ private boolean processResponse(final Call call) throws IOException { boolean error = true; try { // Send as much data as we can in the non-blocking fashion long numBytes = channelWrite(call.connection.channel, call.response); if (numBytes < 0) { throw new HBaseIOException("Error writing on the socket " + "for the call:" + call.toShortString()); } error = false; } finally { if (error) { LOG.debug(getName() + call.toShortString() + ": output error -- closing"); closeConnection(call.connection); } } if (!call.response.hasRemaining()) { call.connection.decRpcCount(); // Say that we're done with this call. return true; } else { return false; // Socket can't take more, we will have to come back. } }
@Override public MoveRegionResponse moveRegion(RpcController controller, MoveRegionRequest req) throws ServiceException { final byte [] encodedRegionName = req.getRegion().getValue().toByteArray(); RegionSpecifierType type = req.getRegion().getType(); final byte [] destServerName = (req.hasDestServerName())? Bytes.toBytes(ProtobufUtil.toServerName(req.getDestServerName()).getServerName()):null; MoveRegionResponse mrr = MoveRegionResponse.newBuilder().build(); if (type != RegionSpecifierType.ENCODED_REGION_NAME) { LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.ENCODED_REGION_NAME + " actual: " + type); } try { move(encodedRegionName, destServerName); } catch (HBaseIOException ioe) { throw new ServiceException(ioe); } return mrr; }
/** * 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 HBaseIOException, MasterNotRunningException, ZooKeeperConnectionException { MasterKeepAliveConnection stub = connection.getKeepAliveMasterService(); try { MoveRegionRequest request = RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName); stub.moveRegion(null,request); } catch (ServiceException se) { IOException ioe = ProtobufUtil.getRemoteException(se); if (ioe instanceof HBaseIOException) { throw (HBaseIOException)ioe; } LOG.error("Unexpected exception: " + se + " from calling HMaster.moveRegion"); } catch (DeserializationException de) { LOG.error("Could not parse destination server name: " + de); } finally { stub.close(); } }
@Override public void initialize() throws HBaseIOException { Class<? extends LoadBalancer> delegatorKlass = conf.getClass(Constants.INDEX_BALANCER_DELEGATOR_CLASS, StochasticLoadBalancer.class, LoadBalancer.class); this.delegator = ReflectionUtils.newInstance(delegatorKlass, conf); this.delegator.setClusterStatus(clusterStatus); this.delegator.setMasterServices(this.master); try { HTableDescriptor desc = null; Map<String, HTableDescriptor> tableDescriptors = this.master.getTableDescriptors().getAll(); for (Entry<String, HTableDescriptor> entry : tableDescriptors.entrySet()) { desc = entry.getValue(); if (desc.getValue(Constants.INDEX_SPEC_KEY) != null) { addIndexedTable(desc.getTableName()); } } } catch (IOException e) { throw new HBaseIOException(e); } }
@Override public Map<ServerName, List<HRegionInfo>> roundRobinAssignment(List<HRegionInfo> regions, List<ServerName> servers) throws HBaseIOException { List<HRegionInfo> userRegions = new ArrayList<HRegionInfo>(1); List<HRegionInfo> indexRegions = new ArrayList<HRegionInfo>(1); for (HRegionInfo hri : regions) { seperateUserAndIndexRegion(hri, userRegions, indexRegions); } Map<ServerName, List<HRegionInfo>> bulkPlan = null; if (false == userRegions.isEmpty()) { bulkPlan = this.delegator.roundRobinAssignment(userRegions, servers); if (null == bulkPlan) { if (LOG.isDebugEnabled()) { LOG.debug("No region plan for user regions."); } return null; } synchronized (this.colocationInfo) { savePlan(bulkPlan); } } bulkPlan = prepareIndexRegionsPlan(indexRegions, bulkPlan, servers); return bulkPlan; }
@Override public Map<ServerName, List<HRegionInfo>> retainAssignment(Map<HRegionInfo, ServerName> regions, List<ServerName> servers) throws HBaseIOException { Map<HRegionInfo, ServerName> userRegionsMap = new ConcurrentHashMap<HRegionInfo, ServerName>(1); List<HRegionInfo> indexRegions = new ArrayList<HRegionInfo>(1); for (Entry<HRegionInfo, ServerName> e : regions.entrySet()) { seperateUserAndIndexRegion(e, userRegionsMap, indexRegions, servers); } Map<ServerName, List<HRegionInfo>> bulkPlan = null; if (false == userRegionsMap.isEmpty()) { bulkPlan = this.delegator.retainAssignment(userRegionsMap, servers); if (null == bulkPlan) { if (LOG.isDebugEnabled()) { LOG.debug("Empty region plan for user regions."); } return null; } synchronized (this.colocationInfo) { savePlan(bulkPlan); } } bulkPlan = prepareIndexRegionsPlan(indexRegions, bulkPlan, servers); return bulkPlan; }
public List<ServerName> generateFavoredNodes(RegionInfo hri) throws IOException { List<ServerName> favoredNodesForRegion = new ArrayList<>(FAVORED_NODES_NUM); ServerName primary = servers.get(random.nextInt(servers.size())); favoredNodesForRegion.add(ServerName.valueOf(primary.getHostAndPort(), ServerName.NON_STARTCODE)); Map<RegionInfo, ServerName> primaryRSMap = new HashMap<>(1); primaryRSMap.put(hri, primary); Map<RegionInfo, ServerName[]> secondaryAndTertiaryRSMap = placeSecondaryAndTertiaryRS(primaryRSMap); ServerName[] secondaryAndTertiaryNodes = secondaryAndTertiaryRSMap.get(hri); if (secondaryAndTertiaryNodes != null && secondaryAndTertiaryNodes.length == 2) { for (ServerName sn : secondaryAndTertiaryNodes) { favoredNodesForRegion.add(ServerName.valueOf(sn.getHostAndPort(), ServerName.NON_STARTCODE)); } return favoredNodesForRegion; } else { throw new HBaseIOException("Unable to generate secondary and tertiary favored nodes."); } }
public Map<RegionInfo, List<ServerName>> generateFavoredNodesRoundRobin( Map<ServerName, List<RegionInfo>> assignmentMap, List<RegionInfo> regions) throws IOException { if (regions.size() > 0) { if (canPlaceFavoredNodes()) { Map<RegionInfo, ServerName> primaryRSMap = new HashMap<>(); // Lets try to have an equal distribution for primary favored node placePrimaryRSAsRoundRobin(assignmentMap, primaryRSMap, regions); return generateFavoredNodes(primaryRSMap); } else { throw new HBaseIOException("Not enough nodes to generate favored nodes"); } } return null; }
/** * Create round-robin assigns. Use on table creation to distribute out regions across cluster. * @return AssignProcedures made out of the passed in <code>hris</code> and a call * to the balancer to populate the assigns with targets chosen using round-robin (default * balancer scheme). If at assign-time, the target chosen is no longer up, thats fine, * the AssignProcedure will ask the balancer for a new target, and so on. */ public AssignProcedure[] createRoundRobinAssignProcedures(final List<RegionInfo> hris) { if (hris.isEmpty()) { return null; } try { // Ask the balancer to assign our regions. Pass the regions en masse. The balancer can do // a better job if it has all the assignments in the one lump. Map<ServerName, List<RegionInfo>> assignments = getBalancer().roundRobinAssignment(hris, this.master.getServerManager().createDestinationServersList(null)); // Return mid-method! return createAssignProcedures(assignments, hris.size()); } catch (HBaseIOException hioe) { LOG.warn("Failed roundRobinAssignment", hioe); } // If an error above, fall-through to this simpler assign. Last resort. return createAssignProcedures(hris); }
public MoveRegionProcedure createMoveRegionProcedure(final RegionPlan plan) { if (plan.getRegionInfo().getTable().isSystemTable()) { List<ServerName> exclude = getExcludedServersForSystemTable(); if (plan.getDestination() != null && exclude.contains(plan.getDestination())) { try { LOG.info("Can not move " + plan.getRegionInfo() + " to " + plan.getDestination() + " because the server is not with highest version"); plan.setDestination(getBalancer().randomAssignment(plan.getRegionInfo(), this.master.getServerManager().createDestinationServersList(exclude))); } catch (HBaseIOException e) { LOG.warn(e.toString(), e); } } } return new MoveRegionProcedure(getProcedureEnvironment(), plan); }
@Test (timeout=180000) public void testTruncatePerms() throws Exception { try { List<UserPermission> existingPerms = AccessControlClient.getUserPermissions( systemUserConnection, TEST_TABLE.getNameAsString()); assertTrue(existingPerms != null); assertTrue(existingPerms.size() > 1); TEST_UTIL.getAdmin().disableTable(TEST_TABLE); TEST_UTIL.truncateTable(TEST_TABLE); TEST_UTIL.waitTableAvailable(TEST_TABLE); List<UserPermission> perms = AccessControlClient.getUserPermissions( systemUserConnection, TEST_TABLE.getNameAsString()); assertTrue(perms != null); assertEquals(existingPerms.size(), perms.size()); } catch (Throwable e) { throw new HBaseIOException(e); } }
/** * Test that abort is called when lockHeartbeat fails with IOException. */ @Test public void testHeartbeatException() throws Exception { final long workerSleepTime = 100; // in ms Abortable abortable = Mockito.mock(Abortable.class); EntityLock lock = admin.namespaceLock("namespace", "description", abortable); lock.setTestingSleepTime(workerSleepTime); when(master.requestLock(any(), any())) .thenReturn(LockResponse.newBuilder().setProcId(procId).build()); when(master.lockHeartbeat(any(), any())) .thenReturn(LOCKED_RESPONSE) .thenThrow(new ServiceException("Failed heartbeat!")); lock.requestLock(); lock.await(); assertTrue(waitLockTimeOut(lock, 100 * workerSleepTime)); while (lock.getWorker().isAlive()) { TimeUnit.MILLISECONDS.sleep(100); } verify(abortable, times(1)).abort(any(), isA(HBaseIOException.class)); assertFalse(lock.getWorker().isAlive()); }
@Test public void testNoNormalizationIfTooFewRegions() throws HBaseIOException { final TableName tableName = TableName.valueOf(name.getMethodName()); List<RegionInfo> RegionInfo = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); RegionInfo hri1 = RegionInfoBuilder.newBuilder(tableName) .setStartKey(Bytes.toBytes("aaa")) .setEndKey(Bytes.toBytes("bbb")) .build(); RegionInfo.add(hri1); regionSizes.put(hri1.getRegionName(), 10); RegionInfo hri2 = RegionInfoBuilder.newBuilder(tableName) .setStartKey(Bytes.toBytes("bbb")) .setEndKey(Bytes.toBytes("ccc")) .build(); RegionInfo.add(hri2); regionSizes.put(hri2.getRegionName(), 15); setupMocksForNormalizer(regionSizes, RegionInfo); List<NormalizationPlan> plans = normalizer.computePlanForTable(tableName); assertTrue(plans == null); }
@Override public Map<ServerName, List<RegionInfo>> roundRobinAssignment( List<RegionInfo> regions, List<ServerName> servers) throws HBaseIOException { Map<ServerName, List<RegionInfo>> assignments = Maps.newHashMap(); ListMultimap<String,RegionInfo> regionMap = ArrayListMultimap.create(); ListMultimap<String,ServerName> serverMap = ArrayListMultimap.create(); generateGroupMaps(regions, servers, regionMap, serverMap); for(String groupKey : regionMap.keySet()) { if (regionMap.get(groupKey).size() > 0) { Map<ServerName, List<RegionInfo>> result = this.internalBalancer.roundRobinAssignment( regionMap.get(groupKey), serverMap.get(groupKey)); if(result != null) { if(result.containsKey(LoadBalancer.BOGUS_SERVER_NAME) && assignments.containsKey(LoadBalancer.BOGUS_SERVER_NAME)){ assignments.get(LoadBalancer.BOGUS_SERVER_NAME).addAll( result.get(LoadBalancer.BOGUS_SERVER_NAME)); } else { assignments.putAll(result); } } } } return assignments; }
private void generateGroupMaps( List<RegionInfo> regions, List<ServerName> servers, ListMultimap<String, RegionInfo> regionMap, ListMultimap<String, ServerName> serverMap) throws HBaseIOException { try { for (RegionInfo region : regions) { String groupName = rsGroupInfoManager.getRSGroupOfTable(region.getTable()); if (groupName == null) { LOG.warn("Group for table "+region.getTable()+" is null"); } regionMap.put(groupName, region); } for (String groupKey : regionMap.keySet()) { RSGroupInfo info = rsGroupInfoManager.getRSGroup(groupKey); serverMap.putAll(groupKey, filterOfflineServers(info, servers)); if(serverMap.get(groupKey).size() < 1) { serverMap.put(groupKey, LoadBalancer.BOGUS_SERVER_NAME); } } } catch(IOException e) { throw new HBaseIOException("Failed to generate group maps", e); } }
@Override public void initialize() throws HBaseIOException { try { if (rsGroupInfoManager == null) { List<RSGroupAdminEndpoint> cps = masterServices.getMasterCoprocessorHost().findCoprocessors(RSGroupAdminEndpoint.class); if (cps.size() != 1) { String msg = "Expected one implementation of GroupAdminEndpoint but found " + cps.size(); LOG.error(msg); throw new HBaseIOException(msg); } rsGroupInfoManager = cps.get(0).getGroupInfoManager(); } } catch (IOException e) { throw new HBaseIOException("Failed to initialize GroupInfoManagerImpl", e); } // Create the balancer Class<? extends LoadBalancer> balancerKlass = config.getClass(HBASE_RSGROUP_LOADBALANCER_CLASS, StochasticLoadBalancer.class, LoadBalancer.class); internalBalancer = ReflectionUtils.newInstance(balancerKlass, config); internalBalancer.setMasterServices(masterServices); internalBalancer.setClusterMetrics(clusterStatus); internalBalancer.setConf(config); internalBalancer.initialize(); }
/** * Two responsibilities * - if the call is already completed (by another replica) stops the retries. * - set the location to the right region, depending on the replica. */ @Override // TODO: Very like the super class implemenation. Can we shrink this down? public void prepare(final boolean reload) throws IOException { if (getRpcController().isCanceled()) return; if (Thread.interrupted()) { throw new InterruptedIOException(); } if (reload || location == null) { RegionLocations rl = getRegionLocations(false, id, cConnection, tableName, get.getRow()); location = id < rl.size() ? rl.getRegionLocation(id) : null; } if (location == null || location.getServerName() == null) { // With this exception, there will be a retry. The location can be null for a replica // when the table is created or after a split. throw new HBaseIOException("There is no location for replica id #" + id); } setStubByServiceName(this.location.getServerName()); }
/** * @param reload force reload of server location * @throws IOException */ @Override public void prepare(boolean reload) throws IOException { if (Thread.interrupted()) { throw new InterruptedIOException(); } RegionLocations rl = RpcRetryingCallerWithReadReplicas.getRegionLocations(!reload, id, getConnection(), getTableName(), getRow()); location = id < rl.size() ? rl.getRegionLocation(id) : null; if (location == null || location.getServerName() == null) { // With this exception, there will be a retry. The location can be null for a replica // when the table is created or after a split. throw new HBaseIOException("There is no location for replica id #" + id); } ServerName dest = location.getServerName(); setStub(super.getConnection().getClient(dest)); if (!instantiated || reload) { checkIfRegionServerIsRemote(); instantiated = true; } cursor = null; // check how often we retry. if (reload) { incRPCRetriesMetrics(scanMetrics, isRegionServerRemote); } }
private void checkTableTypeAndThrowException(TableName name) throws IOException { if (name.isSystemTable()) { LOG.debug("Namespace auditor checks not performed for table " + name.getNameAsString()); } else { throw new HBaseIOException(name + " is being created even before namespace auditor has been initialized."); } }
@Test public void testNoNormalizationForMetaTable() throws HBaseIOException { TableName testTable = TableName.META_TABLE_NAME; List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); assertTrue(plans == null); }
@Test public void testMergeOfSmallRegions() throws HBaseIOException { TableName testTable = TableName.valueOf("testMergeOfSmallRegions"); List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb")); hris.add(hri1); regionSizes.put(hri1.getRegionName(), 15); HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc")); hris.add(hri2); regionSizes.put(hri2.getRegionName(), 5); HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd")); hris.add(hri3); regionSizes.put(hri3.getRegionName(), 5); HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee")); hris.add(hri4); regionSizes.put(hri4.getRegionName(), 15); HRegionInfo hri5 = new HRegionInfo(testTable, Bytes.toBytes("eee"), Bytes.toBytes("fff")); hris.add(hri5); regionSizes.put(hri5.getRegionName(), 16); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); NormalizationPlan plan = plans.get(0); assertTrue(plan instanceof MergeNormalizationPlan); assertEquals(hri2, ((MergeNormalizationPlan) plan).getFirstRegion()); assertEquals(hri3, ((MergeNormalizationPlan) plan).getSecondRegion()); }
@Test public void testMergeOfSecondSmallestRegions() throws HBaseIOException { TableName testTable = TableName.valueOf("testMergeOfSmallRegions"); List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb")); hris.add(hri1); regionSizes.put(hri1.getRegionName(), 1); HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc")); hris.add(hri2); regionSizes.put(hri2.getRegionName(), 10000); HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd")); hris.add(hri3); regionSizes.put(hri3.getRegionName(), 10000); HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee")); hris.add(hri4); regionSizes.put(hri4.getRegionName(), 10000); HRegionInfo hri5 = new HRegionInfo(testTable, Bytes.toBytes("eee"), Bytes.toBytes("fff")); hris.add(hri5); regionSizes.put(hri5.getRegionName(), 2700); HRegionInfo hri6 = new HRegionInfo(testTable, Bytes.toBytes("fff"), Bytes.toBytes("ggg")); hris.add(hri6); regionSizes.put(hri6.getRegionName(), 2700); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); NormalizationPlan plan = plans.get(0); assertTrue(plan instanceof MergeNormalizationPlan); assertEquals(hri5, ((MergeNormalizationPlan) plan).getFirstRegion()); assertEquals(hri6, ((MergeNormalizationPlan) plan).getSecondRegion()); }
@Test public void testMergeOfSmallNonAdjacentRegions() throws HBaseIOException { TableName testTable = TableName.valueOf("testMergeOfSmallRegions"); List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb")); hris.add(hri1); regionSizes.put(hri1.getRegionName(), 15); HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc")); hris.add(hri2); regionSizes.put(hri2.getRegionName(), 5); HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd")); hris.add(hri3); regionSizes.put(hri3.getRegionName(), 16); HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee")); hris.add(hri4); regionSizes.put(hri4.getRegionName(), 15); HRegionInfo hri5 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee")); hris.add(hri4); regionSizes.put(hri5.getRegionName(), 5); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); assertTrue(plans == null); }
@Test public void testSplitOfLargeRegion() throws HBaseIOException { TableName testTable = TableName.valueOf("testSplitOfLargeRegion"); List<HRegionInfo> hris = new ArrayList<>(); Map<byte[], Integer> regionSizes = new HashMap<>(); HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb")); hris.add(hri1); regionSizes.put(hri1.getRegionName(), 8); HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc")); hris.add(hri2); regionSizes.put(hri2.getRegionName(), 6); HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd")); hris.add(hri3); regionSizes.put(hri3.getRegionName(), 10); HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee")); hris.add(hri4); regionSizes.put(hri4.getRegionName(), 30); setupMocksForNormalizer(regionSizes, hris); List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable); NormalizationPlan plan = plans.get(0); assertTrue(plan instanceof SplitNormalizationPlan); assertEquals(hri4, ((SplitNormalizationPlan) plan).getRegionInfo()); }
/** * @param reload force reload of server location * @throws IOException */ @Override public void prepare(boolean reload) throws IOException { if (Thread.interrupted()) { throw new InterruptedIOException(); } RegionLocations rl = RpcRetryingCallerWithReadReplicas.getRegionLocations(!reload, id, getConnection(), getTableName(), getRow()); location = id < rl.size() ? rl.getRegionLocation(id) : null; if (location == null || location.getServerName() == null) { // With this exception, there will be a retry. The location can be null for a replica // when the table is created or after a split. throw new HBaseIOException("There is no location for replica id #" + id); } ServerName dest = location.getServerName(); setStub(super.getConnection().getClient(dest)); if (!instantiated || reload) { checkIfRegionServerIsRemote(); instantiated = true; } // check how often we retry. // HConnectionManager will call instantiateServer with reload==true // if and only if for retries. if (reload && this.scanMetrics != null) { this.scanMetrics.countOfRPCRetries.incrementAndGet(); if (isRegionServerRemote) { this.scanMetrics.countOfRemoteRPCRetries.incrementAndGet(); } } }
public HRegionLocation getLocation(boolean useCache) throws IOException { RegionLocations rl = getRegionLocations(connection, tableName, row, useCache, replicaId); if (rl == null) { throw new HBaseIOException(getExceptionMessage()); } HRegionLocation location = rl.getRegionLocation(replicaId); if (location == null) { throw new HBaseIOException(getExceptionMessage()); } return location; }
@Override protected void chore() { try { master.balance(); } catch (HBaseIOException e) { LOG.error("Failed to balance.", e); } }
public boolean balance() throws HBaseIOException { // if master not initialized, don't run balancer. if (!this.initialized) { LOG.debug("Master has not been initialized, don't run balancer."); return false; } return balanceInternals(); }
@Override public BalanceResponse balance(RpcController c, BalanceRequest request) throws ServiceException { try { return BalanceResponse.newBuilder().setBalancerRan(balance()).build(); } catch (HBaseIOException ex) { throw new ServiceException(ex); } }