This is an automated email from the ASF dual-hosted git repository.

nihaljain pushed a commit to branch branch-2.6
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-2.6 by this push:
     new a5367b87683 HBASE-29036 Backport missing UI patches to branch-2.6 
(#6550)
a5367b87683 is described below

commit a5367b87683372c32cd2da252668ec89f1362c38
Author: Dávid Paksy <[email protected]>
AuthorDate: Wed Jan 8 12:52:42 2025 +0100

    HBASE-29036 Backport missing UI patches to branch-2.6 (#6550)
    
    * HBASE-18382 add transport type info into Thrift UI (#880)
    
    Signed-off-by: Wellington Chevreuil <[email protected]>
    Signed-off-by: Bharath Vissapragada <[email protected]>
    Signed-off-by: Viraj Jasani <[email protected]>
    (cherry picked from commit 82e155eb26cddd642e151d9276e2f4f281b4df88)
    
    * HBASE-20693 Refactor thrift jsp's and extract header and footer (#5732)
    - Fixes the way logLevel page renders in UI
    
    Signed-off-by: Nick Dimiduk <[email protected]>
    (cherry picked from commit ede4ccd2dc5f5690a518f97b6d28a7e18df9584a)
    
    * HBASE-24624 Optimize table.jsp code (#1963)
    
    Signed-off-by: Guangxu Cheng <[email protected]>
    (cherry picked from commit 9ad16aa3763d05e85807a5c81b42c03eb2dec4f5)
    
    * HBASE-25402 Sorting order by start key or end key is not considering 
empty start key/end key (#2955)
    
    Signed-off-by: Duo Zhang <[email protected]>
    Signed-off-by: Pankaj Kumar<[email protected]>
    (cherry picked from commit 157200ef8375a91905efb3589393f2ef2b58b970)
    
    * HBASE-28778 NPE may occur when opening master-status or table.jsp or 
procedure.jsp while Master is initializing (#6152)
    
    Signed-off-by: Duo Zhang <[email protected]>
    (cherry picked from commit 3caaf2d739106b56ab94a0561e730ff35802610d)
    
    ---------
    
    Co-authored-by: Beata Sudi <[email protected]>
    Co-authored-by: Nihal Jain <[email protected]>
    Co-authored-by: xincunSong <[email protected]>
    Co-authored-by: Akshay Sudheer 
<[email protected]>
    Co-authored-by: Peng Lu <[email protected]>
    
    Signed-off-by: Nihal Jain <[email protected]>
    Signed-off-by: Andrew Purtell <[email protected]>
---
 .../hbase/tmpl/regionserver/RSStatusTmpl.jamon     |    7 +-
 .../main/resources/hbase-webapps/master/table.jsp  | 1758 ++++++++++----------
 .../main/resources/hbase-webapps/thrift/footer.jsp |   30 +
 .../main/resources/hbase-webapps/thrift/header.jsp |   74 +
 .../main/resources/hbase-webapps/thrift/thrift.jsp |  101 +-
 5 files changed, 994 insertions(+), 976 deletions(-)

diff --git 
a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
 
b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
index 23330096cf3..d837b850462 100644
--- 
a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
+++ 
b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
@@ -299,7 +299,12 @@ $(document).ready(function()
             type: "numeric"
         });
 
-        $("#baseStatsTable").tablesorter();
+        $("#baseStatsTable").tablesorter({
+            headers: {
+                1: {empty: 'emptyMin'},
+                2: {empty: 'emptyMax'}
+            }
+        });
         $("#requestStatsTable").tablesorter({
             headers: {
                 1: {sorter: 'separator'},
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 56a0c8096d3..f9b6120196c 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
@@ -93,7 +93,7 @@
    * its region server.
    * @return an anchor tag if one can be built, {@code null} otherwise.
    */
-  private static String buildRegionServerLink(final ServerName serverName, 
final int rsInfoPort,
+  private static String buildRegionLink(final ServerName serverName, final int 
rsInfoPort,
     final RegionInfo regionInfo, final RegionState.State regionState) {
     if (serverName == null || regionInfo == null) { return null; }
 
@@ -107,15 +107,74 @@
       + "?name=" + regionInfo.getEncodedName();
     return "<a href=\"" + URI + "\">" + serverName.getServerName() + "</a>";
   }
+
+  /**
+   * Render an <td> tag contents server name which the given region deploys.
+   * Links to the server rs-status page.
+   * <td class="undeployed-region">not deployed</td> instead if can not find 
the deploy message.
+   * @return an <td> tag contents server name links to server rs-status page.
+   */
+  private static String buildRegionDeployedServerTag(RegionInfo regionInfo, 
HMaster master,
+    Map<RegionInfo, ServerName> regionsToServer) {
+    ServerName serverName = regionsToServer.get(regionInfo);
+
+    if (serverName == null) {
+      return "<td class=\"undeployed-region\">not deployed</td>";
+    }
+
+    String hostName = serverName.getHostname();
+    String hostNameEncoded = URLEncoder.encode(hostName);
+    // This port might be wrong if RS actually ended up using something else.
+    int serverInfoPort = master.getRegionServerInfoPort(serverName);
+    String urlRegionServer = "//" + hostNameEncoded + ":" + serverInfoPort + 
"/rs-status";
+
+    return "<td><a href=\"" + urlRegionServer + "\">" + 
StringEscapeUtils.escapeHtml4(hostName)
+      + ":" + serverInfoPort + "</a></td>";
+  }
+
+  /**
+   * @return an <p> tag guide user to see all region messages.
+   */
+  private static String moreRegionsToRender(int numRegionsRendered, int 
numRegions, String fqtn) {
+    if (numRegions > numRegionsRendered) {
+      String allRegionsUrl = "?name=" + URLEncoder.encode(fqtn) + 
"&numRegions=all";
+
+      return "This table has <b>" + numRegions
+        + "</b> regions in total, in order to improve the page load time, only 
<b>"
+        + numRegionsRendered + "</b> regions are displayed here, <a href=\""
+        + allRegionsUrl + "\">click here</a> to see all regions.</p>";
+    }
+    return "";
+  }
 %>
+
+<jsp:include page="header.jsp">
+  <jsp:param name="pageTitle" value="${pageTitle}"/>
+</jsp:include>
+
 <%
   final String ZEROMB = "0 MB";
   HMaster master = (HMaster)getServletContext().getAttribute(HMaster.MASTER);
   Configuration conf = master.getConfiguration();
   String fqtn = request.getParameter("name");
+  // handle the case for fqtn is null or master is not initialized with error 
message + redirect
+  if (fqtn == null || !master.isInitialized()) {
+%>
+    <div class="container-fluid content">
+      <div class="row inner_header">
+        <div class="page-header">
+          <h1>Table not ready</h1>
+        </div>
+      </div>
+      <p><hr><p>
+      <jsp:include page="redirect.jsp" />
+    </div>
+<%  return;
+  } %>
+
+<%
   final String escaped_fqtn = StringEscapeUtils.escapeHtml4(fqtn);
-  Table table;
-  boolean withReplica = false;
+  Table table = master.getConnection().getTable(TableName.valueOf(fqtn));
   boolean showFragmentation = 
conf.getBoolean("hbase.master.ui.fragmentation.enabled", false);
   boolean readOnly = !InfoServer.canUserModifyUI(request, getServletContext(), 
conf);
   int numMetaReplicas =
@@ -162,19 +221,22 @@
   final MetaBrowser metaBrowser = new MetaBrowser(connection, request);
 %>
 
-<jsp:include page="header.jsp">
-  <jsp:param name="pageTitle" value="${pageTitle}"/>
-</jsp:include>
+<% // unknow table
+  if (! admin.tableExists(TableName.valueOf(fqtn)).get()) { %>
+<div class="container-fluid content">
+  <div class="row inner_header">
+    <div class="page-header">
+      <h1>Table not found</h1>
+    </div>
+  </div>
+  <p><hr><p>
+  <jsp:include page="redirect.jsp" />
+</div>
+<%  return;
+  } %>
 
-<%
-  if (fqtn != null && master.isInitialized()) {
-    try {
-      table = master.getConnection().getTable(TableName.valueOf(fqtn));
-      if (table.getTableDescriptor().getRegionReplication() > 1) {
-        withReplica = true;
-      }
-      if ( !readOnly && action != null ) {
-%>
+<% // table split/compact/merge actions
+  if ( !readOnly && action != null ) { %>
 <div class="container-fluid content">
   <div class="row inner_header">
     <div class="page-header">
@@ -182,15 +244,14 @@
     </div>
   </div>
   <p><hr><p>
-    <%
-    if (action.equals("split")) {
+<%  if (action.equals("split")) {
       if (key != null && key.length() > 0) {
         admin.split(TableName.valueOf(fqtn), Bytes.toBytes(key));
       } else {
         admin.split(TableName.valueOf(fqtn));
       }
 
-    %> Split request accepted. <%
+%>    Split request accepted. <%
     } else if (action.equals("major compact")) {
       if (key != null && key.length() > 0) {
         List<RegionInfo> regions = 
admin.getRegions(TableName.valueOf(fqtn)).get();
@@ -203,7 +264,7 @@
       } else {
         admin.majorCompact(TableName.valueOf(fqtn));
       }
-    %> major Compact request accepted. <%
+%>    major Compact request accepted. <%
     } else if (action.equals("compact")) {
       if (key != null && key.length() > 0) {
         List<RegionInfo> regions = 
admin.getRegions(TableName.valueOf(fqtn)).get();
@@ -217,246 +278,227 @@
       } else {
         admin.compact(TableName.valueOf(fqtn));
       }
-    %> Compact request accepted. <%
+%>    Compact request accepted. <%
     } else if (action.equals("merge")) {
-        if (left != null && left.length() > 0 && right != null && 
right.length() > 0) {
-            admin.mergeRegions(Bytes.toBytesBinary(left), 
Bytes.toBytesBinary(right), false);
-        }
-        %> Merge request accepted. <%
-    }
-%>
-  <jsp:include page="redirect.jsp" />
-</div>
-<%
-} else {
-%>
-<div class="container-fluid content">
-  <div class="row inner_header">
-    <div class="page-header">
-      <h1>Table <small><%= escaped_fqtn %></small></h1>
+      if (left != null && left.length() > 0 && right != null && right.length() 
> 0) {
+        admin.mergeRegions(Bytes.toBytesBinary(left), 
Bytes.toBytesBinary(right), false);
+      }
+%>    Merge request accepted. <%
+    } %>
+    <jsp:include page="redirect.jsp" />
     </div>
+<%  return;
+  } %>
+
+<div class="container-fluid content">
+<div class="row inner_header">
+  <div class="page-header">
+    <h1>Table <small><%= escaped_fqtn %></small></h1>
   </div>
-  <div class="row">
-    <%
-      if(fqtn.equals(TableName.META_TABLE_NAME.getNameAsString())) {
-    %>
-    <h2>Table Regions</h2>
-    <div class="tabbable">
-      <ul class="nav nav-pills">
-        <li class="active">
-          <a href="#metaTab_baseStats" data-toggle="tab">Base Stats</a>
-        </li>
-        <li class="">
-          <a href="#metaTab_localityStats" data-toggle="tab">Localities</a>
-        </li>
-        <li class="">
-          <a href="#metaTab_compactStats" data-toggle="tab">Compactions</a>
-        </li>
-      </ul>
-      <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px 
solid #ddd;">
-        <div class="tab-pane active" id="metaTab_baseStats">
-          <table id="tableRegionTable" class="tablesorter table table-striped">
-            <thead>
-            <tr>
-              <th>Name</th>
-              <th>Region Server</th>
-              <th>ReadRequests</th>
-              <th>WriteRequests</th>
-              <th>Uncompressed StoreFileSize</th>
-              <th>StorefileSize</th>
-              <th>Num.Storefiles</th>
-              <th>MemSize</th>
-              <th>Start Key</th>
-              <th>End Key</th>
-              <%
-                if (withReplica) {
-              %>
-              <th>ReplicaID</th>
-              <%
-                }
-              %>
-            </tr>
-            </thead>
-            <tbody>
-            <%
-              // NOTE: Presumes meta with one or more replicas
-              for (int j = 0; j < numMetaReplicas; j++) {
-                RegionInfo meta = RegionReplicaUtil.getRegionInfoForReplica(
-                        RegionInfoBuilder.FIRST_META_REGIONINFO, j);
-                //If a metaLocation is null, All of its info would be empty 
here to be displayed.
-                RegionStateNode rsn = 
master.getAssignmentManager().getRegionStates()
-                  .getRegionStateNode(meta);
-                ServerName metaLocation = rsn != null ? 
rsn.getRegionLocation() : null;
-                for (int i = 0; i < 1; i++) {
-                  //If metaLocation is null, default value below would be 
displayed in UI.
-                  String hostAndPort = "";
-                  String readReq = "N/A";
-                  String writeReq = "N/A";
-                  String fileSizeUncompressed = ZEROMB;
-                  String fileSize = ZEROMB;
-                  String fileCount = "N/A";
-                  String memSize = ZEROMB;
-                  if (metaLocation != null) {
-                    ServerMetrics 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.
-                    hostAndPort = 
URLEncoder.encode(metaLocation.getHostname()) + ":" + 
master.getRegionServerInfoPort(metaLocation);
-                    if (sl != null) {
-                      Map<byte[], RegionMetrics> map = sl.getRegionMetrics();
-                      if (map.containsKey(meta.getRegionName())) {
-                        RegionMetrics load = map.get(meta.getRegionName());
-                        readReq = String.format("%,1d", 
load.getReadRequestCount());
-                        writeReq = String.format("%,1d", 
load.getWriteRequestCount());
-                        double rSize = 
load.getStoreFileSize().get(Size.Unit.BYTE);
-                        if (rSize > 0) {
-                          fileSize = StringUtils.byteDesc((long) rSize);
-                        }
-                        double rSizeUncompressed = 
load.getUncompressedStoreFileSize().get(Size.Unit.BYTE);
-                        if (rSizeUncompressed > 0) {
-                          fileSizeUncompressed = StringUtils.byteDesc((long) 
rSizeUncompressed);
-                        }
-                        fileCount = String.format("%,1d", 
load.getStoreFileCount());
-                        double mSize = 
load.getMemStoreSize().get(Size.Unit.BYTE);
-                        if (mSize > 0) {
-                          memSize = StringUtils.byteDesc((long)mSize);
-                        }
-                      }
+</div>
+<div class="row">
+<% //Meta table.
+  if(fqtn.equals(TableName.META_TABLE_NAME.getNameAsString())) { %>
+<h2>Table Regions</h2>
+<div class="tabbable">
+  <ul class="nav nav-pills">
+    <li class="active"><a href="#metaTab_baseStats" data-toggle="tab">Base 
Stats</a></li>
+    <li class=""><a href="#metaTab_localityStats" 
data-toggle="tab">Localities</a></li>
+    <li class=""><a href="#metaTab_compactStats" 
data-toggle="tab">Compactions</a></li>
+  </ul>
+
+  <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px 
solid #ddd;">
+    <div class="tab-pane active" id="metaTab_baseStats">
+      <table id="metaTableBaseStatsTable" class="tablesorter table 
table-striped">
+        <thead>
+          <tr>
+            <th>Name</th>
+            <th>Region Server</th>
+            <th>ReadRequests</th>
+            <th>WriteRequests</th>
+            <th>Uncompressed StoreFileSize</th>
+            <th>StorefileSize</th>
+            <th>Num.Storefiles</th>
+            <th>MemSize</th>
+            <th>Start Key</th>
+            <th>End Key</th>
+            <th>ReplicaID</th>
+          </tr>
+        </thead>
+        <tbody>
+        <%
+          // NOTE: Presumes meta with one or more replicas
+          for (int j = 0; j < numMetaReplicas; j++) {
+            RegionInfo meta = RegionReplicaUtil.getRegionInfoForReplica(
+                    RegionInfoBuilder.FIRST_META_REGIONINFO, j);
+            //If a metaLocation is null, All of its info would be empty here 
to be displayed.
+            RegionStateNode rsn = 
master.getAssignmentManager().getRegionStates()
+              .getRegionStateNode(meta);
+            ServerName metaLocation = rsn != null ? rsn.getRegionLocation() : 
null;
+            for (int i = 0; i < 1; i++) {
+              //If metaLocation is null, default value below would be 
displayed in UI.
+              String hostAndPort = "";
+              String readReq = "N/A";
+              String writeReq = "N/A";
+              String fileSizeUncompressed = ZEROMB;
+              String fileSize = ZEROMB;
+              String fileCount = "N/A";
+              String memSize = ZEROMB;
+              if (metaLocation != null) {
+                ServerMetrics 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.
+                hostAndPort = URLEncoder.encode(metaLocation.getHostname()) + 
":" + master.getRegionServerInfoPort(metaLocation);
+                if (sl != null) {
+                  Map<byte[], RegionMetrics> map = sl.getRegionMetrics();
+                  if (map.containsKey(meta.getRegionName())) {
+                    RegionMetrics load = map.get(meta.getRegionName());
+                    readReq = String.format("%,1d", 
load.getReadRequestCount());
+                    writeReq = String.format("%,1d", 
load.getWriteRequestCount());
+                    double rSize = load.getStoreFileSize().get(Size.Unit.BYTE);
+                    if (rSize > 0) {
+                      fileSize = StringUtils.byteDesc((long) rSize);
+                    }
+                    double rSizeUncompressed = 
load.getUncompressedStoreFileSize().get(Size.Unit.BYTE);
+                    if (rSizeUncompressed > 0) {
+                      fileSizeUncompressed = StringUtils.byteDesc((long) 
rSizeUncompressed);
+                    }
+                    fileCount = String.format("%,1d", 
load.getStoreFileCount());
+                    double mSize = load.getMemStoreSize().get(Size.Unit.BYTE);
+                    if (mSize > 0) {
+                      memSize = StringUtils.byteDesc((long)mSize);
                     }
                   }
-            %>
-            <tr>
-              <td><%= escapeXml(meta.getRegionNameAsString()) %></td>
-              <td><a href="http://<%= hostAndPort %>/rs-status"><%= 
StringEscapeUtils.escapeHtml4(hostAndPort) %></a></td>
-              <td><%= readReq%></td>
-              <td><%= writeReq%></td>
-              <td><%= fileSizeUncompressed%></td>
-              <td><%= fileSize%></td>
-              <td><%= fileCount%></td>
-              <td><%= memSize%></td>
-              <td><%= escapeXml(Bytes.toString(meta.getStartKey())) %></td>
-              <td><%= escapeXml(Bytes.toString(meta.getEndKey())) %></td>
-              <%
-                if (withReplica) {
-              %>
-              <td><%= meta.getReplicaId() %></td>
-              <%
                 }
-              %>
-            </tr>
-            <%  } %>
-            <%} %>
-            </tbody>
-          </table>
-        </div>
-        <div class="tab-pane" id="metaTab_localityStats">
-           <table id="tableRegionTable" class="tablesorter table 
table-striped">
-             <thead>
-               <tr>
-                 <th>Name</th>
-                 <th>Region Server</th>
-                 <th>Locality</th>
-                 <th>LocalityForSsd</th>
-               </tr>
-             </thead>
-             <tbody>
-             <%
-               // NOTE: Presumes meta with one or more replicas
-               for (int j = 0; j < numMetaReplicas; j++) {
-                 RegionInfo meta = RegionReplicaUtil.getRegionInfoForReplica(
-                                         
RegionInfoBuilder.FIRST_META_REGIONINFO, j);
-                 //If a metaLocation is null, All of its info would be empty 
here to be displayed.
-                 RegionStateNode rsn = 
master.getAssignmentManager().getRegionStates()
-                   .getRegionStateNode(meta);
-                 ServerName metaLocation = rsn != null ? 
rsn.getRegionLocation() : null;
-                 for (int i = 0; i < 1; i++) {
-                   //If metaLocation is null, default value below would be 
displayed in UI.
-                   String hostAndPort = "";
-                   float locality = 0.0f;
-                   float localityForSsd = 0.0f;
-                   if (metaLocation != null) {
-                     ServerMetrics sl = 
master.getServerManager().getLoad(metaLocation);
-                     hostAndPort = 
URLEncoder.encode(metaLocation.getHostname()) + ":" + 
master.getRegionServerInfoPort(metaLocation);
-                     if (sl != null) {
-                       Map<byte[], RegionMetrics> map = sl.getRegionMetrics();
-                       if (map.containsKey(meta.getRegionName())) {
-                         RegionMetrics load = map.get(meta.getRegionName());
-                         locality = load.getDataLocality();
-                         localityForSsd = load.getDataLocalityForSsd();
-                       }
-                     }
+              }
+            %>
+          <tr>
+            <td><%= escapeXml(meta.getRegionNameAsString()) %></td>
+            <td><a href="http://<%= hostAndPort %>/rs-status"><%= 
StringEscapeUtils.escapeHtml4(hostAndPort) %></a></td>
+            <td><%= readReq%></td>
+            <td><%= writeReq%></td>
+            <td><%= fileSizeUncompressed%></td>
+            <td><%= fileSize%></td>
+            <td><%= fileCount%></td>
+            <td><%= memSize%></td>
+            <td><%= escapeXml(Bytes.toString(meta.getStartKey())) %></td>
+            <td><%= escapeXml(Bytes.toString(meta.getEndKey())) %></td>
+            <td><%= meta.getReplicaId() %></td>
+          </tr>
+        <%  } %>
+        <%} %>
+        </tbody>
+      </table>
+    </div>
+    <div class="tab-pane" id="metaTab_localityStats">
+       <table id="metaTableLocalityStatsTable" class="tablesorter table 
table-striped">
+         <thead>
+           <tr>
+             <th>Name</th>
+             <th>Region Server</th>
+             <th>Locality</th>
+             <th>LocalityForSsd</th>
+           </tr>
+         </thead>
+         <tbody>
+         <%
+           // NOTE: Presumes meta with one or more replicas
+           for (int j = 0; j < numMetaReplicas; j++) {
+             RegionInfo meta = RegionReplicaUtil.getRegionInfoForReplica(
+                                     RegionInfoBuilder.FIRST_META_REGIONINFO, 
j);
+             //If a metaLocation is null, All of its info would be empty here 
to be displayed.
+             RegionStateNode rsn = 
master.getAssignmentManager().getRegionStates()
+               .getRegionStateNode(meta);
+             ServerName metaLocation = rsn != null ? rsn.getRegionLocation() : 
null;
+             for (int i = 0; i < 1; i++) {
+               //If metaLocation is null, default value below would be 
displayed in UI.
+               String hostAndPort = "";
+               float locality = 0.0f;
+               float localityForSsd = 0.0f;
+               if (metaLocation != null) {
+                 ServerMetrics sl = 
master.getServerManager().getLoad(metaLocation);
+                 hostAndPort = URLEncoder.encode(metaLocation.getHostname()) + 
":" + master.getRegionServerInfoPort(metaLocation);
+                 if (sl != null) {
+                   Map<byte[], RegionMetrics> map = sl.getRegionMetrics();
+                   if (map.containsKey(meta.getRegionName())) {
+                     RegionMetrics load = map.get(meta.getRegionName());
+                     locality = load.getDataLocality();
+                     localityForSsd = load.getDataLocalityForSsd();
                    }
-                 %>
-               <tr>
-                 <td><%= escapeXml(meta.getRegionNameAsString()) %></td>
-                 <td><a href="http://<%= hostAndPort %>/rs-status"><%= 
StringEscapeUtils.escapeHtml4(hostAndPort) %></a></td>
-                 <td><%= locality%></td>
-                 <td><%= localityForSsd%></td>
-               </tr>
-             <%  } %>
-             <%} %>
-             </tbody>
-           </table>
-         </div>
-        <div class="tab-pane" id="metaTab_compactStats">
-          <table id="metaTableCompactStatsTable" class="tablesorter table 
table-striped">
-            <thead>
-            <tr>
-              <th>Name</th>
-              <th>Region Server</th>
-              <th>Num. Compacting Cells</th>
-              <th>Num. Compacted Cells</th>
-              <th>Remaining Cells</th>
-              <th>Compaction Progress</th>
-            </tr>
-            </thead>
-            <tbody>
-            <%
-              // NOTE: Presumes meta with one or more replicas
-              for (int j = 0; j < numMetaReplicas; j++) {
-                RegionInfo meta = RegionReplicaUtil.getRegionInfoForReplica(
+                 }
+               }
+             %>
+           <tr>
+             <td><%= escapeXml(meta.getRegionNameAsString()) %></td>
+             <td><a href="http://<%= hostAndPort %>/rs-status"><%= 
StringEscapeUtils.escapeHtml4(hostAndPort) %></a></td>
+             <td><%= locality%></td>
+             <td><%= localityForSsd%></td>
+           </tr>
+         <%  } %>
+         <%} %>
+         </tbody>
+       </table>
+     </div>
+    <div class="tab-pane" id="metaTab_compactStats">
+      <table id="metaTableCompactStatsTable" class="tablesorter table 
table-striped">
+        <thead>
+          <tr>
+            <th>Name</th>
+            <th>Region Server</th>
+            <th>Num. Compacting Cells</th>
+            <th>Num. Compacted Cells</th>
+            <th>Remaining Cells</th>
+            <th>Compaction Progress</th>
+          </tr>
+        </thead>
+        <tbody>
+        <%
+          // NOTE: Presumes meta with one or more replicas
+          for (int j = 0; j < numMetaReplicas; j++) {
+            RegionInfo meta = RegionReplicaUtil.getRegionInfoForReplica(
                         RegionInfoBuilder.FIRST_META_REGIONINFO, j);
-                //If a metaLocation is null, All of its info would be empty 
here to be displayed.
-                RegionStateNode rsn = 
master.getAssignmentManager().getRegionStates()
-                  .getRegionStateNode(meta);
-                ServerName metaLocation = rsn != null ? 
rsn.getRegionLocation() : null;
-                for (int i = 0; i < 1; i++) {
-                  //If metaLocation is null, default value below would be 
displayed in UI.
-                  String hostAndPort = "";
-                  long compactingCells = 0;
-                  long compactedCells = 0;
-                  String compactionProgress = "";
-                  if (metaLocation != null) {
-                    ServerMetrics sl = 
master.getServerManager().getLoad(metaLocation);
-                    hostAndPort = 
URLEncoder.encode(metaLocation.getHostname()) + ":" + 
master.getRegionServerInfoPort(metaLocation);
-                    if (sl != null) {
-                      Map<byte[], RegionMetrics> map = sl.getRegionMetrics();
-                      if (map.containsKey(meta.getRegionName())) {
-                        RegionMetrics load = map.get(meta.getRegionName());
-                        compactingCells = load.getCompactingCellCount();
-                        compactedCells = load.getCompactedCellCount();
-                        if (compactingCells > 0) {
-                          compactionProgress = String.format("%.2f", 100 * 
((float)
-                                  compactedCells / compactingCells)) + "%";
-                        }
-                      }
+            //If a metaLocation is null, All of its info would be empty here 
to be displayed.
+            RegionStateNode rsn = 
master.getAssignmentManager().getRegionStates()
+              .getRegionStateNode(meta);
+            ServerName metaLocation = rsn != null ? rsn.getRegionLocation() : 
null;
+            for (int i = 0; i < 1; i++) {
+              //If metaLocation is null, default value below would be 
displayed in UI.
+              String hostAndPort = "";
+              long compactingCells = 0;
+              long compactedCells = 0;
+              String compactionProgress = "";
+              if (metaLocation != null) {
+                ServerMetrics sl = 
master.getServerManager().getLoad(metaLocation);
+                hostAndPort = URLEncoder.encode(metaLocation.getHostname()) + 
":" + master.getRegionServerInfoPort(metaLocation);
+                if (sl != null) {
+                  Map<byte[], RegionMetrics> map = sl.getRegionMetrics();
+                  if (map.containsKey(meta.getRegionName())) {
+                    RegionMetrics load = map.get(meta.getRegionName());
+                    compactingCells = load.getCompactingCellCount();
+                    compactedCells = load.getCompactedCellCount();
+                    if (compactingCells > 0) {
+                      compactionProgress = String.format("%.2f", 100 * ((float)
+                              compactedCells / compactingCells)) + "%";
                     }
                   }
-            %>
-            <tr>
-              <td><%= escapeXml(meta.getRegionNameAsString()) %></td>
-              <td><a href="http://<%= hostAndPort %>/rs-status"><%= 
StringEscapeUtils.escapeHtml4(hostAndPort) %></a></td>
-              <td><%= String.format("%,1d", compactingCells)%></td>
-              <td><%= String.format("%,1d", compactedCells)%></td>
-              <td><%= String.format("%,1d", compactingCells - 
compactedCells)%></td>
-              <td><%= compactionProgress%></td>
-            </tr>
-            <%  } %>
-            <%} %>
-            </tbody>
-          </table>
-        </div>
-      </div>
+                }
+              }
+        %>
+          <tr>
+            <td><%= escapeXml(meta.getRegionNameAsString()) %></td>
+            <td><a href="http://<%= hostAndPort %>/rs-status"><%= 
StringEscapeUtils.escapeHtml4(hostAndPort) %></a></td>
+            <td><%= String.format("%,1d", compactingCells)%></td>
+            <td><%= String.format("%,1d", compactedCells)%></td>
+            <td><%= String.format("%,1d", compactingCells - 
compactedCells)%></td>
+            <td><%= compactionProgress%></td>
+          </tr>
+        <%  } %>
+        <%} %>
+        </tbody>
+      </table>
     </div>
-    <h2 id="meta-entries">Meta Entries</h2>
+  </div>
+</div>
+<h2 id="meta-entries">Meta Entries</h2>
 <%
   if (!metaBrowser.getErrorMessages().isEmpty()) {
     for (final String errorMessage : metaBrowser.getErrorMessages()) {
@@ -541,20 +583,20 @@
         splitRegions.entrySet().stream()
           .map(entry -> String.format(regionSpanFormat, entry.getKey(), 
entry.getValue().getRegionNameAsString()))
           .collect(Collectors.joining("<br/>"));
-%>
-        <tr>
-          <td title="<%= regionInfoColumnName %>"><%= regionNameDisplay %></td>
-          <td title="startKey"><%= startKeyDisplay %></td>
-          <td title="endKey"><%= endKeyDisplay %></td>
-          <td title="replicaId"><%= replicaIdDisplay %></td>
-          <td title="regionState"><%= regionStateDisplay %></td>
-          <td title="<%= serverColumnName + "," + startCodeColumnName %>"><%= 
serverName != null ? buildRegionServerLink(serverName, 
master.getRegionServerInfoPort(serverName), regionInfo, regionState) : "" 
%></td>
-          <td title="<%= seqNumColumnName %>"><%= seqNum %></td>
-          <td title="<%= serverNameColumnName %>"><%= targetServerName %></td>
-          <td><%= mergeRegionNames %></td>
-          <td><%= splitName %></td>
-        </tr>
-<%
+  %>
+    <tr>
+      <td title="<%= regionInfoColumnName %>"><%= regionNameDisplay %></td>
+      <td title="startKey"><%= startKeyDisplay %></td>
+      <td title="endKey"><%= endKeyDisplay %></td>
+      <td title="replicaId"><%= replicaIdDisplay %></td>
+      <td title="regionState"><%= regionStateDisplay %></td>
+      <td title="<%= serverColumnName + "," + startCodeColumnName %>"><%= 
buildRegionLink(serverName, master.getRegionServerInfoPort(serverName), 
regionInfo, regionState) %></td>
+      <td title="<%= seqNumColumnName %>"><%= seqNum %></td>
+      <td title="<%= serverNameColumnName %>"><%= targetServerName %></td>
+      <td><%= mergeRegionNames %></td>
+      <td><%= splitName %></td>
+    </tr>
+  <%
     }
 
     metaScanHasMore = results.hasMoreResults();
@@ -608,568 +650,491 @@
 <%
   }
 %>
-            </select>
-            <button type="submit" class="btn btn-primary" 
style="display:inline; width:auto">
-              Filter Results
-            </button>
-          </div>
-        </form>
+        </select>
+        <button type="submit" class="btn btn-primary" style="display:inline; 
width:auto">
+          Filter Results
+        </button>
       </div>
-    </div>
-    <%} else {
-      RegionStates states = master.getAssignmentManager().getRegionStates();
-      Map<RegionState.State, List<RegionInfo>> regionStates = 
states.getRegionByStateOfTable(table.getName());
-      Map<String, RegionState.State> stateMap = new HashMap<>();
-      for (RegionState.State regionState : regionStates.keySet()) {
-        for (RegionInfo regionInfo : regionStates.get(regionState)) {
-          stateMap.put(regionInfo.getEncodedName(), regionState);
-        }
+    </form>
+  </div>
+</div>
+<%} else {
+  //Common tables
+  RegionStates states = master.getAssignmentManager().getRegionStates();
+  Map<RegionState.State, List<RegionInfo>> regionStates = 
states.getRegionByStateOfTable(table.getName());
+  Map<String, RegionState.State> stateMap = new HashMap<>();
+  for (RegionState.State regionState : regionStates.keySet()) {
+    for (RegionInfo regionInfo : regionStates.get(regionState)) {
+      stateMap.put(regionInfo.getEncodedName(), regionState);
+    }
+  }
+  RegionLocator r = master.getConnection().getRegionLocator(table.getName());
+
+  try {
+%>
+<h2>Table Attributes</h2>
+<table class="table table-striped">
+  <tr>
+      <th>Attribute Name</th>
+      <th>Value</th>
+      <th>Description</th>
+  </tr>
+  <tr>
+      <td>Enabled</td>
+      <td><%= master.getTableStateManager().isTableState(table.getName(), 
TableState.State.ENABLED) %></td>
+      <td>Is the table enabled</td>
+  </tr>
+  <tr>
+      <td>Compaction</td>
+      <td>
+<%
+  if (master.getTableStateManager().isTableState(table.getName(), 
TableState.State.ENABLED)) {
+    CompactionState compactionState = 
master.getCompactionState(table.getName());
+    %><%= compactionState==null?"UNKNOWN":compactionState %><%
+  } else {
+  %><%= CompactionState.NONE %><%
+  }
+%>
+      </td>
+      <td>Is the table compacting</td>
+  </tr>
+<%  if (showFragmentation) { %>
+  <tr>
+      <td>Fragmentation</td>
+      <td><%= frags.get(fqtn) != null ? frags.get(fqtn).intValue() + "%" : 
"n/a" %></td>
+      <td>How fragmented is the table. After a major compaction it is 0%.</td>
+  </tr>
+<%  } %>
+<%
+  if (quotasEnabled) {
+    TableName tn = TableName.valueOf(fqtn);
+    SpaceQuotaSnapshot masterSnapshot = null;
+    Quotas quota = QuotaTableUtil.getTableQuota(master.getConnection(), tn);
+    if (quota == null || !quota.hasSpace()) {
+      quota = QuotaTableUtil.getNamespaceQuota(master.getConnection(), 
tn.getNamespaceAsString());
+      if (quota != null) {
+        masterSnapshot = 
master.getQuotaObserverChore().getNamespaceQuotaSnapshots()
+          .get(tn.getNamespaceAsString());
       }
-      RegionLocator r = 
master.getConnection().getRegionLocator(table.getName());
-      try { %>
-    <h2>Table Attributes</h2>
-    <table class="table table-striped">
-      <tr>
-        <th>Attribute Name</th>
-        <th>Value</th>
-        <th>Description</th>
-      </tr>
-      <tr>
-        <td>Enabled</td>
-        <td><%= master.getTableStateManager().isTableState(table.getName(), 
TableState.State.ENABLED) %></td>
-        <td>Is the table enabled</td>
-      </tr>
-      <tr>
-        <td>Compaction</td>
-        <td>
-          <%
-            if (master.getTableStateManager().isTableState(table.getName(), 
TableState.State.ENABLED)) {
-              CompactionState compactionState = 
master.getCompactionState(table.getName());
-              %><%= compactionState==null?"UNKNOWN":compactionState %><%
-            } else {
-            %><%= CompactionState.NONE %><%
-            }
-            %>
-        </td>
-        <td>Is the table compacting</td>
-      </tr>
-      <%  if (showFragmentation) { %>
-      <tr>
-        <td>Fragmentation</td>
-        <td><%= frags.get(fqtn) != null ? frags.get(fqtn).intValue() + "%" : 
"n/a" %></td>
-        <td>How fragmented is the table. After a major compaction it is 
0%.</td>
-      </tr>
-      <%  } %>
-      <%
-        if (quotasEnabled) {
-          TableName tn = TableName.valueOf(fqtn);
-          SpaceQuotaSnapshot masterSnapshot = null;
-          Quotas quota = QuotaTableUtil.getTableQuota(master.getConnection(), 
tn);
-          if (quota == null || !quota.hasSpace()) {
-            quota = QuotaTableUtil.getNamespaceQuota(master.getConnection(), 
tn.getNamespaceAsString());
-            if (quota != null) {
-              masterSnapshot = 
master.getQuotaObserverChore().getNamespaceQuotaSnapshots()
-                      .get(tn.getNamespaceAsString());
-            }
-          } else {
-            masterSnapshot = 
master.getQuotaObserverChore().getTableQuotaSnapshots().get(tn);
-          }
-          if (quota != null && quota.hasSpace()) {
-            SpaceQuota spaceQuota = quota.getSpace();
-      %>
-      <tr>
-        <td>Space Quota</td>
-        <td>
-          <table>
-            <tr>
-              <th>Property</th>
-              <th>Value</th>
-            </tr>
-            <tr>
-              <td>Limit</td>
-              <td><%= StringUtils.byteDesc(spaceQuota.getSoftLimit()) %></td>
-            </tr>
-            <tr>
-              <td>Policy</td>
-              <td><%= spaceQuota.getViolationPolicy() %></td>
-            </tr>
-            <%
-              if (masterSnapshot != null) {
-            %>
-            <tr>
-              <td>Usage</td>
-              <td><%= StringUtils.byteDesc(masterSnapshot.getUsage()) %></td>
-            </tr>
-            <tr>
-              <td>State</td>
-              <td><%= masterSnapshot.getQuotaStatus().isInViolation() ? "In 
Violation" : "In Observance" %></td>
-            </tr>
-            <%
-              }
-            %>
-          </table>
-        </td>
-        <td>Information about a Space Quota on this table, if set.</td>
-      </tr>
-      <%
-        }
-        if (quota != null && quota.hasThrottle()) {
-          List<ThrottleSettings> throttles = 
QuotaSettingsFactory.fromTableThrottles(table.getName(), quota.getThrottle());
-          if (throttles.size() > 0) {
-      %>
-      <tr>
-        <td>Throttle Quota</td>
-        <td>
-          <table>
-            <tr>
-              <th>Limit</th>
-              <th>Type</th>
-              <th>TimeUnit</th>
-              <th>Scope</th>
-            </tr>
-            <%
-              for (ThrottleSettings throttle : throttles) {
-            %>
-            <tr>
-              <td><%= throttle.getSoftLimit() %></td>
-              <td><%= throttle.getThrottleType() %></td>
-              <td><%= throttle.getTimeUnit() %></td>
-              <td><%= throttle.getQuotaScope() %></td>
-            </tr>
-            <%
-              }
-            %>
-          </table>
-        </td>
-        <td>Information about a Throttle Quota on this table, if set.</td>
-      </tr>
+    } else {
+      masterSnapshot = 
master.getQuotaObserverChore().getTableQuotaSnapshots().get(tn);
+    }
+    if (quota != null && quota.hasSpace()) {
+      SpaceQuota spaceQuota = quota.getSpace();
+%>
+  <tr>
+    <td>Space Quota</td>
+    <td>
+      <table>
+        <tr>
+          <th>Property</th>
+          <th>Value</th>
+        </tr>
+        <tr>
+          <td>Limit</td>
+          <td><%= StringUtils.byteDesc(spaceQuota.getSoftLimit()) %></td>
+        </tr>
+        <tr>
+          <td>Policy</td>
+          <td><%= spaceQuota.getViolationPolicy() %></td>
+        </tr>
+<%
+      if (masterSnapshot != null) {
+%>
+        <tr>
+          <td>Usage</td>
+          <td><%= StringUtils.byteDesc(masterSnapshot.getUsage()) %></td>
+        </tr>
+        <tr>
+          <td>State</td>
+          <td><%= masterSnapshot.getQuotaStatus().isInViolation() ? "In 
Violation" : "In Observance" %></td>
+        </tr>
+<%
+      }
+%>
+      </table>
+    </td>
+    <td>Information about a Space Quota on this table, if set.</td>
+  </tr>
+<%
+    }
+  if (quota != null && quota.hasThrottle()) {
+    List<ThrottleSettings> throttles = 
QuotaSettingsFactory.fromTableThrottles(table.getName(), quota.getThrottle());
+    if (throttles.size() > 0) {
+%>
+  <tr>
+    <td>Throttle Quota</td>
+    <td>
+      <table>
+        <tr>
+          <th>Limit</th>
+          <th>Type</th>
+          <th>TimeUnit</th>
+          <th>Scope</th>
+        </tr>
+<%
+    for (ThrottleSettings throttle : throttles) {
+%>
+        <tr>
+          <td><%= throttle.getSoftLimit() %></td>
+          <td><%= throttle.getThrottleType() %></td>
+          <td><%= throttle.getTimeUnit() %></td>
+          <td><%= throttle.getQuotaScope() %></td>
+        </tr>
+<%
+    }
+%>
+      </table>
+    </td>
+    <td>Information about a Throttle Quota on this table, if set.</td>
+  </tr>
+<%
+    }
+   }
+ }
+%>
+</table>
+<h2>Table Schema</h2>
+<table class="table table-striped">
+<%
+ColumnFamilyDescriptor[] families = table.getDescriptor().getColumnFamilies();
+Set<Bytes> familyKeySet = new HashSet<>();
+for (ColumnFamilyDescriptor family: families) {
+  familyKeySet.addAll(family.getValues().keySet());
+}
+%>
+<tr>
+  <th>Property \ Column Family Name</th>
+  <%
+  for (ColumnFamilyDescriptor family: families) {
+  %>
+  <th>
+    <%= StringEscapeUtils.escapeHtml4(family.getNameAsString()) %>
+  </th>
+  <% } %>
+</tr>
+  <%
+  for (Bytes familyKey: familyKeySet) {
+  %>
+    <tr>
+      <td>
+        <%= StringEscapeUtils.escapeHtml4(familyKey.toString()) %>
+      </td>
       <%
-            }
-          }
+      for (ColumnFamilyDescriptor family: families) {
+        String familyValue = "-";
+        if(family.getValues().containsKey(familyKey)){
+          familyValue = family.getValues().get(familyKey).toString();
         }
       %>
-    </table>
-    <h2>Table Schema</h2>
-    <table class="table table-striped">
-    <%
-      ColumnFamilyDescriptor[] families = 
table.getDescriptor().getColumnFamilies();
-      Set<Bytes> familyKeySet = new HashSet<>();
-      for (ColumnFamilyDescriptor family: families) {
-        familyKeySet.addAll(family.getValues().keySet());
-      }
-    %>
-      <tr>
-        <th>Property \ Column Family Name</th>
-        <%
-        for (ColumnFamilyDescriptor family: families) {
-        %>
-        <th>
-          <%= StringEscapeUtils.escapeHtml4(family.getNameAsString()) %>
-        </th>
-        <% } %>
-      </tr>
-        <%
-        for (Bytes familyKey: familyKeySet) {
-        %>
-          <tr>
-            <td>
-              <%= StringEscapeUtils.escapeHtml4(familyKey.toString()) %>
-            </td>
-            <%
-            for (ColumnFamilyDescriptor family: families) {
-              String familyValue = "-";
-              if(family.getValues().containsKey(familyKey)){
-                familyValue = family.getValues().get(familyKey).toString();
-              }
-            %>
-            <td>
-              <%= StringEscapeUtils.escapeHtml4(familyValue) %>
-            </td>
-            <% } %>
-          </tr>
-        <% } %>
-    </table>
-    <%
-      long totalReadReq = 0;
-      long totalWriteReq = 0;
-      long totalSizeUncompressed = 0;
-      long totalSize = 0;
-      long totalStoreFileCount = 0;
-      long totalMemSize = 0;
-      long totalCompactingCells = 0;
-      long totalCompactedCells = 0;
-      long totalBlocksTotalWeight = 0;
-      long totalBlocksLocalWeight = 0;
-      long totalBlocksLocalWithSsdWeight = 0;
-      String totalCompactionProgress = "";
-      String totalMemSizeStr = ZEROMB;
-      String totalSizeUncompressedStr = ZEROMB;
-      String totalSizeStr = ZEROMB;
-      String totalLocality = "";
-      String totalLocalityForSsd = "";
-      String urlRegionServer = null;
-      Map<ServerName, Integer> regDistribution = new TreeMap<>();
-      Map<ServerName, Integer> primaryRegDistribution = new TreeMap<>();
-      List<HRegionLocation> regions = r.getAllRegionLocations();
-      Map<RegionInfo, RegionMetrics> regionsToLoad = new LinkedHashMap<>();
-      Map<RegionInfo, ServerName> regionsToServer = new LinkedHashMap<>();
-      for (HRegionLocation hriEntry : regions) {
-        RegionInfo regionInfo = hriEntry.getRegionInfo();
-        ServerName addr = hriEntry.getServerName();
-        regionsToServer.put(regionInfo, addr);
+      <td>
+        <%= StringEscapeUtils.escapeHtml4(familyValue) %>
+      </td>
+      <% } %>
+    </tr>
+  <% } %>
+</table>
+<%
+  long totalReadReq = 0;
+  long totalWriteReq = 0;
+  long totalSizeUncompressed = 0;
+  long totalSize = 0;
+  long totalStoreFileCount = 0;
+  long totalMemSize = 0;
+  long totalCompactingCells = 0;
+  long totalCompactedCells = 0;
+  long totalBlocksTotalWeight = 0;
+  long totalBlocksLocalWeight = 0;
+  long totalBlocksLocalWithSsdWeight = 0;
+  String totalCompactionProgress = "";
+  String totalMemSizeStr = ZEROMB;
+  String totalSizeUncompressedStr = ZEROMB;
+  String totalSizeStr = ZEROMB;
+  String totalLocality = "";
+  String totalLocalityForSsd = "";
+  String urlRegionServer = null;
+  Map<ServerName, Integer> regDistribution = new TreeMap<>();
+  Map<ServerName, Integer> primaryRegDistribution = new TreeMap<>();
+  List<HRegionLocation> regions = r.getAllRegionLocations();
+  Map<RegionInfo, RegionMetrics> regionsToLoad = new LinkedHashMap<>();
+  Map<RegionInfo, ServerName> regionsToServer = new LinkedHashMap<>();
+  for (HRegionLocation hriEntry : regions) {
+    RegionInfo regionInfo = hriEntry.getRegionInfo();
+    ServerName addr = hriEntry.getServerName();
+    regionsToServer.put(regionInfo, addr);
 
-        if (addr != null) {
-          ServerMetrics sl = master.getServerManager().getLoad(addr);
-          if (sl != null) {
-            RegionMetrics regionMetrics = 
sl.getRegionMetrics().get(regionInfo.getRegionName());
-            regionsToLoad.put(regionInfo, regionMetrics);
-            if (regionMetrics != null) {
-              totalReadReq += regionMetrics.getReadRequestCount();
-              totalWriteReq += regionMetrics.getWriteRequestCount();
-              totalSizeUncompressed += 
regionMetrics.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
-              totalSize += 
regionMetrics.getStoreFileSize().get(Size.Unit.MEGABYTE);
-              totalStoreFileCount += regionMetrics.getStoreFileCount();
-              totalMemSize += 
regionMetrics.getMemStoreSize().get(Size.Unit.MEGABYTE);
-              totalStoreFileSizeMB += 
regionMetrics.getStoreFileSize().get(Size.Unit.MEGABYTE);
-              totalCompactingCells += regionMetrics.getCompactingCellCount();
-              totalCompactedCells += regionMetrics.getCompactedCellCount();
-              totalBlocksTotalWeight += regionMetrics.getBlocksTotalWeight();
-              totalBlocksLocalWeight += regionMetrics.getBlocksLocalWeight();
-              totalBlocksLocalWithSsdWeight += 
regionMetrics.getBlocksLocalWithSsdWeight();
-            } else {
-              RegionMetrics load0 = getEmptyRegionMetrics(regionInfo);
-              regionsToLoad.put(regionInfo, load0);
-            }
-          } else{
-            RegionMetrics load0 = getEmptyRegionMetrics(regionInfo);
-            regionsToLoad.put(regionInfo, load0);
-          }
+    if (addr != null) {
+      ServerMetrics sl = master.getServerManager().getLoad(addr);
+      if (sl != null) {
+        RegionMetrics regionMetrics = 
sl.getRegionMetrics().get(regionInfo.getRegionName());
+        regionsToLoad.put(regionInfo, regionMetrics);
+        if (regionMetrics != null) {
+          totalReadReq += regionMetrics.getReadRequestCount();
+          totalWriteReq += regionMetrics.getWriteRequestCount();
+          totalSizeUncompressed += 
regionMetrics.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
+          totalSize += 
regionMetrics.getStoreFileSize().get(Size.Unit.MEGABYTE);
+          totalStoreFileCount += regionMetrics.getStoreFileCount();
+          totalMemSize += 
regionMetrics.getMemStoreSize().get(Size.Unit.MEGABYTE);
+          totalStoreFileSizeMB += 
regionMetrics.getStoreFileSize().get(Size.Unit.MEGABYTE);
+          totalCompactingCells += regionMetrics.getCompactingCellCount();
+          totalCompactedCells += regionMetrics.getCompactedCellCount();
+          totalBlocksTotalWeight += regionMetrics.getBlocksTotalWeight();
+          totalBlocksLocalWeight += regionMetrics.getBlocksLocalWeight();
+          totalBlocksLocalWithSsdWeight += 
regionMetrics.getBlocksLocalWithSsdWeight();
         } else {
           RegionMetrics load0 = getEmptyRegionMetrics(regionInfo);
           regionsToLoad.put(regionInfo, load0);
         }
+      } else{
+        RegionMetrics load0 = getEmptyRegionMetrics(regionInfo);
+        regionsToLoad.put(regionInfo, load0);
       }
-      if (totalSize > 0) {
-        totalSizeStr = StringUtils.byteDesc(totalSize*1024l*1024);
-      }
-      if (totalSizeUncompressed > 0){
-        totalSizeUncompressedStr = 
StringUtils.byteDesc(totalSizeUncompressed*1024l*1024);
-      }
-      if (totalMemSize > 0) {
-        totalMemSizeStr = StringUtils.byteDesc(totalMemSize*1024l*1024);
-      }
-      if (totalCompactingCells > 0) {
-        totalCompactionProgress = String.format("%.2f", 100 *
-                ((float) totalCompactedCells / totalCompactingCells)) + "%";
-      }
-      if (totalBlocksTotalWeight > 0) {
-        totalLocality = String.format("%.1f",
-          ((float) totalBlocksLocalWeight / totalBlocksTotalWeight));
-        totalLocalityForSsd = String.format("%.1f",
-          ((float) totalBlocksLocalWithSsdWeight / totalBlocksTotalWeight));
-      }
-      if(regions != null && regions.size() > 0) { %>
-    <h2>Table Regions</h2>
-    <div class="tabbable">
-      <ul class="nav nav-pills">
-        <li class="active">
-          <a href="#tab_baseStats" data-toggle="tab">Base Stats</a>
-        </li>
-        <li class="">
-          <a href="#tab_localityStats" data-toggle="tab">Localities</a>
-        </li>
-        <li class="">
-          <a href="#tab_compactStats" data-toggle="tab">Compactions</a>
-        </li>
-      </ul>
-      <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px 
solid #ddd;">
-        <div class="tab-pane active" id="tab_baseStats">
-          <table id="regionServerDetailsTable" class="tablesorter table 
table-striped">
-            <thead>
-            <tr>
-              <th>Name(<%= String.format("%,1d", regions.size())%>)</th>
-              <th>Region Server</th>
-              <th>ReadRequests<br>(<%= String.format("%,1d", 
totalReadReq)%>)</th>
-              <th>WriteRequests<br>(<%= String.format("%,1d", 
totalWriteReq)%>)</th>
-              <th>Uncompressed StoreFileSize<br>(<%= totalSizeUncompressedStr 
%>)</th>
-              <th>StorefileSize<br>(<%= totalSizeStr %>)</th>
-              <th>Num.Storefiles<br>(<%= String.format("%,1d", 
totalStoreFileCount)%>)</th>
-              <th>MemSize<br>(<%= totalMemSizeStr %>)</th>
-              <th>Start Key</th>
-              <th>End Key</th>
-              <th>Region State</th>
-              <%
-                if (withReplica) {
-              %>
-              <th>ReplicaID</th>
-              <%
-                }
-              %>
-            </tr>
-            </thead>
-            <tbody>
-            <%
-              List<Map.Entry<RegionInfo, RegionMetrics>> entryList = new 
ArrayList<>(regionsToLoad.entrySet());
-              numRegions = regions.size();
-              int numRegionsRendered = 0;
-              // render all regions
-              if (numRegionsToRender < 0) {
-                numRegionsToRender = numRegions;
+    } else {
+      RegionMetrics load0 = getEmptyRegionMetrics(regionInfo);
+      regionsToLoad.put(regionInfo, load0);
+    }
+  }
+  if (totalSize > 0) {
+    totalSizeStr = StringUtils.byteDesc(totalSize*1024l*1024);
+  }
+  if (totalSizeUncompressed > 0){
+    totalSizeUncompressedStr = 
StringUtils.byteDesc(totalSizeUncompressed*1024l*1024);
+  }
+  if (totalMemSize > 0) {
+    totalMemSizeStr = StringUtils.byteDesc(totalMemSize*1024l*1024);
+  }
+  if (totalCompactingCells > 0) {
+    totalCompactionProgress = String.format("%.2f", 100 *
+            ((float) totalCompactedCells / totalCompactingCells)) + "%";
+  }
+  if (totalBlocksTotalWeight > 0) {
+    totalLocality = String.format("%.1f",
+      ((float) totalBlocksLocalWeight / totalBlocksTotalWeight));
+    totalLocalityForSsd = String.format("%.1f",
+      ((float) totalBlocksLocalWithSsdWeight / totalBlocksTotalWeight));
+  }
+  if(regions != null && regions.size() > 0) { %>
+<h2>Table Regions</h2>
+<div class="tabbable">
+  <ul class="nav nav-pills">
+    <li class="active"><a href="#tab_baseStats" data-toggle="tab">Base 
Stats</a></li>
+    <li class=""><a href="#tab_localityStats" 
data-toggle="tab">Localities</a></li>
+    <li class=""><a href="#tab_compactStats" 
data-toggle="tab">Compactions</a></li>
+  </ul>
+  <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px 
solid #ddd;">
+    <div class="tab-pane active" id="tab_baseStats">
+      <table id="tableBaseStatsTable" class="tablesorter table table-striped">
+        <thead>
+          <tr>
+            <th>Name(<%= String.format("%,1d", regions.size())%>)</th>
+            <th>Region Server</th>
+            <th>ReadRequests<br>(<%= String.format("%,1d", 
totalReadReq)%>)</th>
+            <th>WriteRequests<br>(<%= String.format("%,1d", 
totalWriteReq)%>)</th>
+            <th>Uncompressed StoreFileSize<br>(<%= totalSizeUncompressedStr 
%>)</th>
+            <th>StorefileSize<br>(<%= totalSizeStr %>)</th>
+            <th>Num.Storefiles<br>(<%= String.format("%,1d", 
totalStoreFileCount)%>)</th>
+            <th>MemSize<br>(<%= totalMemSizeStr %>)</th>
+            <th>Start Key</th>
+            <th>End Key</th>
+            <th>Region State</th>
+            <th>ReplicaID</th>
+          </tr>
+        </thead>
+        <tbody>
+        <%
+          List<Map.Entry<RegionInfo, RegionMetrics>> entryList = new 
ArrayList<>(regionsToLoad.entrySet());
+          numRegions = regions.size();
+          int numRegionsRendered = 0;
+          // render all regions
+          if (numRegionsToRender < 0) {
+            numRegionsToRender = numRegions;
+          }
+          for (Map.Entry<RegionInfo, RegionMetrics> hriEntry : entryList) {
+            RegionInfo regionInfo = hriEntry.getKey();
+            ServerName addr = regionsToServer.get(regionInfo);
+            RegionMetrics load = hriEntry.getValue();
+            String readReq = "N/A";
+            String writeReq = "N/A";
+            String regionSizeUncompressed = ZEROMB;
+            String regionSize = ZEROMB;
+            String fileCount = "N/A";
+            String memSize = ZEROMB;
+            String state = "N/A";
+            if (load != null) {
+              readReq = String.format("%,1d", load.getReadRequestCount());
+              writeReq = String.format("%,1d", load.getWriteRequestCount());
+              double rSize = load.getStoreFileSize().get(Size.Unit.BYTE);
+              if (rSize > 0) {
+                regionSize = StringUtils.byteDesc((long)rSize);
               }
-              for (Map.Entry<RegionInfo, RegionMetrics> hriEntry : entryList) {
-                RegionInfo regionInfo = hriEntry.getKey();
-                ServerName addr = regionsToServer.get(regionInfo);
-                RegionMetrics load = hriEntry.getValue();
-                String readReq = "N/A";
-                String writeReq = "N/A";
-                String regionSizeUncompressed = ZEROMB;
-                String regionSize = ZEROMB;
-                String fileCount = "N/A";
-                String memSize = ZEROMB;
-                String state = "N/A";
-                if (load != null) {
-                  readReq = String.format("%,1d", load.getReadRequestCount());
-                  writeReq = String.format("%,1d", 
load.getWriteRequestCount());
-                  double rSize = load.getStoreFileSize().get(Size.Unit.BYTE);
-                  if (rSize > 0) {
-                    regionSize = StringUtils.byteDesc((long)rSize);
-                  }
-                  double rSizeUncompressed = 
load.getUncompressedStoreFileSize().get(Size.Unit.BYTE);
-                  if (rSizeUncompressed > 0) {
-                    regionSizeUncompressed = 
StringUtils.byteDesc((long)rSizeUncompressed);
-                  }
-                  fileCount = String.format("%,1d", load.getStoreFileCount());
-                  double mSize = load.getMemStoreSize().get(Size.Unit.BYTE);
-                  if (mSize > 0) {
-                    memSize = StringUtils.byteDesc((long)mSize);
-                  }
-                }
-                if (stateMap.containsKey(regionInfo.getEncodedName())) {
-                  state = stateMap.get(regionInfo.getEncodedName()).toString();
-                }
-                if (addr != null) {
-                  ServerMetrics sl = master.getServerManager().getLoad(addr);
-                  // This port might be wrong if RS actually ended up using 
something else.
-                  urlRegionServer =
-                          "//" + URLEncoder.encode(addr.getHostname()) + ":" + 
master.getRegionServerInfoPort(addr) + "/rs-status";
-                  if(sl != null) {
-                    Integer i = regDistribution.get(addr);
-                    if (null == i) i = Integer.valueOf(0);
-                    regDistribution.put(addr, i + 1);
-                    if (withReplica && 
RegionReplicaUtil.isDefaultReplica(regionInfo.getReplicaId())) {
-                      i = primaryRegDistribution.get(addr);
-                      if (null == i) i = Integer.valueOf(0);
-                      primaryRegDistribution.put(addr, i+1);
-                    }
-                  }
-                }
-                if (numRegionsRendered < numRegionsToRender) {
-                  numRegionsRendered++;
-            %>
-            <tr>
-              <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) %></td>
-              <%
-                if (urlRegionServer != null) {
-              %>
-              <td>
-                <a href="<%= urlRegionServer %>"><%= addr == null? "-": 
StringEscapeUtils.escapeHtml4(addr.getHostname().toString()) + ":" + 
master.getRegionServerInfoPort(addr) %></a>
-              </td>
-              <%
-              } else {
-              %>
-              <td class="undeployed-region">not deployed</td>
-              <%
-                }
-              %>
-              <td><%= readReq%></td>
-              <td><%= writeReq%></td>
-              <td><%= regionSizeUncompressed%></td>
-              <td><%= regionSize%></td>
-              <td><%= fileCount%></td>
-              <td><%= memSize%></td>
-              <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getStartKey()))%></td>
-              <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getEndKey()))%></td>
-              <td><%= state%></td>
-              <%
-                if (withReplica) {
-              %>
-              <td><%= regionInfo.getReplicaId() %></td>
-              <%
-                }
-              %>
-            </tr>
-            <% } %>
-            <% } %>
-            </tbody>
-          </table>
-          <% if (numRegions > numRegionsRendered) {
-            String allRegionsUrl = "?name=" + URLEncoder.encode(fqtn,"UTF-8") 
+ "&numRegions=all";
-          %>
-          <p>This table has <b><%= numRegions %></b> regions in total, in 
order to improve the page load time,
-            only <b><%= numRegionsRendered %></b> regions are displayed here, 
<a href="<%= allRegionsUrl %>">click
-              here</a> to see all regions.</p>
-          <% } %>
-        </div>
-        <div class="tab-pane" id="tab_localityStats">
-          <table id="regionServerDetailsTable" class="tablesorter table 
table-striped">
-            <thead>
-              <tr>
-                <th>Name(<%= String.format("%,1d", regions.size())%>)</th>
-                <th>Region Server</th>
-                <th>Locality<br>(<%= totalLocality %>)</th>
-                <th>LocalityForSsd<br>(<%= totalLocalityForSsd %>)</th>
-              </tr>
-            </thead>
-            <tbody>
-            <%
-              numRegionsRendered = 0;
-              for (Map.Entry<RegionInfo, RegionMetrics> hriEntry : entryList) {
-                RegionInfo regionInfo = hriEntry.getKey();
-                ServerName addr = regionsToServer.get(regionInfo);
-                RegionMetrics load = hriEntry.getValue();
-                float locality = 0.0f;
-                float localityForSsd = 0.0f;
-                String state = "N/A";
-                if (load != null) {
-                  locality = load.getDataLocality();
-                  localityForSsd = load.getDataLocalityForSsd();
-                }
-                if (addr != null) {
-                  // This port might be wrong if RS actually ended up using 
something else.
-                  urlRegionServer =
-                    "//" + URLEncoder.encode(addr.getHostname()) + ":" + 
master.getRegionServerInfoPort(addr) + "/rs-status";
-                }
-                if (numRegionsRendered < numRegionsToRender) {
-                  numRegionsRendered++;
-            %>
-            <tr>
-              <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) %></td>
-              <%
-              if (urlRegionServer != null) {
-              %>
-              <td>
-                 <a href="<%= urlRegionServer %>"><%= addr == null? "-": 
StringEscapeUtils.escapeHtml4(addr.getHostname().toString()) + ":" + 
master.getRegionServerInfoPort(addr) %></a>
-              </td>
-              <%
-              } else {
-              %>
-              <td class="undeployed-region">not deployed</td>
-              <%
+              double rSizeUncompressed = 
load.getUncompressedStoreFileSize().get(Size.Unit.BYTE);
+              if (rSizeUncompressed > 0) {
+                regionSizeUncompressed = 
StringUtils.byteDesc((long)rSizeUncompressed);
               }
-              %>
-              <td><%= locality%></td>
-              <td><%= localityForSsd%></td>
-            </tr>
-            <% } %>
-            <% } %>
-            </tbody>
-          </table>
-        </div>
-        <div class="tab-pane" id="tab_compactStats">
-          <table id="tableCompactStatsTable" class="tablesorter table 
table-striped">
-            <thead>
-            <tr>
-              <th>Name(<%= String.format("%,1d", regions.size())%>)</th>
-              <th>Region Server</th>
-              <th>Num. Compacting Cells<br>(<%= String.format("%,1d", 
totalCompactingCells)%>)</th>
-              <th>Num. Compacted Cells<br>(<%= String.format("%,1d", 
totalCompactedCells)%>)</th>
-              <th>Remaining Cells<br>(<%= String.format("%,1d", 
totalCompactingCells-totalCompactedCells)%>)</th>
-              <th>Compaction Progress<br>(<%= totalCompactionProgress %>)</th>
-            </tr>
-            </thead>
-            <tbody>
-            <%
-              numRegionsRendered = 0;
-              for (Map.Entry<RegionInfo, RegionMetrics> hriEntry : entryList) {
-                RegionInfo regionInfo = hriEntry.getKey();
-                ServerName addr = regionsToServer.get(regionInfo);
-                RegionMetrics load = hriEntry.getValue();
-                long compactingCells = 0;
-                long compactedCells = 0;
-                String compactionProgress = "";
-                if (load != null) {
-                  compactingCells = load.getCompactingCellCount();
-                  compactedCells = load.getCompactedCellCount();
-                  if (compactingCells > 0) {
-                    compactionProgress = String.format("%.2f", 100 * ((float)
-                            compactedCells / compactingCells)) + "%";
-                  }
-                }
-                if (addr != null) {
-                  // This port might be wrong if RS actually ended up using 
something else.
-                  urlRegionServer =
-                          "//" + URLEncoder.encode(addr.getHostname()) + ":" + 
master.getRegionServerInfoPort(addr) + "/rs-status";
-                }
-                if (numRegionsRendered < numRegionsToRender) {
-                  numRegionsRendered++;
-            %>
-            <tr>
-              <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) %></td>
-              <%
-                if (urlRegionServer != null) {
-              %>
-              <td>
-                <a href="<%= urlRegionServer %>"><%= addr == null? "-": 
StringEscapeUtils.escapeHtml4(addr.getHostname().toString()) + ":" + 
master.getRegionServerInfoPort(addr) %></a>
-              </td>
-              <%
-              } else {
-              %>
-              <td class="undeployed-region">not deployed</td>
-              <%
+              fileCount = String.format("%,1d", load.getStoreFileCount());
+              double mSize = load.getMemStoreSize().get(Size.Unit.BYTE);
+              if (mSize > 0) {
+                memSize = StringUtils.byteDesc((long)mSize);
+              }
+            }
+
+            if (stateMap.containsKey(regionInfo.getEncodedName())) {
+              state = stateMap.get(regionInfo.getEncodedName()).toString();
+            }
+
+            if (addr != null) {
+              ServerMetrics sl = master.getServerManager().getLoad(addr);
+              if(sl != null) {
+                Integer i = regDistribution.get(addr);
+                if (null == i) i = Integer.valueOf(0);
+                regDistribution.put(addr, i + 1);
+                if 
(RegionReplicaUtil.isDefaultReplica(regionInfo.getReplicaId())) {
+                  i = primaryRegDistribution.get(addr);
+                  if (null == i) i = Integer.valueOf(0);
+                  primaryRegDistribution.put(addr, i+1);
                 }
-              %>
-              <td><%= String.format("%,1d", compactingCells)%></td>
-              <td><%= String.format("%,1d", compactedCells)%></td>
-              <td><%= String.format("%,1d", compactingCells - 
compactedCells)%></td>
-              <td><%= compactionProgress%></td>
-            </tr>
-            <% } %>
-            <% } %>
-            </tbody>
-          </table>
-          <% if (numRegions > numRegionsRendered) {
-            String allRegionsUrl = "?name=" + URLEncoder.encode(fqtn,"UTF-8") 
+ "&numRegions=all";
-          %>
-          <p>This table has <b><%= numRegions %></b> regions in total, in 
order to improve the page load time,
-            only <b><%= numRegionsRendered %></b> regions are displayed here, 
<a href="<%= allRegionsUrl %>">click
-              here</a> to see all regions.</p>
-          <% } %>
-        </div>
-      </div>
+              }
+            }
+            if (numRegionsRendered < numRegionsToRender) {
+              numRegionsRendered++;
+        %>
+        <tr>
+          <td><%= escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) 
%></td>
+          <%= buildRegionDeployedServerTag(regionInfo, master, 
regionsToServer) %>
+          <td><%= readReq%></td>
+          <td><%= writeReq%></td>
+          <td><%= regionSizeUncompressed%></td>
+          <td><%= regionSize%></td>
+          <td><%= fileCount%></td>
+          <td><%= memSize%></td>
+          <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getStartKey()))%></td>
+          <td><%= 
escapeXml(Bytes.toStringBinary(regionInfo.getEndKey()))%></td>
+          <td><%= state%></td>
+          <td><%= regionInfo.getReplicaId() %></td>
+        </tr>
+        <% } %>
+        <% } %>
+        </tbody>
+      </table>
+      <%= moreRegionsToRender(numRegionsRendered, numRegions, fqtn) %>
     </div>
-    <h2>Regions by Region Server</h2>
-    <%
-      if (withReplica) {
-    %>
-    <table id="regionServerTable" class="tablesorter table 
table-striped"><thead><tr><th>Region Server</th><th>Region 
Count</th><th>Primary Region Count</th></tr></thead>
-        <%
-} else {
-%>
-      <table id="regionServerTable" class="tablesorter table 
table-striped"><thead><tr><th>Region Server</th><th>Region 
Count</th></tr></thead>
+    <div class="tab-pane" id="tab_localityStats">
+      <table id="tableLocalityStatsTable" class="tablesorter table 
table-striped">
+        <thead>
+          <tr>
+            <th>Name(<%= String.format("%,1d", regions.size())%>)</th>
+            <th>Region Server</th>
+            <th>Locality<br>(<%= totalLocality %>)</th>
+            <th>LocalityForSsd<br>(<%= totalLocalityForSsd %>)</th>
+          </tr>
+        </thead>
         <tbody>
         <%
-          }
+          numRegionsRendered = 0;
+          for (Map.Entry<RegionInfo, RegionMetrics> hriEntry : entryList) {
+            RegionInfo regionInfo = hriEntry.getKey();
+            ServerName addr = regionsToServer.get(regionInfo);
+            RegionMetrics load = hriEntry.getValue();
+            float locality = 0.0f;
+            float localityForSsd = 0.0f;
+            String state = "N/A";
+            if (load != null) {
+              locality = load.getDataLocality();
+              localityForSsd = load.getDataLocalityForSsd();
+            }
+
+            if (numRegionsRendered < numRegionsToRender) {
+              numRegionsRendered++;
         %>
+        <tr>
+          <td><%= escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) 
%></td>
+          <%= buildRegionDeployedServerTag(regionInfo, master, 
regionsToServer) %>
+          <td><%= locality%></td>
+          <td><%= localityForSsd%></td>
+        </tr>
+        <% } %>
+        <% } %>
+        </tbody>
+      </table>
+      <%= moreRegionsToRender(numRegionsRendered, numRegions, fqtn) %>
+    </div>
+    <div class="tab-pane" id="tab_compactStats">
+      <table id="tableCompactStatsTable" class="tablesorter table 
table-striped">
+        <thead>
+          <tr>
+            <th>Name(<%= String.format("%,1d", regions.size())%>)</th>
+            <th>Region Server</th>
+            <th>Num. Compacting Cells<br>(<%= String.format("%,1d", 
totalCompactingCells)%>)</th>
+            <th>Num. Compacted Cells<br>(<%= String.format("%,1d", 
totalCompactedCells)%>)</th>
+            <th>Remaining Cells<br>(<%= String.format("%,1d", 
totalCompactingCells-totalCompactedCells)%>)</th>
+            <th>Compaction Progress<br>(<%= totalCompactionProgress %>)</th>
+          </tr>
+        </thead>
+        <tbody>
         <%
-          for (Map.Entry<ServerName, Integer> rdEntry : 
regDistribution.entrySet()) {
-            ServerName addr = rdEntry.getKey();
-            String url = "//" + URLEncoder.encode(addr.getHostname()) + ":" + 
master.getRegionServerInfoPort(addr) + "/rs-status";
+          numRegionsRendered = 0;
+          for (Map.Entry<RegionInfo, RegionMetrics> hriEntry : entryList) {
+            RegionInfo regionInfo = hriEntry.getKey();
+            ServerName addr = regionsToServer.get(regionInfo);
+            RegionMetrics load = hriEntry.getValue();
+            long compactingCells = 0;
+            long compactedCells = 0;
+            String compactionProgress = "";
+            if (load != null) {
+              compactingCells = load.getCompactingCellCount();
+              compactedCells = load.getCompactedCellCount();
+              if (compactingCells > 0) {
+                compactionProgress = String.format("%.2f", 100 * ((float)
+                        compactedCells / compactingCells)) + "%";
+              }
+            }
+
+            if (numRegionsRendered < numRegionsToRender) {
+              numRegionsRendered++;
         %>
         <tr>
-          <td><a href="<%= url %>"><%= 
StringEscapeUtils.escapeHtml4(addr.getHostname().toString()) + ":" + 
master.getRegionServerInfoPort(addr) %></a></td>
-          <td><%= rdEntry.getValue()%></td>
-          <%
-            if (withReplica) {
-          %>
-          <td><%= primaryRegDistribution.get(addr)%></td>
-          <%
-            }
-          %>
+          <td><%= escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) 
%></td>
+          <%= buildRegionDeployedServerTag(regionInfo, master, 
regionsToServer) %>
+          <td><%= String.format("%,1d", compactingCells)%></td>
+          <td><%= String.format("%,1d", compactedCells)%></td>
+          <td><%= String.format("%,1d", compactingCells - 
compactedCells)%></td>
+          <td><%= compactionProgress%></td>
         </tr>
         <% } %>
+        <% } %>
         </tbody>
       </table>
-        <% }
+      <%= moreRegionsToRender(numRegionsRendered, numRegions, fqtn) %>
+    </div>
+  </div>
+</div>
+
+<h2>Regions by Region Server</h2>
+<table id="regionServerTable" class="tablesorter table table-striped">
+  <thead>
+    <tr>
+      <th>Region Server</th><th>Region Count</th><th>Primary Region Count</th>
+    </tr>
+  </thead>
+
+  <tbody>
+  <%
+    for (Map.Entry<ServerName, Integer> rdEntry : regDistribution.entrySet()) {
+      ServerName addr = rdEntry.getKey();
+      String url = "//" + URLEncoder.encode(addr.getHostname()) + ":"
+        + master.getRegionServerInfoPort(addr) + "/rs-status";
+  %>
+      <tr>
+        <td><a href="<%= url %>"><%= 
StringEscapeUtils.escapeHtml4(addr.getHostname().toString())
+          + ":" + master.getRegionServerInfoPort(addr) %></a></td>
+        <td><%= rdEntry.getValue()%></td>
+        <td><%= primaryRegDistribution.get(addr) == null ? 0 : 
primaryRegDistribution.get(addr)%></td>
+      </tr>
+  <% } %>
+  </tbody>
+</table>
+
+<% }
 } catch(Exception ex) { %>
   Unknown Issue with Regions
   <div 
onclick="document.getElementById('closeStackTrace').style.display='block';document.getElementById('openStackTrace').style.display='none';">
@@ -1296,41 +1261,6 @@
         <% } %>
   </div>
 </div>
-<% }
-} catch(TableNotFoundException e) { %>
-<div class="container-fluid content">
-  <div class="row inner_header">
-    <div class="page-header">
-      <h1>Table not found</h1>
-    </div>
-  </div>
-  <p><hr><p>
-  <p>Go <a href="javascript:history.back()">Back</a>
-</div> <%
-} catch(IllegalArgumentException e) { %>
-<div class="container-fluid content">
-  <div class="row inner_header">
-    <div class="page-header">
-      <h1>Table qualifier must not be empty</h1>
-    </div>
-  </div>
-  <p><hr><p>
-  <p>Go <a href="javascript:history.back()">Back</a>
-</div> <%
-  }
-}
-else { // handle the case for fqtn is null or master is not initialized with 
error message + redirect
-%>
-<div class="container-fluid content">
-  <div class="row inner_header">
-    <div class="page-header">
-      <h1>Table not ready</h1>
-    </div>
-  </div>
-  <p><hr><p>
-  <jsp:include page="redirect.jsp" />
-</div>
-<% } %>
 
 <jsp:include page="footer.jsp" />
 <script src="/static/js/jquery.min.js" type="text/javascript"></script>
@@ -1338,78 +1268,94 @@ else { // handle the case for fqtn is null or master is 
not initialized with err
 <script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
 
 <script>
-    $(document).ready(function()
+$(document).ready(function()
+    {
+        $.tablesorter.addParser(
         {
-            $.tablesorter.addParser(
-                {
-                    id: 'filesize',
-                    is: function(s) {
-                        return s.match(new RegExp( /([\.0-9]+)\ 
(B|KB|MB|GB|TB)/ ));
-                    },
-                    format: function(s) {
-                        var suf = s.match(new RegExp( /(B|KB|MB|GB|TB)$/ ))[1];
-                        var num = parseFloat(s.match( new RegExp( /([\.0-9]+)\ 
(B|KB|MB|GB|TB)/ ))[0]);
-                        switch(suf) {
-                            case 'B':
-                                return num;
-                            case 'KB':
-                                return num * 1024;
-                            case 'MB':
-                                return num * 1024 * 1024;
-                            case 'GB':
-                                return num * 1024 * 1024 * 1024;
-                            case 'TB':
-                                return num * 1024 * 1024 * 1024 * 1024;
-                        }
-                    },
-                    type: 'numeric'
-                });
-            $.tablesorter.addParser(
-                {
-                    id: "separator",
-                    is: function (s) {
-                        return /^[0-9]?[0-9,]*$/.test(s);
-                    }, format: function (s) {
-                        return $.tablesorter.formatFloat( s.replace(/,/g,'') );
-                    }, type: "numeric"
-                });
-            $("#regionServerTable").tablesorter({
-                headers: {
-                    1: {sorter: 'separator'}
-                }
-            });
-            $("#regionServerDetailsTable").tablesorter({
-                headers: {
-                    2: {sorter: 'separator'},
-                    3: {sorter: 'separator'},
-                    4: {sorter: 'filesize'},
-                    5: {sorter: 'separator'},
-                    6: {sorter: 'filesize'}
-                }
-            });
-            $("#tableRegionTable").tablesorter({
-                headers: {
-                    2: {sorter: 'separator'},
-                    3: {sorter: 'separator'},
-                    4: {sorter: 'filesize'},
-                    5: {sorter: 'separator'},
-                    6: {sorter: 'filesize'}
-                }
-            });
-            $("#tableCompactStatsTable").tablesorter({
-                headers: {
-                    2: {sorter: 'separator'},
-                    3: {sorter: 'separator'},
-                    4: {sorter: 'separator'}
+            id: 'filesize',
+            is: function(s) {
+                return s.match(new RegExp( /([\.0-9]+)\ (B|KB|MB|GB|TB)/ ));
+            },
+            format: function(s) {
+                var suf = s.match(new RegExp( /(B|KB|MB|GB|TB)$/ ))[1];
+                var num = parseFloat(s.match( new RegExp( /([\.0-9]+)\ 
(B|KB|MB|GB|TB)/ ))[0]);
+                switch(suf) {
+                    case 'B':
+                        return num;
+                    case 'KB':
+                        return num * 1024;
+                    case 'MB':
+                        return num * 1024 * 1024;
+                    case 'GB':
+                        return num * 1024 * 1024 * 1024;
+                    case 'TB':
+                        return num * 1024 * 1024 * 1024 * 1024;
                 }
-            });
-            $("#metaTableCompactStatsTable").tablesorter({
-                headers: {
-                    2: {sorter: 'separator'},
-                    3: {sorter: 'separator'},
-                    4: {sorter: 'separator'}
-                }
-            });
-        }
-    );
+            },
+            type: 'numeric'
+        });
+        $.tablesorter.addParser(
+        {
+            id: "separator",
+            is: function (s) {
+                return /^[0-9]?[0-9,]*$/.test(s);
+            }, format: function (s) {
+                return $.tablesorter.formatFloat( s.replace(/,/g,'') );
+            }, type: "numeric"
+        });
+        $("#regionServerTable").tablesorter({
+            headers: {
+                1: {sorter: 'separator'}
+            }
+        });
+        $("#tableBaseStatsTable").tablesorter({
+            headers: {
+                2: {sorter: 'separator'},
+                3: {sorter: 'separator'},
+                4: {sorter: 'filesize'},
+                5: {sorter: 'separator'},
+                6: {sorter: 'filesize'},
+                7: {empty: 'emptyMin'},
+                8: {empty: 'emptyMax'}
+            }
+        });
+        $("#metaTableBaseStatsTable").tablesorter({
+            headers: {
+                2: {sorter: 'separator'},
+                3: {sorter: 'separator'},
+                4: {sorter: 'filesize'},
+                5: {sorter: 'separator'},
+                6: {sorter: 'filesize'},
+                7: {empty: 'emptyMin'},
+                8: {empty: 'emptyMax'}
+            }
+        });
+        $("#tableLocalityStatsTable").tablesorter({
+            headers: {
+                2: {sorter: 'separator'},
+                3: {sorter: 'separator'}
+            }
+        });
+        $("#metaTableLocalityStatsTable").tablesorter({
+            headers: {
+                2: {sorter: 'separator'},
+                3: {sorter: 'separator'}
+            }
+        });
+        $("#tableCompactStatsTable").tablesorter({
+            headers: {
+                2: {sorter: 'separator'},
+                3: {sorter: 'separator'},
+                4: {sorter: 'separator'}
+            }
+        });
+        $("#metaTableCompactStatsTable").tablesorter({
+            headers: {
+                2: {sorter: 'separator'},
+                3: {sorter: 'separator'},
+                4: {sorter: 'separator'}
+            }
+        });
+    }
+);
 </script>
diff --git a/hbase-thrift/src/main/resources/hbase-webapps/thrift/footer.jsp 
b/hbase-thrift/src/main/resources/hbase-webapps/thrift/footer.jsp
new file mode 100644
index 00000000000..53a7d0cdbdb
--- /dev/null
+++ b/hbase-thrift/src/main/resources/hbase-webapps/thrift/footer.jsp
@@ -0,0 +1,30 @@
+<%--
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+--%>
+    <script src="/static/js/jquery.min.js" type="text/javascript"></script>
+    <script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
+    <script src="/static/js/tab.js" type="text/javascript"></script>
+    <script type="text/javascript">
+      $(document).ready(function() {
+        $('li.active').removeClass('active');
+        $('a[href="' + location.pathname + 
'"]').closest('li').addClass('active');
+      });
+    </script>
+  </body>
+</html>
diff --git a/hbase-thrift/src/main/resources/hbase-webapps/thrift/header.jsp 
b/hbase-thrift/src/main/resources/hbase-webapps/thrift/header.jsp
new file mode 100644
index 00000000000..f43872c11af
--- /dev/null
+++ b/hbase-thrift/src/main/resources/hbase-webapps/thrift/header.jsp
@@ -0,0 +1,74 @@
+<%--
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+--%>
+<%@ page contentType="text/html;charset=UTF-8"
+         import="org.apache.hadoop.hbase.HBaseConfiguration"%>
+
+<!DOCTYPE html>
+<?xml version="1.0" encoding="UTF-8" ?>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <title><%= request.getParameter("pageTitle")%></title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta name="description" content="">
+
+  <link href="/static/css/bootstrap.min.css" rel="stylesheet">
+  <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
+  <link href="/static/css/hbase.css" rel="stylesheet">
+</head>
+
+<body>
+<div class="navbar  navbar-fixed-top navbar-default">
+  <div class="container-fluid">
+    <div class="navbar-header">
+      <button type="button"
+              class="navbar-toggle" data-toggle="collapse" 
data-target=".navbar-collapse">
+        <span class="icon-bar"></span>
+        <span class="icon-bar"></span>
+        <span class="icon-bar"></span>
+      </button>
+      <a class="navbar-brand" href="/thrift.jsp">
+        <img src="/static/hbase_logo_small.png" alt="HBase Logo"/>
+      </a>
+    </div>
+    <div class="collapse navbar-collapse">
+      <ul class="nav navbar-nav">
+        <li class="active"><a href="/thrift.jsp">Home</a></li>
+        <li><a href="/logs/">Local logs</a></li>
+        <li><a href="/logLevel">Log Level</a></li>
+        <li class="nav-item dropdown">
+          <a class="nav-link dropdown-toggle" href="#" 
id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">
+            Metrics <span class="caret"></span>
+          </a>
+          <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
+            <li><a target="_blank" href="/jmx">JMX</a></li>
+            <li><a target="_blank" href="/jmx?description=true">JMX with 
description</a></li>
+            <li><a target="_blank" href="/prometheus">Prometheus</a></li>
+            <li><a target="_blank" 
href="/prometheus?description=true">Prometheus with description</a></li>
+          </ul>
+        </li>
+        <li><a href="/prof">Profiler</a></li>
+        <% if (HBaseConfiguration.isShowConfInServlet()) { %>
+        <li><a href="/conf">HBase Configuration</a></li>
+        <% } %>
+      </ul>
+    </div><!--/.nav-collapse -->
+  </div>
+</div>
diff --git a/hbase-thrift/src/main/resources/hbase-webapps/thrift/thrift.jsp 
b/hbase-thrift/src/main/resources/hbase-webapps/thrift/thrift.jsp
index dea59123099..d148df1f2e2 100644
--- a/hbase-thrift/src/main/resources/hbase-webapps/thrift/thrift.jsp
+++ b/hbase-thrift/src/main/resources/hbase-webapps/thrift/thrift.jsp
@@ -19,7 +19,6 @@
 --%>
 <%@ page contentType="text/html;charset=UTF-8"
   import="org.apache.hadoop.conf.Configuration"
-  import="org.apache.hadoop.hbase.HBaseConfiguration"
   import="org.apache.hadoop.hbase.util.VersionInfo"
   import="java.util.Date"
 %>
@@ -27,64 +26,25 @@
 <%@ page import="org.apache.hadoop.hbase.util.JvmVersion" %>
 
 <%
-Configuration conf = 
(Configuration)getServletContext().getAttribute("hbase.conf");
-String serverType = 
(String)getServletContext().getAttribute("hbase.thrift.server.type");
-long startcode = conf.getLong("startcode", System.currentTimeMillis());
-String listenPort = conf.get("hbase.regionserver.thrift.port", "9090");
-ImplType implType = ImplType.getServerImpl(conf);
-String framed = implType.isAlwaysFramed()
-    ? "true" : conf.get("hbase.regionserver.thrift.framed", "false");
-String compact = conf.get("hbase.regionserver.thrift.compact", "false");
-%>
-<!DOCTYPE html>
-<?xml version="1.0" encoding="UTF-8" ?>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>HBase Thrift Server: <%= listenPort %></title>
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <meta name="description" content="">
+  Configuration conf = 
(Configuration)getServletContext().getAttribute("hbase.conf");
+  String serverType = 
(String)getServletContext().getAttribute("hbase.thrift.server.type");
+  long startcode = conf.getLong("startcode", System.currentTimeMillis());
+  String listenPort = conf.get("hbase.regionserver.thrift.port", "9090");
+  ImplType implType = ImplType.getServerImpl(conf);
+
+  String transport =
+    (implType.isAlwaysFramed() ||
+      conf.getBoolean("hbase.regionserver.thrift.framed", false)) ? "Framed" : 
"Standard";
+  String protocol =
+    conf.getBoolean("hbase.regionserver.thrift.compact", false) ? "Compact" : 
"Binary";
+  String qop = conf.get("hbase.thrift.security.qop", "None");
 
-    <link href="/static/css/bootstrap.min.css" rel="stylesheet">
-    <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
-    <link href="/static/css/hbase.css" rel="stylesheet">
-  </head>
+  pageContext.setAttribute("pageTitle", "HBase Thrift Server: " + listenPort);
+%>
 
-  <body>
-  <div class="navbar  navbar-fixed-top navbar-default">
-      <div class="container-fluid">
-          <div class="navbar-header">
-              <button type="button" class="navbar-toggle" 
data-toggle="collapse" data-target=".navbar-collapse">
-                  <span class="icon-bar"></span>
-                  <span class="icon-bar"></span>
-                  <span class="icon-bar"></span>
-              </button>
-              <a class="navbar-brand" href="/thrift.jsp"><img 
src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
-          </div>
-          <div class="collapse navbar-collapse">
-              <ul class="nav navbar-nav">
-                <li class="active"><a href="/">Home</a></li>
-                <li><a href="/logs/">Local logs</a></li>
-                <li><a href="/logLevel">Log Level</a></li>
-                <li class="nav-item dropdown">
-                  <a class="nav-link dropdown-toggle" href="#" 
id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">
-                    Metrics <span class="caret"></span>
-                  </a>
-                  <ul class="dropdown-menu" 
aria-labelledby="navbarDropdownMenuLink">
-                    <li><a target="_blank" href="/jmx">JMX</a></li>
-                    <li><a target="_blank" href="/jmx?description=true">JMX 
with description</a></li>
-                    <li><a target="_blank" 
href="/prometheus">Prometheus</a></li>
-                    <li><a target="_blank" 
href="/prometheus?description=true">Prometheus with description</a></li>
-                  </ul>
-                </li>
-                <li><a href="/prof">Profiler</a></li>
-                <% if (HBaseConfiguration.isShowConfInServlet()) { %>
-                <li><a href="/conf">HBase Configuration</a></li>
-                <% } %>
-            </ul>
-          </div><!--/.nav-collapse -->
-      </div>
-  </div>
+<jsp:include page="header.jsp">
+  <jsp:param name="pageTitle" value="${pageTitle}"/>
+</jsp:include>
 
 <div class="container-fluid content">
     <div class="row inner_header">
@@ -128,31 +88,34 @@ String compact = 
conf.get("hbase.regionserver.thrift.compact", "false");
             <td>Thrift RPC engine implementation type chosen by this Thrift 
server</td>
         </tr>
         <tr>
-            <td>Compact Protocol</td>
-            <td><%= compact %></td>
-            <td>Thrift RPC engine uses compact protocol</td>
+            <td>Protocol</td>
+            <td><%= protocol %></td>
+            <td>Thrift RPC engine protocol type</td>
         </tr>
         <tr>
-            <td>Framed Transport</td>
-            <td><%= framed %></td>
-            <td>Thrift RPC engine uses framed transport</td>
+            <td>Transport</td>
+            <td><%= transport %></td>
+            <td>Thrift RPC engine transport type</td>
         </tr>
         <tr>
             <td>Thrift Server Type</td>
             <td><%= serverType %></td>
             <td>The type of this Thrift server</td>
         </tr>
+      <tr>
+        <td>Quality of Protection</td>
+        <td><%= qop %></td>
+        <td>QOP Settings for SASL</td>
+      </tr>
     </table>
     </section>
     </div>
     <div class="row">
         <section>
-            <a href="http://hbase.apache.org/book.html#_thrift";>Apache HBase 
Reference Guide chapter on Thrift</a>
+            <a href="http://hbase.apache.org/book.html#_thrift";>
+              Apache HBase Reference Guide chapter on Thrift</a>
         </section>
     </div>
 </div>
-<script src="/static/js/jquery.min.js" type="text/javascript"></script>
-<script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
-<script src="/static/js/tab.js" type="text/javascript"></script>
-</body>
-</html>
+
+<jsp:include page="footer.jsp" />


Reply via email to