From 6765f5e203d0930e6305c1ba9aa8762e80fcbc8e Mon Sep 17 00:00:00 2001 From: Balazs Meszaros Date: Tue, 10 Oct 2017 09:24:51 +0200 Subject: [PATCH] HBASE-18350 RSGroups are broken under AMv2 - Table moving to RSG was buggy, because it left the table unassigned. Now it is fixed we immediately assign to an appropriate RS (MoveRegionProcedure). - Table was locked while moving, but unassign operation hung, because locked table queues are not scheduled while locked. Fixed. - ProcedureSyncWait was buggy, because it searched the procId in executor, but executor does not store the return values of internal operations (they are stored, but immediately removed by the cleaner). - list_rsgroups in the shell show also the assigned tables and servers. Signed-off-by: Michael Stack --- .../hbase/rsgroup/RSGroupAdminServer.java | 156 ++++++++---------- .../rsgroup/RSGroupBasedLoadBalancer.java | 16 +- .../hadoop/hbase/rsgroup/TestRSGroups.java | 16 +- .../rsgroup/TestRSGroupsOfflineMode.java | 3 +- .../master/assignment/AssignmentManager.java | 25 +-- .../master/procedure/ProcedureSyncWait.java | 50 +++--- .../resources/hbase-webapps/master/table.jsp | 6 +- .../src/main/ruby/hbase/rsgroup_admin.rb | 29 +--- .../main/ruby/shell/commands/get_rsgroup.rb | 14 +- .../main/ruby/shell/commands/list_rsgroups.rb | 37 ++++- .../shell/commands/move_servers_rsgroup.rb | 3 +- 11 files changed, 183 insertions(+), 172 deletions(-) diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java index b13dafd195e..3c82d76b9e7 100644 --- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java +++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java @@ -44,13 +44,10 @@ import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.ServerManager; import org.apache.hadoop.hbase.master.assignment.AssignmentManager; import org.apache.hadoop.hbase.master.assignment.RegionStates.RegionStateNode; -import org.apache.hadoop.hbase.master.locking.LockManager; import org.apache.hadoop.hbase.net.Address; -import org.apache.hadoop.hbase.procedure2.LockType; -import org.apache.yetus.audience.InterfaceAudience; - import org.apache.hadoop.hbase.shaded.com.google.common.collect.Lists; import org.apache.hadoop.hbase.shaded.com.google.common.collect.Maps; +import org.apache.yetus.audience.InterfaceAudience; /** * Service to support Region Server Grouping (HBase-6721). @@ -88,10 +85,10 @@ public class RSGroupAdminServer implements RSGroupAdmin { for(ServerName server: master.getServerManager().getOnlineServers().keySet()) { onlineServers.add(server.getAddress()); } - for (Address el: servers) { - if (!onlineServers.contains(el)) { + for (Address address: servers) { + if (!onlineServers.contains(address)) { throw new ConstraintException( - "Server " + el + " is not an online server in 'default' RSGroup."); + "Server " + address + " is not an online server in 'default' RSGroup."); } } } @@ -192,18 +189,20 @@ public class RSGroupAdminServer implements RSGroupAdmin { } /** + * Moves every region from servers which are currently located on these servers, + * but should not be located there. * @param servers the servers that will move to new group + * @param tables these tables will be kept on the servers, others will be moved * @param targetGroupName the target group name - * @param tables The regions of tables assigned to these servers will not unassign * @throws IOException */ - private void unassignRegionFromServers(Set
servers, String targetGroupName, - Set tables) throws IOException { - boolean foundRegionsToUnassign; + private void moveRegionsFromServers(Set
servers, Set tables, + String targetGroupName) throws IOException { + boolean foundRegionsToMove; RSGroupInfo targetGrp = getRSGroupInfo(targetGroupName); Set
allSevers = new HashSet<>(servers); do { - foundRegionsToUnassign = false; + foundRegionsToMove = false; for (Iterator
iter = allSevers.iterator(); iter.hasNext();) { Address rs = iter.next(); // Get regions that are associated with this server and filter regions by tables. @@ -214,22 +213,22 @@ public class RSGroupAdminServer implements RSGroupAdmin { } } - LOG.info("Unassigning " + regions.size() + - " region(s) from " + rs + " for server move to " + targetGroupName); + LOG.info("Moving " + regions.size() + " region(s) from " + rs + + " for server move to " + targetGroupName); if (!regions.isEmpty()) { for (RegionInfo region: regions) { // Regions might get assigned from tables of target group so we need to filter if (!targetGrp.containsTable(region.getTable())) { - this.master.getAssignmentManager().unassign(region); + this.master.getAssignmentManager().move(region); if (master.getAssignmentManager().getRegionStates(). - getRegionState(region).isFailedOpen()) { + getRegionState(region).isFailedOpen()) { continue; } - foundRegionsToUnassign = true; + foundRegionsToMove = true; } } } - if (!foundRegionsToUnassign) { + if (!foundRegionsToMove) { iter.remove(); } } @@ -239,36 +238,27 @@ public class RSGroupAdminServer implements RSGroupAdmin { LOG.warn("Sleep interrupted", e); Thread.currentThread().interrupt(); } - } while (foundRegionsToUnassign); + } while (foundRegionsToMove); } /** + * Moves every region of tables which should be kept on the servers, + * but currently they are located on other servers. + * @param servers the regions of these servers will be kept on the servers, + * others will be moved * @param tables the tables that will move to new group * @param targetGroupName the target group name - * @param servers the regions of tables assigned to these servers will not unassign * @throws IOException */ - private void unassignRegionFromTables(Set tables, String targetGroupName, - Set
servers) throws IOException { + private void moveRegionsToServers(Set
servers, Set tables, + String targetGroupName) throws IOException { for (TableName table: tables) { - LOG.info("Unassigning region(s) from " + table + " for table move to " + targetGroupName); - LockManager.MasterLock lock = master.getLockManager().createMasterLock(table, - LockType.EXCLUSIVE, this.getClass().getName() + ": RSGroup: table move"); - try { - try { - lock.acquire(); - } catch (InterruptedException e) { - throw new IOException("Interrupted when waiting for table lock", e); + LOG.info("Moving region(s) from " + table + " for table move to " + targetGroupName); + for (RegionInfo region : master.getAssignmentManager().getRegionStates().getRegionsOfTable(table)) { + ServerName sn = master.getAssignmentManager().getRegionStates().getRegionServerOfRegion(region); + if (!servers.contains(sn.getAddress())) { + master.getAssignmentManager().move(region); } - for (RegionInfo region : - master.getAssignmentManager().getRegionStates().getRegionsOfTable(table)) { - ServerName sn = master.getAssignmentManager().getRegionStates().getRegionServerOfRegion(region); - if (!servers.contains(sn.getAddress())) { - master.getAssignmentManager().unassign(region); - } - } - } finally { - lock.release(); } } } @@ -329,39 +319,34 @@ public class RSGroupAdminServer implements RSGroupAdmin { Set
movedServers = rsGroupInfoManager.moveServers(servers, srcGrp.getName(), targetGroupName); List
editableMovedServers = Lists.newArrayList(movedServers); - boolean foundRegionsToUnassign; + boolean foundRegionsToMove; do { - foundRegionsToUnassign = false; + foundRegionsToMove = false; for (Iterator
iter = editableMovedServers.iterator(); iter.hasNext();) { Address rs = iter.next(); // Get regions that are associated with this server. List regions = getRegions(rs); - // Unassign regions for a server - // TODO: This is problematic especially if hbase:meta is in the mix. - // We need to update state in hbase:meta on Master and if unassigned we hang - // around in here. There is a silly sort on linked list done above - // in getRegions putting hbase:meta last which helps but probably has holes. - LOG.info("Unassigning " + regions.size() + - " region(s) from " + rs + " for server move to " + targetGroupName); - if (!regions.isEmpty()) { - // TODO bulk unassign or throttled unassign? - for (RegionInfo region: regions) { - // Regions might get assigned from tables of target group so we need to filter - if (!targetGrp.containsTable(region.getTable())) { - this.master.getAssignmentManager().unassign(region); - if (master.getAssignmentManager().getRegionStates(). - getRegionState(region).isFailedOpen()) { - // If region is in FAILED_OPEN state, it won't recover, not without - // operator intervention... in hbase-2.0.0 at least. Continue rather - // than mark region as 'foundRegionsToUnassign'. - continue; - } - foundRegionsToUnassign = true; - } + LOG.info("Moving " + regions.size() + " region(s) from " + rs + + " for server move to " + targetGroupName); + + for (RegionInfo region: regions) { + // Regions might get assigned from tables of target group so we need to filter + if (targetGrp.containsTable(region.getTable())) { + continue; } + LOG.info("Moving region " + region.getShortNameToLog()); + this.master.getAssignmentManager().move(region); + if (master.getAssignmentManager().getRegionStates(). + getRegionState(region).isFailedOpen()) { + // If region is in FAILED_OPEN state, it won't recover, not without + // operator intervention... in hbase-2.0.0 at least. Continue rather + // than mark region as 'foundRegionsToMove'. + continue; + } + foundRegionsToMove = true; } - if (!foundRegionsToUnassign) { + if (!foundRegionsToMove) { iter.remove(); } } @@ -371,7 +356,8 @@ public class RSGroupAdminServer implements RSGroupAdmin { LOG.warn("Sleep interrupted", e); Thread.currentThread().interrupt(); } - } while (foundRegionsToUnassign); + } while (foundRegionsToMove); + if (master.getMasterCoprocessorHost() != null) { master.getMasterCoprocessorHost().postMoveServers(servers, targetGroupName); } @@ -412,29 +398,27 @@ public class RSGroupAdminServer implements RSGroupAdmin { "Source RSGroup " + srcGroup + " is same as target " + targetGroup + " RSGroup for table " + table); } + LOG.info("Moving table " + table.getNameAsString() + " to RSGroup " + targetGroup); } rsGroupInfoManager.moveTables(tables, targetGroup); + + // targetGroup is null when a table is being deleted. In this case no further + // action is required. + if (targetGroup != null) { + for (TableName table: tables) { + for (RegionInfo region : + master.getAssignmentManager().getRegionStates().getRegionsOfTable(table)) { + LOG.info("Moving region " + region.getShortNameToLog() + + " to RSGroup " + targetGroup); + master.getAssignmentManager().move(region); + } + } + } + if (master.getMasterCoprocessorHost() != null) { master.getMasterCoprocessorHost().postMoveTables(tables, targetGroup); } } - for (TableName table: tables) { - LockManager.MasterLock lock = master.getLockManager().createMasterLock(table, - LockType.EXCLUSIVE, this.getClass().getName() + ": RSGroup: table move"); - try { - try { - lock.acquire(); - } catch (InterruptedException e) { - throw new IOException("Interrupted when waiting for table lock", e); - } - for (RegionInfo region : - master.getAssignmentManager().getRegionStates().getRegionsOfTable(table)) { - master.getAssignmentManager().unassign(region); - } - } finally { - lock.release(); - } - } } @Override @@ -582,10 +566,10 @@ public class RSGroupAdminServer implements RSGroupAdmin { String srcGroup = getRSGroupOfServer(servers.iterator().next()).getName(); rsGroupInfoManager.moveServersAndTables(servers, tables, srcGroup, targetGroup); - //unassign regions which not belong to these tables - unassignRegionFromServers(servers, targetGroup, tables); - //unassign regions which not assigned to these servers - unassignRegionFromTables(tables, targetGroup, servers); + //move regions which should not belong to these tables + moveRegionsFromServers(servers, tables, targetGroup); + //move regions which should belong to these servers + moveRegionsToServers(servers, tables, targetGroup); if (master.getMasterCoprocessorHost() != null) { master.getMasterCoprocessorHost().postMoveServersAndTables(servers, tables, targetGroup); diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java index 3f1373f3cbc..68fd98baa5d 100644 --- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java +++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java @@ -124,7 +124,8 @@ public class RSGroupBasedLoadBalancer implements RSGroupableBalancer { List misplacedRegions = correctedState.get(LoadBalancer.BOGUS_SERVER_NAME); for (RegionInfo regionInfo : misplacedRegions) { - regionPlans.add(new RegionPlan(regionInfo, null, null)); + ServerName serverName = findServerForRegion(clusterState, regionInfo); + regionPlans.add(new RegionPlan(regionInfo, serverName, null)); } try { List rsgi = rsGroupInfoManager.listRSGroups(); @@ -323,6 +324,19 @@ public class RSGroupBasedLoadBalancer implements RSGroupableBalancer { return misplacedRegions; } + private ServerName findServerForRegion( + Map> existingAssignments, RegionInfo region) + { + for (Map.Entry> entry : existingAssignments.entrySet()) { + if (entry.getValue().contains(region)) { + return entry.getKey(); + } + } + + throw new IllegalStateException("Could not find server for region " + + region.getShortNameToLog()); + } + private Map> correctAssignments( Map> existingAssignments) throws HBaseIOException{ diff --git a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroups.java b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroups.java index a9493cad4b6..fffdeb73081 100644 --- a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroups.java +++ b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroups.java @@ -51,13 +51,11 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.hadoop.hbase.shaded.com.google.common.collect.Sets; -@Ignore // TODO: Fix after HBASE-14614 goes in. @Category({MediumTests.class}) public class TestRSGroups extends TestRSGroupsBase { protected static final Log LOG = LogFactory.getLog(TestRSGroups.class); @@ -149,7 +147,7 @@ public class TestRSGroups extends TestRSGroupsBase { }); } - @Ignore @Test + @Test public void testBasicStartUp() throws IOException { RSGroupInfo defaultInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP); assertEquals(4, defaultInfo.getServers().size()); @@ -159,7 +157,7 @@ public class TestRSGroups extends TestRSGroupsBase { assertEquals(3, count); } - @Ignore @Test + @Test public void testNamespaceCreateAndAssign() throws Exception { LOG.info("testNamespaceCreateAndAssign"); String nsName = tablePrefix+"_foo"; @@ -185,7 +183,7 @@ public class TestRSGroups extends TestRSGroupsBase { Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(rs).size()); } - @Ignore @Test + @Test public void testDefaultNamespaceCreateAndAssign() throws Exception { LOG.info("testDefaultNamespaceCreateAndAssign"); final byte[] tableName = Bytes.toBytes(tablePrefix + "_testCreateAndAssign"); @@ -203,7 +201,7 @@ public class TestRSGroups extends TestRSGroupsBase { }); } - @Ignore @Test + @Test public void testNamespaceConstraint() throws Exception { String nsName = tablePrefix+"_foo"; String groupName = tablePrefix+"_foo"; @@ -238,7 +236,7 @@ public class TestRSGroups extends TestRSGroupsBase { } } - @Ignore @Test + @Test public void testGroupInfoMultiAccessing() throws Exception { RSGroupInfoManager manager = rsGroupAdminEndpoint.getGroupInfoManager(); RSGroupInfo defaultGroup = manager.getRSGroup("default"); @@ -249,7 +247,7 @@ public class TestRSGroups extends TestRSGroupsBase { it.next(); } - @Ignore @Test + @Test public void testMisplacedRegions() throws Exception { final TableName tableName = TableName.valueOf(tablePrefix+"_testMisplacedRegions"); LOG.info("testMisplacedRegions"); @@ -277,7 +275,7 @@ public class TestRSGroups extends TestRSGroupsBase { }); } - @Ignore @Test + @Test public void testCloneSnapshot() throws Exception { byte[] FAMILY = Bytes.toBytes("test"); String snapshotName = tableName.getNameAsString() + "_snap"; diff --git a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java index 025bb2482bd..b0a1c1ce82b 100644 --- a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java +++ b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java @@ -37,7 +37,6 @@ import org.apache.hadoop.hbase.util.Bytes; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -99,7 +98,7 @@ public class TestRSGroupsOfflineMode { TEST_UTIL.shutdownMiniCluster(); } - @Ignore @Test + @Test public void testOffline() throws Exception, InterruptedException { // Table should be after group table name so it gets assigned later. final TableName failoverTable = TableName.valueOf(name.getMethodName()); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java index 3ade3a3c9f8..8bdf4d5dfd1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java @@ -76,21 +76,18 @@ import org.apache.hadoop.hbase.procedure2.ProcedureEvent; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.procedure2.ProcedureInMemoryChore; import org.apache.hadoop.hbase.procedure2.util.StringUtils; -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; -import org.apache.hadoop.hbase.util.Pair; -import org.apache.hadoop.hbase.util.Threads; -import org.apache.hadoop.hbase.util.VersionInfo; -import org.apache.yetus.audience.InterfaceAudience; - import org.apache.hadoop.hbase.shaded.com.google.common.annotations.VisibleForTesting; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionResponse; - -// TODO: why are they here? +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; +import org.apache.hadoop.hbase.util.Pair; +import org.apache.hadoop.hbase.util.Threads; +import org.apache.hadoop.hbase.util.VersionInfo; +import org.apache.yetus.audience.InterfaceAudience; /** * The AssignmentManager is the coordinator for region assign/unassign operations. @@ -552,6 +549,14 @@ public class AssignmentManager implements ServerListener { ProcedureSyncWait.submitAndWaitProcedure(master.getMasterProcedureExecutor(), proc); } + public void move(final RegionInfo regionInfo) throws IOException { + RegionStateNode node = this.regionStates.getRegionNode(regionInfo); + ServerName sourceServer = node.getRegionLocation(); + RegionPlan plan = new RegionPlan(regionInfo, sourceServer, null); + MoveRegionProcedure proc = createMoveRegionProcedure(plan); + ProcedureSyncWait.submitAndWaitProcedure(master.getMasterProcedureExecutor(), proc); + } + public Future moveAsync(final RegionPlan regionPlan) { MoveRegionProcedure proc = createMoveRegionProcedure(regionPlan); return ProcedureSyncWait.submitProcedure(master.getMasterProcedureExecutor(), proc); @@ -590,7 +595,7 @@ public class AssignmentManager implements ServerListener { } ProcedureSyncWait.waitForProcedureToCompleteIOE( - master.getMasterProcedureExecutor(), proc.getProcId(), timeout); + master.getMasterProcedureExecutor(), proc, timeout); return true; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java index 18fa91db4dc..23b83acd645 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedureSyncWait.java @@ -61,14 +61,14 @@ public final class ProcedureSyncWait { private static class ProcedureFuture implements Future { private final ProcedureExecutor procExec; - private final long procId; + private final Procedure proc; private boolean hasResult = false; private byte[] result = null; - public ProcedureFuture(ProcedureExecutor procExec, long procId) { + public ProcedureFuture(ProcedureExecutor procExec, Procedure proc) { this.procExec = procExec; - this.procId = procId; + this.proc = proc; } @Override @@ -84,7 +84,7 @@ public final class ProcedureSyncWait { public byte[] get() throws InterruptedException, ExecutionException { if (hasResult) return result; try { - return waitForProcedureToComplete(procExec, procId, Long.MAX_VALUE); + return waitForProcedureToComplete(procExec, proc, Long.MAX_VALUE); } catch (Exception e) { throw new ExecutionException(e); } @@ -95,7 +95,7 @@ public final class ProcedureSyncWait { throws InterruptedException, ExecutionException, TimeoutException { if (hasResult) return result; try { - result = waitForProcedureToComplete(procExec, procId, unit.toMillis(timeout)); + result = waitForProcedureToComplete(procExec, proc, unit.toMillis(timeout)); hasResult = true; return result; } catch (TimeoutIOException e) { @@ -107,26 +107,27 @@ public final class ProcedureSyncWait { } public static Future submitProcedure(final ProcedureExecutor procExec, - final Procedure proc) { + final Procedure proc) { if (proc.isInitializing()) { procExec.submitProcedure(proc); } - return new ProcedureFuture(procExec, proc.getProcId()); + return new ProcedureFuture(procExec, proc); } public static byte[] submitAndWaitProcedure(ProcedureExecutor procExec, - final Procedure proc) throws IOException { + final Procedure proc) throws IOException { if (proc.isInitializing()) { procExec.submitProcedure(proc); } - return waitForProcedureToCompleteIOE(procExec, proc.getProcId(), Long.MAX_VALUE); + return waitForProcedureToCompleteIOE(procExec, proc, Long.MAX_VALUE); } public static byte[] waitForProcedureToCompleteIOE( - final ProcedureExecutor procExec, final long procId, final long timeout) + final ProcedureExecutor procExec, + final Procedure proc, final long timeout) throws IOException { try { - return waitForProcedureToComplete(procExec, procId, timeout); + return waitForProcedureToComplete(procExec, proc, timeout); } catch (IOException e) { throw e; } catch (Exception e) { @@ -135,30 +136,27 @@ public final class ProcedureSyncWait { } public static byte[] waitForProcedureToComplete( - final ProcedureExecutor procExec, final long procId, final long timeout) + final ProcedureExecutor procExec, + final Procedure proc, final long timeout) throws IOException { - waitFor(procExec.getEnvironment(), "pid=" + procId, + waitFor(procExec.getEnvironment(), "pid=" + proc.getProcId(), new ProcedureSyncWait.Predicate() { @Override public Boolean evaluate() throws IOException { - return !procExec.isRunning() || procExec.isFinished(procId); + return !procExec.isRunning() || procExec.isFinished(proc.getProcId()); } } ); - Procedure result = procExec.getResult(procId); - if (result != null) { - if (result.hasException()) { - // If the procedure fails, we should always have an exception captured. Throw it. - throw result.getException().unwrapRemoteIOException(); - } - return result.getResult(); + if (!procExec.isRunning()) { + throw new IOException("The Master is Aborting"); + } + + if (proc.hasException()) { + // If the procedure fails, we should always have an exception captured. Throw it. + throw proc.getException().unwrapRemoteIOException(); } else { - if (procExec.isRunning()) { - throw new IOException("pid= " + procId + "not found"); - } else { - throw new IOException("The Master is Aborting"); - } + return proc.getResult(); } } diff --git a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp index c7a1aff1a4d..685678196b3 100644 --- a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp +++ b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp @@ -251,7 +251,7 @@ if ( fqtn != null ) { RegionInfoBuilder.FIRST_META_REGIONINFO, j); ServerName metaLocation = metaTableLocator.waitMetaRegionLocation(master.getZooKeeper(), j, 1); for (int i = 0; i < 1; i++) { - String url = ""; + String hostAndPort = ""; String readReq = "N/A"; String writeReq = "N/A"; String fileSize = "N/A"; @@ -262,7 +262,7 @@ if ( fqtn != null ) { if (metaLocation != null) { ServerLoad sl = master.getServerManager().getLoad(metaLocation); // The host name portion should be safe, but I don't know how we handle IDNs so err on the side of failing safely. - url = "//" + URLEncoder.encode(metaLocation.getHostname()) + ":" + master.getRegionServerInfoPort(metaLocation) + "/"; + hostAndPort = URLEncoder.encode(metaLocation.getHostname()) + ":" + master.getRegionServerInfoPort(metaLocation); if (sl != null) { Map map = sl.getRegionsLoad(); if (map.containsKey(meta.getRegionName())) { @@ -279,7 +279,7 @@ if ( fqtn != null ) { %> <%= escapeXml(meta.getRegionNameAsString()) %> - <%= StringEscapeUtils.escapeHtml4(metaLocation.getHostname().toString()) + ":" + master.getRegionServerInfoPort(metaLocation) %> + <%= StringEscapeUtils.escapeHtml4(hostAndPort) %> <%= readReq%> <%= writeReq%> <%= fileSize%> diff --git a/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb b/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb index c8ef3e9e9f2..befed010ed1 100644 --- a/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb +++ b/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb @@ -36,7 +36,7 @@ module Hbase #-------------------------------------------------------------------------- # Returns a list of groups in hbase def list_rs_groups - @admin.listRSGroups.map(&:getName) + @admin.listRSGroups end #-------------------------------------------------------------------------- @@ -44,32 +44,7 @@ module Hbase def get_rsgroup(group_name) group = @admin.getRSGroupInfo(group_name) raise(ArgumentError, 'Group does not exist: ' + group_name) if group.nil? - - res = {} - yield('Servers:') if block_given? - - servers = [] - group.getServers.each do |v| - if block_given? - yield(v.toString) - else - servers << v.toString - end - end - res[:servers] = servers - - tables = [] - yield('Tables:') if block_given? - group.getTables.each do |v| - if block_given? - yield(v.toString) - else - tables << v.toString - end - end - res[:tables] = tables - - res unless block_given? + group end #-------------------------------------------------------------------------- diff --git a/hbase-shell/src/main/ruby/shell/commands/get_rsgroup.rb b/hbase-shell/src/main/ruby/shell/commands/get_rsgroup.rb index a18083f6bed..8f5b1c1f921 100644 --- a/hbase-shell/src/main/ruby/shell/commands/get_rsgroup.rb +++ b/hbase-shell/src/main/ruby/shell/commands/get_rsgroup.rb @@ -30,9 +30,17 @@ EOF end def command(group_name) - formatter.header(['RSGROUP '.concat(group_name)]) - rsgroup_admin.get_rsgroup(group_name) do |s| - formatter.row([s]) + group = rsgroup_admin.get_rsgroup(group_name) + + formatter.header(['SERVERS']) + group.getServers.each do |server| + formatter.row([server.toString]) + end + formatter.footer + + formatter.header(['TABLES']) + group.getTables.each do |table| + formatter.row([table.getNameAsString]) end formatter.footer end diff --git a/hbase-shell/src/main/ruby/shell/commands/list_rsgroups.rb b/hbase-shell/src/main/ruby/shell/commands/list_rsgroups.rb index ef22aa9ea32..dc33b851dc1 100644 --- a/hbase-shell/src/main/ruby/shell/commands/list_rsgroups.rb +++ b/hbase-shell/src/main/ruby/shell/commands/list_rsgroups.rb @@ -32,15 +32,44 @@ EOF end def command(regex = '.*') - formatter.header(['GROUPS']) + formatter.header(['NAME', 'SERVER / TABLE']) regex = /#{regex}/ unless regex.is_a?(Regexp) - list = rsgroup_admin.list_rs_groups.grep(regex) + list = rsgroup_admin.list_rs_groups + groups = 0 + list.each do |group| - formatter.row([group]) + next unless group.getName.match(regex) + + groups += 1 + group_name_printed = false + + group.getServers.each do |server| + if group_name_printed + group_name = '' + else + group_name = group.getName + group_name_printed = true + end + + formatter.row([group_name, 'server ' + server.toString]) + end + + group.getTables.each do |table| + if group_name_printed + group_name = '' + else + group_name = group.getName + group_name_printed = true + end + + formatter.row([group_name, 'table ' + table.getNameAsString]) + end + + formatter.row([group.getName, '']) unless group_name_printed end - formatter.footer(list.size) + formatter.footer(groups) end end end diff --git a/hbase-shell/src/main/ruby/shell/commands/move_servers_rsgroup.rb b/hbase-shell/src/main/ruby/shell/commands/move_servers_rsgroup.rb index e2d89233d18..5370f483ffd 100644 --- a/hbase-shell/src/main/ruby/shell/commands/move_servers_rsgroup.rb +++ b/hbase-shell/src/main/ruby/shell/commands/move_servers_rsgroup.rb @@ -20,7 +20,8 @@ module Shell class MoveServersRsgroup < Command def help <<-EOF -Reassign RegionServers from one group to another. +Reassign RegionServers from one group to another. Every region of the +RegionServer will be moved to another RegionServer. Example: