| <%-- |
| /** |
| * 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="static org.apache.commons.lang3.StringEscapeUtils.escapeXml" |
| import="java.net.URLEncoder" |
| import="java.util.ArrayList" |
| import="java.util.Collection" |
| import="java.util.HashMap" |
| import="java.util.LinkedHashMap" |
| import="java.util.List" |
| import="java.util.Map" |
| import="java.util.Set" |
| import="java.util.HashSet" |
| import="java.util.Optional" |
| import="java.util.TreeMap" |
| import="java.util.concurrent.TimeoutException" |
| import="java.util.concurrent.TimeUnit" |
| import="org.apache.commons.lang3.StringEscapeUtils" |
| import="org.apache.hadoop.conf.Configuration" |
| import="org.apache.hadoop.hbase.HConstants" |
| import="org.apache.hadoop.hbase.HRegionLocation" |
| import="org.apache.hadoop.hbase.NotServingRegionException" |
| import="org.apache.hadoop.hbase.RegionMetrics" |
| import="org.apache.hadoop.hbase.RegionMetricsBuilder" |
| import="org.apache.hadoop.hbase.ServerMetrics" |
| import="org.apache.hadoop.hbase.ServerName" |
| import="org.apache.hadoop.hbase.Size" |
| import="org.apache.hadoop.hbase.TableName" |
| import="org.apache.hadoop.hbase.TableNotFoundException" |
| import="org.apache.hadoop.hbase.client.AsyncAdmin" |
| import="org.apache.hadoop.hbase.client.AsyncConnection" |
| import="org.apache.hadoop.hbase.client.ColumnFamilyDescriptor" |
| import="org.apache.hadoop.hbase.client.CompactionState" |
| import="org.apache.hadoop.hbase.client.RegionInfo" |
| import="org.apache.hadoop.hbase.client.RegionInfoBuilder" |
| import="org.apache.hadoop.hbase.client.RegionLocator" |
| import="org.apache.hadoop.hbase.client.RegionReplicaUtil" |
| import="org.apache.hadoop.hbase.client.Table" |
| import="org.apache.hadoop.hbase.client.TableState" |
| import="org.apache.hadoop.hbase.client.ColumnFamilyDescriptor" |
| import="org.apache.hadoop.hbase.http.InfoServer" |
| import="org.apache.hadoop.hbase.master.HMaster" |
| import="org.apache.hadoop.hbase.master.RegionState" |
| import="org.apache.hadoop.hbase.master.assignment.RegionStates" |
| import="org.apache.hadoop.hbase.master.http.MetaBrowser" |
| import="org.apache.hadoop.hbase.master.http.RegionReplicaInfo" |
| import="org.apache.hadoop.hbase.quotas.QuotaSettingsFactory" |
| import="org.apache.hadoop.hbase.quotas.QuotaTableUtil"%> |
| <%@ page import="org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot" %> |
| <%@ page import="org.apache.hadoop.hbase.quotas.ThrottleSettings" %> |
| <%@ page import="org.apache.hadoop.hbase.util.Bytes" %> |
| <%@ page import="org.apache.hadoop.hbase.util.FSUtils" %> |
| <%@ page import="org.apache.hadoop.hbase.zookeeper.MetaTableLocator" %> |
| <%@ page import="org.apache.hadoop.util.StringUtils" %> |
| <%@ page import="org.apache.hbase.thirdparty.com.google.protobuf.ByteString" %> |
| <%@ page import="org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos" %> |
| <%@ page import="org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos" %> |
| <%@ page import="org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas" %> |
| <%@ page import="org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota" %> |
| <%@ page import="java.util.stream.Collectors" %> |
| <%! |
| /** |
| * @return An empty region load stamped with the passed in <code>regionInfo</code> |
| * region name. |
| */ |
| private static RegionMetrics getEmptyRegionMetrics(final RegionInfo regionInfo) { |
| return RegionMetricsBuilder.toRegionMetrics(ClusterStatusProtos.RegionLoad.newBuilder(). |
| setRegionSpecifier(HBaseProtos.RegionSpecifier.newBuilder(). |
| setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME). |
| setValue(ByteString.copyFrom(regionInfo.getRegionName())).build()).build()); |
| } |
| |
| /** |
| * Given dicey information that may or not be available in meta, render a link to the region on |
| * its region server. |
| * @return an anchor tag if one can be built, {@code null} otherwise. |
| */ |
| private static String buildRegionLink(final ServerName serverName, final int rsInfoPort, |
| final RegionInfo regionInfo, final RegionState.State regionState) { |
| if (serverName == null || regionInfo == null) { return null; } |
| |
| if (regionState != RegionState.State.OPEN) { |
| // region is assigned to RS, but RS knows nothing of it. don't bother with a link. |
| return serverName.getServerName(); |
| } |
| |
| final String socketAddress = serverName.getHostname() + ":" + rsInfoPort; |
| final String URI = "//" + socketAddress + "/region.jsp" |
| + "?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 ""; |
| } |
| %> |
| <% |
| final String ZEROMB = "0 MB"; |
| HMaster master = (HMaster)getServletContext().getAttribute(HMaster.MASTER); |
| Configuration conf = master.getConfiguration(); |
| String fqtn = request.getParameter("name"); |
| final String escaped_fqtn = StringEscapeUtils.escapeHtml4(fqtn); |
| 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 = |
| master.getTableDescriptors().get(TableName.META_TABLE_NAME).getRegionReplication(); |
| Map<String, Integer> frags = null; |
| if (showFragmentation) { |
| frags = FSUtils.getTableFragmentation(master); |
| } |
| boolean quotasEnabled = conf.getBoolean("hbase.quota.enabled", false); |
| String action = request.getParameter("action"); |
| String key = request.getParameter("key"); |
| String left = request.getParameter("left"); |
| String right = request.getParameter("right"); |
| long totalStoreFileSizeMB = 0; |
| |
| final String numRegionsParam = request.getParameter("numRegions"); |
| // By default, the page render up to 10000 regions to improve the page load time |
| int numRegionsToRender = 10000; |
| if (numRegionsParam != null) { |
| // either 'all' or a number |
| if (numRegionsParam.equals("all")) { |
| numRegionsToRender = -1; |
| } else { |
| try { |
| numRegionsToRender = Integer.parseInt(numRegionsParam); |
| } catch (NumberFormatException ex) { |
| // ignore |
| } |
| } |
| } |
| int numRegions = 0; |
| |
| String pageTitle; |
| if ( !readOnly && action != null ) { |
| pageTitle = "HBase Master: " + StringEscapeUtils.escapeHtml4(master.getServerName().toString()); |
| } else { |
| pageTitle = "Table: " + escaped_fqtn; |
| } |
| pageContext.setAttribute("pageTitle", pageTitle); |
| final AsyncConnection connection = master.getAsyncConnection(); |
| final AsyncAdmin admin = connection.getAdminBuilder() |
| .setOperationTimeout(5, TimeUnit.SECONDS) |
| .build(); |
| final MetaBrowser metaBrowser = new MetaBrowser(connection, request); |
| %> |
| |
| <jsp:include page="header.jsp"> |
| <jsp:param name="pageTitle" value="${pageTitle}"/> |
| </jsp:include> |
| |
| <% // 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; |
| } %> |
| |
| <% // 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; |
| } %> |
| |
| <% // 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. <% |
| } else if (action.equals("compact")) { |
| if (key != null && key.length() > 0) { |
| List<RegionInfo> regions = admin.getRegions(TableName.valueOf(fqtn)).get(); |
| byte[] row = Bytes.toBytes(key); |
| |
| for (RegionInfo region : regions) { |
| if (region.containsRow(row)) { |
| admin.compactRegion(region.getRegionName()); |
| } |
| } |
| } else { |
| admin.compact(TableName.valueOf(fqtn)); |
| } |
| %> 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> |
| <% return; |
| } %> |
| |
| <div class="container-fluid content"> |
| <div class="row inner_header"> |
| <div class="page-header"> |
| <h1>Table <small><%= escaped_fqtn %></small></h1> |
| </div> |
| </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>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); |
| ServerName metaLocation = MetaTableLocator.waitMetaRegionLocation(master.getZooKeeper(), j, 1); |
| for (int i = 0; i < 1; i++) { |
| String hostAndPort = ""; |
| String readReq = "N/A"; |
| String writeReq = "N/A"; |
| 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); |
| } |
| 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><%= 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); |
| ServerName metaLocation = MetaTableLocator.waitMetaRegionLocation(master.getZooKeeper(), j, 1); |
| for (int i = 0; i < 1; i++) { |
| 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( |
| RegionInfoBuilder.FIRST_META_REGIONINFO, j); |
| ServerName metaLocation = MetaTableLocator.waitMetaRegionLocation(master.getZooKeeper(), j, 1); |
| for (int i = 0; i < 1; i++) { |
| 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> |
| </div> |
| |
| <h2 id="meta-entries">Meta Entries</h2> |
| <% |
| if (!metaBrowser.getErrorMessages().isEmpty()) { |
| for (final String errorMessage : metaBrowser.getErrorMessages()) { |
| %> |
| <div class="alert alert-warning" role="alert"> |
| <%= errorMessage %> |
| </div> |
| <% |
| } |
| } |
| |
| String regionInfoColumnName = HConstants.CATALOG_FAMILY_STR + ":" + HConstants.REGIONINFO_QUALIFIER_STR; |
| String serverColumnName = HConstants.CATALOG_FAMILY_STR + ":" + HConstants.SERVER_QUALIFIER_STR; |
| String startCodeColumnName = HConstants.CATALOG_FAMILY_STR + ":" + HConstants.STARTCODE_QUALIFIER_STR; |
| String serverNameColumnName = HConstants.CATALOG_FAMILY_STR + ":" + HConstants.SERVERNAME_QUALIFIER_STR; |
| String seqNumColumnName = HConstants.CATALOG_FAMILY_STR + ":" + HConstants.SEQNUM_QUALIFIER_STR; |
| %> |
| <div style="overflow-x: auto"> |
| <table class="table table-striped nowrap"> |
| <tr> |
| <th title="Region name, stored in <%= regionInfoColumnName %> column">RegionName</th> |
| <th title="The startKey of this region">Start Key</th> |
| <th title="The endKey of this region">End Key</th> |
| <th title="Region replica id">Replica ID</th> |
| <th title="State of the region while undergoing transitions">RegionState</th> |
| <th title="Server hosting this region replica, stored in <%= serverColumnName %> column">Server</th> |
| <th title="The seqNum for the region at the time the server opened this region replica, stored in <%= seqNumColumnName %>">Sequence Number</th> |
| <th title="The server to which the region is transiting, stored in <%= serverNameColumnName %> column">Target Server</th> |
| <th title="The parents regions if this region is undergoing a merge">info:merge*</th> |
| <th title="The daughter regions if this region is split">info:split*</th> |
| </tr> |
| <% |
| final boolean metaScanHasMore; |
| byte[] lastRow = null; |
| try (final MetaBrowser.Results results = metaBrowser.getResults()) { |
| for (final RegionReplicaInfo regionReplicaInfo : results) { |
| lastRow = Optional.ofNullable(regionReplicaInfo) |
| .map(RegionReplicaInfo::getRow) |
| .orElse(null); |
| if (regionReplicaInfo == null) { |
| %> |
| <tr> |
| <td colspan="6">Null result</td> |
| </tr> |
| <% |
| continue; |
| } |
| |
| final String regionNameDisplay = regionReplicaInfo.getRegionName() != null |
| ? Bytes.toStringBinary(regionReplicaInfo.getRegionName()) |
| : ""; |
| final String startKeyDisplay = regionReplicaInfo.getStartKey() != null |
| ? Bytes.toStringBinary(regionReplicaInfo.getStartKey()) |
| : ""; |
| final String endKeyDisplay = regionReplicaInfo.getEndKey() != null |
| ? Bytes.toStringBinary(regionReplicaInfo.getEndKey()) |
| : ""; |
| final String replicaIdDisplay = regionReplicaInfo.getReplicaId() != null |
| ? regionReplicaInfo.getReplicaId().toString() |
| : ""; |
| final String regionStateDisplay = regionReplicaInfo.getRegionState() != null |
| ? regionReplicaInfo.getRegionState().toString() |
| : ""; |
| |
| 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(); |
| |
| final String regionSpanFormat = "<span title=" + HConstants.CATALOG_FAMILY_STR + ":%s>%s</span>"; |
| final String targetServerName = regionReplicaInfo.getTargetServerName().toString(); |
| final Map<String, RegionInfo> mergeRegions = regionReplicaInfo.getMergeRegionInfo(); |
| final String mergeRegionNames = (mergeRegions == null) ? "" : |
| mergeRegions.entrySet().stream() |
| .map(entry -> String.format(regionSpanFormat, entry.getKey(), entry.getValue().getRegionNameAsString())) |
| .collect(Collectors.joining("<br/>")); |
| final Map<String, RegionInfo> splitRegions = regionReplicaInfo.getSplitRegionInfo(); |
| final String splitName = (splitRegions == null) ? "" : |
| 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 %>"><%= 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(); |
| } |
| %> |
| </table> |
| </div> |
| <div class="row"> |
| <div class="col-md-4"> |
| <ul class="pagination" style="margin: 20px 0"> |
| <li> |
| <a href="<%= metaBrowser.buildFirstPageUrl() %>" aria-label="Previous"> |
| <span aria-hidden="true">⇤</span> |
| </a> |
| </li> |
| <li<%= metaScanHasMore ? "" : " class=\"disabled\"" %>> |
| <a<%= metaScanHasMore ? " href=\"" + metaBrowser.buildNextPageUrl(lastRow) + "\"" : "" %> aria-label="Next"> |
| <span aria-hidden="true">»</span> |
| </a> |
| </li> |
| </ul> |
| </div> |
| <div class="col-md-8"> |
| <form action="/table.jsp" method="get" class="form-inline pull-right" style="margin: 20px 0"> |
| <input type="hidden" name="name" value="<%= TableName.META_TABLE_NAME %>" /> |
| <div class="form-group"> |
| <label for="scan-limit">Scan Limit</label> |
| <input type="text" id="scan-limit" name="<%= MetaBrowser.SCAN_LIMIT_PARAM %>" |
| class="form-control" placeholder="<%= MetaBrowser.SCAN_LIMIT_DEFAULT %>" |
| <%= metaBrowser.getScanLimit() != null |
| ? "value=\"" + metaBrowser.getScanLimit() + "\"" |
| : "" |
| %> |
| aria-describedby="scan-limit" style="display:inline; width:auto" /> |
| <label for="table-name-filter">Table</label> |
| <input type="text" id="table-name-filter" name="<%= MetaBrowser.SCAN_TABLE_PARAM %>" |
| <%= metaBrowser.getScanTable() != null |
| ? "value=\"" + metaBrowser.getScanTable() + "\"" |
| : "" |
| %> |
| aria-describedby="scan-filter-table" style="display:inline; width:auto" /> |
| <label for="region-state-filter">Region State</label> |
| <select class="form-control" id="region-state-filter" style="display:inline; width:auto" |
| name="<%= MetaBrowser.SCAN_REGION_STATE_PARAM %>"> |
| <option></option> |
| <% |
| for (final RegionState.State state : RegionState.State.values()) { |
| final boolean selected = metaBrowser.getScanRegionState() == state; |
| %> |
| <option<%= selected ? " selected" : "" %>><%= state %></option> |
| <% |
| } |
| %> |
| </select> |
| <button type="submit" class="btn btn-primary" style="display:inline; width:auto"> |
| Filter Results |
| </button> |
| </div> |
| </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()); |
| } |
| } 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(); |
| } |
| %> |
| <td> |
| <%= StringEscapeUtils.escapeHtml4(familyValue) %> |
| </td> |
| <% } %> |
| </tr> |
| <% } %> |
| </table> |
| <% |
| long totalReadReq = 0; |
| long totalWriteReq = 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 totalSizeStr = ZEROMB; |
| String totalLocality = ""; |
| String totalLocalityForSsd = ""; |
| 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.getRegion(); |
| 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(); |
| 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); |
| } |
| } else { |
| RegionMetrics load0 = getEmptyRegionMetrics(regionInfo); |
| regionsToLoad.put(regionInfo, load0); |
| } |
| } |
| if (totalSize > 0) { |
| totalSizeStr = StringUtils.byteDesc(totalSize*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>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 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); |
| } |
| 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); |
| } |
| } |
| } |
| if (numRegionsRendered < numRegionsToRender) { |
| numRegionsRendered++; |
| %> |
| <tr> |
| <td><%= escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) %></td> |
| <%= buildRegionDeployedServerTag(regionInfo, master, regionsToServer) %> |
| <td><%= readReq%></td> |
| <td><%= writeReq%></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> |
| <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> |
| <% |
| 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><%= 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';"> |
| <a id="openStackTrace" style="cursor:pointer;"> Show StackTrace</a> |
| </div> |
| <div id="closeStackTrace" style="display:none;clear:both;"> |
| <div onclick="document.getElementById('closeStackTrace').style.display='none';document.getElementById('openStackTrace').style.display='block';"> |
| <a style="cursor:pointer;"> Close StackTrace</a> |
| </div> |
| <% |
| for(StackTraceElement element : ex.getStackTrace()) { |
| %><%= StringEscapeUtils.escapeHtml4(element.toString() + "\n") %><% |
| } |
| } |
| } // end else |
| %> |
| |
| <h2>Table Stats</h2> |
| <table class="table table-striped"> |
| <tr> |
| <th>Name</th> |
| <th>Value</th> |
| <th>Description</th> |
| </tr> |
| <tr> |
| <td>Size</td> |
| <td> |
| <% |
| if (totalStoreFileSizeMB > 0) { |
| %> |
| <%= StringUtils.TraditionalBinaryPrefix. |
| long2String(totalStoreFileSizeMB * 1024 * 1024, "B", 2)%></td> |
| <% |
| } else { |
| %> |
| 0 MB </td> |
| <% |
| } |
| %> |
| <td>Total size of store files</td> |
| </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="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> |
| </div> |
| |
| <jsp:include page="footer.jsp" /> |
| <script src="/static/js/jquery.min.js" type="text/javascript"></script> |
| <script src="/static/js/jquery.tablesorter.min.js" type="text/javascript"></script> |
| <script src="/static/js/bootstrap.min.js" type="text/javascript"></script> |
| |
| <script> |
| $(document).ready(function() |
| { |
| $.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'} |
| } |
| }); |
| $("#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> |