Repository: hbase Updated Branches: refs/heads/branch-1 e06bbe480 -> d349f642c
HBASE-16262 Backport HBASE-13839: Fix AssgnmentManagerTmpl.jamon issues (coloring, content â¦etc). Ignoring UI changes provided by HBASE-11344. Signed-off-by: Elliott Clark <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/d349f642 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/d349f642 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/d349f642 Branch: refs/heads/branch-1 Commit: d349f642c02c83eaa020afcee076f16cba96e299 Parents: e06bbe4 Author: Joseph Hwang <[email protected]> Authored: Fri Feb 12 15:06:38 2016 -0800 Committer: Elliott Clark <[email protected]> Committed: Wed Jul 27 13:09:28 2016 -0700 ---------------------------------------------------------------------- .../master/AssignmentManagerStatusTmpl.jamon | 146 ++++++++++++------- .../hadoop/hbase/master/RegionStates.java | 29 +++- .../hbase/master/TestMasterStatusServlet.java | 6 +- 3 files changed, 122 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/d349f642/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon index 64bb7ef..67816b2 100644 --- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon +++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon @@ -23,81 +23,115 @@ org.apache.hadoop.hbase.master.RegionState; org.apache.hadoop.conf.Configuration; org.apache.hadoop.hbase.HBaseConfiguration; org.apache.hadoop.hbase.HConstants; +java.util.SortedSet; java.util.Iterator; +java.util.List; +java.util.ArrayList; java.util.Set; +java.util.HashSet; +java.lang.Integer; </%import> <%args> AssignmentManager assignmentManager; -int limit = 100; +int limit = Integer.MAX_VALUE; </%args> + +<%java SortedSet<RegionState> rit = assignmentManager + .getRegionStates().getRegionsInTransitionOrderedByTimestamp(); %> + +<%if !rit.isEmpty() %> <%java> -Set<RegionState> rit = assignmentManager.getRegionStates().getRegionsInTransition(); +Set<String> ritsOverThreshold = new HashSet<>(); +Set<String> ritsTwiceThreshold = new HashSet<>(); // process the map to find region in transition details Configuration conf = HBaseConfiguration.create(); int ritThreshold = conf.getInt(HConstants.METRICS_RIT_STUCK_WARNING_THRESHOLD, 60000); int numOfRITOverThreshold = 0; -long maxRITTime = Long.MIN_VALUE; long currentTime = System.currentTimeMillis(); -String regionIDForOldestRIT = ""; // avoiding null +List<RegionState> ritToDisplay = new ArrayList<>(); +int count = 0; for (RegionState rs : rit) { long ritTime = currentTime - rs.getStamp(); - if(ritTime > ritThreshold) { + if(ritTime > (ritThreshold * 2)) { numOfRITOverThreshold++; - } - if(maxRITTime < ritTime) { - maxRITTime = ritTime; - regionIDForOldestRIT = rs.getRegion().getEncodedName(); - } -} - -int totalRITs = rit.size(); -int toRemove = rit.size() - limit; -int removed = 0; -if (toRemove > 0) { - // getRegionsInTransition returned a copy, so we can mutate it - for (Iterator<RegionState> it = rit.iterator(); it.hasNext() && toRemove > 0;) { - RegionState rs = it.next(); - String regionEncodedName = rs.getRegion().getEncodedName(); - if (HRegionInfo.FIRST_META_REGIONINFO.getEncodedName().equals(regionEncodedName) || - regionIDForOldestRIT.equals(regionEncodedName)) { - // don't remove the meta & the oldest rit regions, they're too interesting! - continue; - } - it.remove(); - toRemove--; - removed++; + ritsTwiceThreshold.add(rs.getRegion().getEncodedName()); + } else if (ritTime > ritThreshold) { + numOfRITOverThreshold++; + ritsOverThreshold.add(rs.getRegion().getEncodedName()); + } + if (count++ < limit) { + ritToDisplay.add(rs); } } - +int numOfRITs = rit.size(); +int ritsPerPage = Math.min(5, numOfRITs); +int numOfPages = (int) Math.ceil(numOfRITs * 1.0 / ritsPerPage); </%java> - - -<%if !rit.isEmpty() %> <section> <h2>Regions in Transition</h2> - <table class="table table-striped"> - <tr><th>Region</th><th>State</th><th>RIT time (ms)</th></tr> - <%for RegionState rs : rit %> - <%if regionIDForOldestRIT.equals(rs.getRegion().getEncodedName()) %> - <tr BGCOLOR="#FE2E2E" > - <%else> - <tr> - </%if> - <td><% rs.getRegion().getEncodedName() %></td><td><% rs.toDescriptiveString() %></td> - <td><% (currentTime - rs.getStamp()) %> </td></tr> + <p><% numOfRITs %> region(s) in transition. + <%if !ritsTwiceThreshold.isEmpty() %> + <span class="label label-danger" style="font-size:100%;font-weight:normal"> + <%elseif !ritsOverThreshold.isEmpty() %> + <span class="label label-warning" style="font-size:100%;font-weight:normal"> + <%else> + <span> + </%if> + <% numOfRITOverThreshold %> region(s) in transition for + more than <% ritThreshold %> milliseconds. + </span> + </p> + <div class="tabbable"> + <div class="tab-content"> + <%java int recordItr = 0; %> + <%for RegionState rs : ritToDisplay %> + <%if (recordItr % ritsPerPage) == 0 %> + <%if recordItr == 0 %> + <div class="tab-pane active" id="tab_rits<% (recordItr / ritsPerPage) + 1 %>"> + <%else> + <div class="tab-pane" id="tab_rits<% (recordItr / ritsPerPage) + 1 %>"> + </%if> + <table class="table table-striped" style="margin-bottom:0px;"><tr><th>Region</th> + <th>State</th><th>RIT time (ms)</th></tr> + </%if> + + <%if ritsOverThreshold.contains(rs.getRegion().getEncodedName()) %> + <tr class="alert alert-warning" role="alert"> + <%elseif ritsTwiceThreshold.contains(rs.getRegion().getEncodedName()) %> + <tr class="alert alert-danger" role="alert"> + <%else> + <tr> + </%if> + <td><% rs.getRegion().getEncodedName() %></td><td> + <% rs.toDescriptiveString() %></td> + <td><% (currentTime - rs.getStamp()) %> </td> + <%java recordItr++; %> + <%if (recordItr % ritsPerPage) == 0 %> + </table> + </div> + </%if> </%for> - <%if numOfRITOverThreshold > 0 %> - <tr BGCOLOR="#D7DF01" > - <%else> - <tr> - </%if> - <td>Total number of Regions in Transition for more than <% ritThreshold %> milliseconds</td><td> <% numOfRITOverThreshold %></td><td></td> - </tr> - <tr> <td> Total number of Regions in Transition</td><td><% totalRITs %> </td><td></td> - </table> - <%if removed > 0 %> - (<% removed %> more regions in transition not shown) - </%if> - </section> -</%if> + <%if (recordItr % ritsPerPage) != 0 %> + <%for ; (recordItr % ritsPerPage) != 0 ; recordItr++ %> + <tr><td colspan="3" style="height:61px"></td></tr> + </%for> + </table> + </div> + </%if> + </div> + <nav> + <ul class="nav nav-pills pagination"> + <%for int i = 1 ; i <= numOfPages; i++ %> + <%if i == 1 %> + <li class="active"> + <%else> + <li> + </%if> + <a href="#tab_rits<% i %>"><% i %></a></li> + </%for> + </ul> + </nav> + </div> + </section> + </%if> http://git-wip-us.apache.org/repos/asf/hbase/blob/d349f642/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java ---------------------------------------------------------------------- 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 e6f5707..52cc92d 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 @@ -20,13 +20,14 @@ package org.apache.hadoop.hbase.master; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Comparator; +import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; @@ -67,6 +68,21 @@ import com.google.common.base.Preconditions; public class RegionStates { private static final Log LOG = LogFactory.getLog(RegionStates.class); + public final static RegionStateStampComparator REGION_STATE_COMPARATOR = + new RegionStateStampComparator(); + + // This comparator sorts the RegionStates by time stamp then Region name. + // Comparing by timestamp alone can lead us to discard different RegionStates that happen + // to share a timestamp. + private static class RegionStateStampComparator implements Comparator<RegionState> { + @Override + public int compare(RegionState l, RegionState r) { + return Long.compare(l.getStamp(), r.getStamp()) == 0 ? + Bytes.compareTo(l.getRegion().getRegionName(), r.getRegion().getRegionName()) : + Long.compare(l.getStamp(), r.getStamp()); + } + } + /** * Regions currently in transition. */ @@ -214,6 +230,17 @@ public class RegionStates { } /** + * @return a set of the regions in transition that are sorted by timestamp + */ + public synchronized SortedSet<RegionState> getRegionsInTransitionOrderedByTimestamp() { + final TreeSet<RegionState> rit = new TreeSet<RegionState>(REGION_STATE_COMPARATOR); + for (RegionState rs: regionsInTransition.values()) { + rit.add(rs); + } + return rit; + } + + /** * @return True if specified region in transition. */ public synchronized boolean isRegionInTransition(final HRegionInfo hri) { http://git-wip-us.apache.org/repos/asf/hbase/blob/d349f642/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterStatusServlet.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterStatusServlet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterStatusServlet.java index 801566b..19ba132 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterStatusServlet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterStatusServlet.java @@ -25,6 +25,8 @@ import java.io.StringWriter; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -45,7 +47,6 @@ import org.junit.experimental.categories.Category; import org.mockito.Mockito; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; /** * Tests for the master status page and its template. @@ -157,7 +158,7 @@ public class TestMasterStatusServlet { RegionStates rs = Mockito.mock(RegionStates.class); // Add 100 regions as in-transition - HashSet<RegionState> regionsInTransition = new HashSet<RegionState>(); + SortedSet<RegionState> regionsInTransition = new TreeSet<>(RegionStates.REGION_STATE_COMPARATOR); for (byte i = 0; i < 100; i++) { HRegionInfo hri = new HRegionInfo(FAKE_TABLE.getTableName(), new byte[]{i}, new byte[]{(byte) (i+1)}); @@ -170,6 +171,7 @@ public class TestMasterStatusServlet { RegionState.State.CLOSING, 123L, FAKE_HOST)); Mockito.doReturn(rs).when(am).getRegionStates(); Mockito.doReturn(regionsInTransition).when(rs).getRegionsInTransition(); + Mockito.doReturn(regionsInTransition).when(rs).getRegionsInTransitionOrderedByTimestamp(); // Render to a string StringWriter sw = new StringWriter();
