diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon index 97921263c9f..c83f2952287 100644 --- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon +++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon @@ -43,6 +43,8 @@ org.apache.hadoop.hbase.ServerLoad; org.apache.hadoop.hbase.ServerName; org.apache.hadoop.hbase.client.Admin; org.apache.hadoop.hbase.client.HConnectionManager; +org.apache.hadoop.hbase.HRegionInfo; +org.apache.hadoop.hbase.master.RegionState; org.apache.hadoop.hbase.HTableDescriptor; org.apache.hadoop.hbase.HBaseConfiguration; org.apache.hadoop.hbase.TableName; @@ -363,17 +365,42 @@ AssignmentManager assignmentManager = master.getAssignmentManager(); Frag. Online Regions + Offline Regions + Failed Regions + Split Regions + Other Regions Description <%for HTableDescriptor htDesc : tables%> + <%java> + Map> tableRegions = + master.getAssignmentManager().getRegionStates() + .getRegionByStateOfTable(htDesc.getTableName()); + int openRegionsCount = tableRegions.get(RegionState.State.OPEN).size(); + int offlineRegionsCount = tableRegions.get(RegionState.State.OFFLINE).size(); + int splitRegionsCount = tableRegions.get(RegionState.State.SPLIT).size(); + int failedRegionsCount = tableRegions.get(RegionState.State.FAILED_OPEN).size() + + tableRegions.get(RegionState.State.FAILED_CLOSE).size(); + int otherRegionsCount = 0; + for (List list: tableRegions.values()) { + otherRegionsCount += list.size(); + } + // now subtract known states + otherRegionsCount = otherRegionsCount - openRegionsCount + - failedRegionsCount - offlineRegionsCount + - splitRegionsCount; + <% htDesc.getTableName().getNamespaceAsString() %> ><% htDesc.getTableName().getQualifierAsString() %> <%if (frags != null) %> <% frags.get(htDesc.getTableName().getNameAsString()) != null ? frags.get(htDesc.getTableName().getQualifierAsString()).intValue() + "%" : "n/a" %> - <% master.getAssignmentManager().getRegionStates().getRegionsOfTable(htDesc - .getTableName()).size() %> + <% openRegionsCount %> + <% offlineRegionsCount %> + <% failedRegionsCount %> + <% splitRegionsCount %> + <% otherRegionsCount %> <% htDesc.toStringCustomizedValues() %> diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java index ece9a0d359f..f270cd2e79b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java @@ -80,6 +80,12 @@ public class RegionStates { private final Map regionStates = new HashMap(); + /** + * Holds mapping of table -> region state + */ + private final Map> regionStatesTableIndex = + new HashMap>(); + /** * Server to regions assignment map. * Contains the set of regions currently assigned to a given server. @@ -334,7 +340,7 @@ public class RegionStates { + "used existing: " + regionState + ", ignored new: " + newState); } else { regionState = new RegionState(hri, newState, serverName); - regionStates.put(encodedName, regionState); + putRegionState(regionState); if (newState == State.OPEN) { if (!serverName.equals(lastHost)) { LOG.warn("Open region's last host " + lastHost @@ -357,6 +363,20 @@ public class RegionStates { return regionState; } + private RegionState putRegionState(RegionState regionState) { + HRegionInfo hri = regionState.getRegion(); + String encodedName = hri.getEncodedName(); + TableName table = hri.getTable(); + RegionState oldState = regionStates.put(encodedName, regionState); + Map map = regionStatesTableIndex.get(table); + if (map == null) { + map = new HashMap(); + regionStatesTableIndex.put(table, map); + } + map.put(encodedName, regionState); + return oldState; + } + /** * Update a region state. It will be put in transition if not already there. */ @@ -682,6 +702,30 @@ public class RegionStates { return tableRegions; } + /** + * Gets current state of all regions of the table. + * This method looks at the in-memory state. It does not go to hbase:meta. + * Method guaranteed to return keys for all states + * in {@link org.apache.hadoop.hbase.master.RegionState.State} + * + * @param tableName + * @return Online regions from tableName + */ + public synchronized Map> + getRegionByStateOfTable(TableName tableName) { + Map> tableRegions = + new HashMap>(); + for (State state : State.values()) { + tableRegions.put(state, new ArrayList()); + } + Map indexMap = regionStatesTableIndex.get(tableName); + if (indexMap == null) + return tableRegions; + for (RegionState regionState : indexMap.values()) { + tableRegions.get(regionState.getState()).add(regionState.getRegion()); + } + return tableRegions; + } /** * Wait on region to clear regions-in-transition. @@ -741,6 +785,11 @@ public class RegionStates { String encodedName = hri.getEncodedName(); regionsInTransition.remove(encodedName); regionStates.remove(encodedName); + TableName table = hri.getTable(); + Map indexMap = regionStatesTableIndex.get(table); + indexMap.remove(encodedName); + if (indexMap.size() == 0) + regionStatesTableIndex.remove(table); lastAssignments.remove(encodedName); ServerName sn = regionAssignments.remove(hri); if (sn != null) { @@ -1047,7 +1096,7 @@ public class RegionStates { synchronized (this) { regionsInTransition.put(encodedName, regionState); - regionStates.put(encodedName, regionState); + putRegionState(regionState); // For these states, region should be properly closed. // There should be no log splitting issue. diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManagerOnCluster.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManagerOnCluster.java index a4ae2fe36c2..5de785a5329 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManagerOnCluster.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManagerOnCluster.java @@ -361,9 +361,9 @@ public class TestAssignmentManagerOnCluster { long timeoutTime = System.currentTimeMillis() + 800; while (true) { - List regions = - regionStates.getRegionsOfTable(table); - if (!regions.contains(hri)) break; + if (regionStates.getRegionByStateOfTable(table) + .get(RegionState.State.OFFLINE).contains(hri)) + break; long now = System.currentTimeMillis(); if (now > timeoutTime) { fail("Failed to offline the region in time");