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

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


The following commit(s) were added to refs/heads/branch-2 by this push:
     new cd6f22416ab HBASE-29037 Backport missing UI patches to branch-2 (#6551)
cd6f22416ab is described below

commit cd6f22416ab23d23b723574c5f268b86ec992f8e
Author: Dávid Paksy <[email protected]>
AuthorDate: Tue Dec 24 07:13:06 2024 +0100

    HBASE-29037 Backport missing UI patches to branch-2 (#6551)
    
    * 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)
    
    * HBASE-20452 Master UI: Table merge button should validate required fields 
before submit
    
    Signed-off-by: tedyu <[email protected]>
    (cherry picked from commit 6ce1136ebae75abc2a1d8d35e1963546b8e2d014)
    
    ---------
    Co-authored-by: xincunSong <[email protected]>
    Co-authored-by: Akshay Sudheer 
<[email protected]>
    Co-authored-by: Peng Lu <[email protected]>
    Co-authored-by: Nihal Jain <[email protected]>
    
    Signed-off-by: Duo Zhang <[email protected]>
    Signed-off-by: Nihal Jain <[email protected]>
---
 .../hbase/tmpl/regionserver/RSStatusTmpl.jamon     |    7 +-
 .../main/resources/hbase-webapps/master/table.jsp  | 1809 ++++++++++----------
 2 files changed, 886 insertions(+), 930 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..fdec6849de0 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,35 +221,36 @@
   final MetaBrowser metaBrowser = new MetaBrowser(connection, request);
 %>
 
-<jsp:include page="header.jsp">
-  <jsp:param name="pageTitle" value="${pageTitle}"/>
-</jsp:include>
-
-<%
-  if (fqtn != null && master.isInitialized()) {
-    try {
-      table = master.getConnection().getTable(TableName.valueOf(fqtn));
-      if (table.getTableDescriptor().getRegionReplication() > 1) {
-        withReplica = true;
-      }
-      if ( !readOnly && action != null ) {
-%>
-<div class="container-fluid content">
-  <div class="row inner_header">
-    <div class="page-header">
-      <h1>Table action request accepted</h1>
+<% // 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>
-  </div>
-  <p><hr><p>
-    <%
-    if (action.equals("split")) {
+<%  return;
+  } %>
+
+<% // table split/compact/merge actions
+  if ( !readOnly && action != null ) { %>
+    <div class="container-fluid content">
+      <div class="row inner_header">
+        <div class="page-header">
+          <h1>Table action request accepted</h1>
+        </div>
+      </div>
+      <p><hr><p>
+<%  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 +263,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 +277,232 @@
       } 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(
+</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);
-                        }
-                      }
+            //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()) {
@@ -524,6 +570,7 @@
       final RegionInfo regionInfo = regionReplicaInfo.getRegionInfo();
       final ServerName serverName = regionReplicaInfo.getServerName();
       final RegionState.State regionState = regionReplicaInfo.getRegionState();
+      final int rsPort = master.getRegionServerInfoPort(serverName);
 
       final long seqNum = regionReplicaInfo.getSeqNum();
 
@@ -541,20 +588,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, rsPort, regionInfo, regionState) %></td>
+      <td title="<%= seqNumColumnName %>"><%= seqNum %></td>
+      <td title="<%= serverNameColumnName %>"><%= targetServerName %></td>
+      <td><%= mergeRegionNames %></td>
+      <td><%= splitName %></td>
+    </tr>
+  <%
     }
 
     metaScanHasMore = results.hasMoreResults();
@@ -608,149 +655,152 @@
 <%
   }
 %>
-            </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>
-      <%
-            }
-          }
-        }
-      %>
-    </table>
-    <h2>Table Schema</h2>
-    <table class="table table-striped">
+    } 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<>();
@@ -818,358 +868,278 @@
         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';">
@@ -1215,122 +1185,87 @@
         </tr>
       </table>
 
-        <% if (!readOnly) { %>
-      <p><hr/></p>
-      Actions:
-      <p>
-      <center>
-        <table class="table" style="border: 0;" width="95%" >
-          <tr>
-            <form method="get">
-            <input type="hidden" name="action" value="major compact" />
-            <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
-            <td class="centered">
-              <input style="font-size: 12pt; width: 10em" type="submit" 
value="Major Compact" class="btn" />
-            </td>
-            <td style="text-align: center;">
-              <input type="text" name="key" size="40" placeholder="Row Key 
(optional)" />
-            </td>
-            <td>
-              This action will force a major compaction of all regions of the 
table, or,
-              if a key is supplied, only the region major containing the
-              given key.
-            </td>
-            </form>
-          </tr>
-          <tr>
-            <form method="get">
-              <input type="hidden" name="action" value="compact" />
-              <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
-              <td class="centered">
-                <input style="font-size: 12pt; width: 10em" type="submit" 
value="Compact" class="btn" />
-              </td>
-              <td style="text-align: center;">
-                <input type="text" name="key" size="40" placeholder="Row Key 
(optional)" />
-              </td>
-              <td>
-                This action will force a compaction of all regions of the 
table, or,
-                if a key is supplied, only the region containing the
-                given key.
-              </td>
-            </form>
-          </tr>
-          <tr>
-            <form method="get">
-              <input type="hidden" name="action" value="split" />
-              <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
-              <td class="centered">
-                <input style="font-size: 12pt; width: 10em" type="submit" 
value="Split" class="btn" />
-              </td>
-              <td style="text-align: center;">
-                <input type="text" name="key" size="40" placeholder="Row Key 
(optional)" />
-              </td>
-              <td>
-                This action will force a split of all eligible
-                regions of the table, or, if a key is supplied, only the 
region containing the
-                given key. An eligible region is one that does not contain any 
references to
-                other regions. Split requests for noneligible regions will be 
ignored.
-              </td>
-            </form>
-          </tr>
-          <tr>
-            <form method="get">
-              <input type="hidden" name="action" value="merge" />
-              <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
-              <td class="centered">
-                <input style="font-size: 12pt; width: 10em" type="submit" 
value="Merge" class="btn" />
-              </td>
-              <td style="text-align: center;">
-                <input type="text" name="left" size="40" placeholder="Region 
Key (required)" />
-                <input type="text" name="right" size="40" placeholder="Region 
Key (required)" />
-              </td>
-              <td>
-                This action will merge two regions of the table, Merge 
requests for
-                noneligible regions will be ignored.
-              </td>
-            </form>
-          </tr>
-        </table>
-      </center>
-      </p>
-        <% } %>
-  </div>
+<% if (!readOnly) { %>
+<p><hr/></p>
+Actions:
+<p>
+<center>
+<table class="table" style="border: 0;" width="95%" >
+<tr>
+  <form method="get">
+  <input type="hidden" name="action" value="major compact" />
+  <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
+  <td class="centered">
+    <input style="font-size: 12pt; width: 10em" type="submit" value="Major 
Compact" class="btn" />
+  </td>
+  <td style="text-align: center;">
+    <input type="text" name="key" size="40" placeholder="Row Key (optional)" />
+  </td>
+  <td>
+    This action will force a major compaction of all regions of the table, or,
+    if a key is supplied, only the region major containing the
+    given key.
+  </td>
+  </form>
+</tr>
+<tr>
+  <form method="get">
+  <input type="hidden" name="action" value="compact" />
+  <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
+  <td class="centered">
+    <input style="font-size: 12pt; width: 10em" type="submit" value="Compact" 
class="btn" />
+  </td>
+  <td style="text-align: center;">
+    <input type="text" name="key" size="40" placeholder="Row Key (optional)" />
+  </td>
+  <td>
+    This action will force a compaction of all regions of the table, or,
+    if a key is supplied, only the region containing the
+    given key.
+  </td>
+  </form>
+</tr>
+<tr>
+  <form method="get">
+  <input type="hidden" name="action" value="split" />
+  <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
+  <td class="centered">
+    <input style="font-size: 12pt; width: 10em" type="submit" value="Split" 
class="btn" />
+  </td>
+  <td style="text-align: center;">
+    <input type="text" name="key" size="40" placeholder="Row Key (optional)" />
+  </td>
+  <td>
+    This action will force a split of all eligible
+    regions of the table, or, if a key is supplied, only the region containing 
the
+    given key. An eligible region is one that does not contain any references 
to
+    other regions. Split requests for noneligible regions will be ignored.
+  </td>
+  </form>
+</tr>
+<tr>
+  <form method="get">
+  <input type="hidden" name="action" value="merge" />
+  <input type="hidden" name="name" value="<%= escaped_fqtn %>" />
+  <td class="centered">
+    <input style="font-size: 12pt; width: 10em" type="submit" value="Merge" 
class="btn" />
+  </td>
+  <td style="text-align: center;">
+    <input type="text" name="left" size="40" required="required" 
placeholder="Region Key (required)" />
+    <input type="text" name="right" size="40" required="required" 
placeholder="Region Key (required)" />
+  </td>
+  <td>
+    This action will merge two regions of the table, Merge requests for
+    noneligible regions will be ignored.
+  </td>
+  </form>
+</tr>
+</table>
+</center>
+</p>
+<% } %>
 </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 +1273,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'}
-                }
-            });
-            $("#metaTableCompactStatsTable").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;
                 }
-            });
-        }
-    );
+            },
+            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>

Reply via email to