blob: 0ac66782dc16f314678d7b2d285cbfac0486fa10 [file] [log] [blame]
<%--
/**
* 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="java.time.Instant"
import="java.time.ZoneId"
import="java.util.Date"
import="java.util.List"
import="java.util.Map"
import="java.util.stream.Collectors"
import="java.time.ZonedDateTime"
import="java.time.format.DateTimeFormatter"
%>
<%@ page import="org.apache.hadoop.fs.Path" %>
<%@ page import="org.apache.hadoop.hbase.client.RegionInfo" %>
<%@ page import="org.apache.hadoop.hbase.master.HbckChore" %>
<%@ page import="org.apache.hadoop.hbase.master.HMaster" %>
<%@ page import="org.apache.hadoop.hbase.ServerName" %>
<%@ page import="org.apache.hadoop.hbase.util.Bytes" %>
<%@ page import="org.apache.hadoop.hbase.util.Pair" %>
<%@ page import="org.apache.hadoop.hbase.master.CatalogJanitor" %>
<%@ page import="org.apache.hadoop.hbase.master.CatalogJanitor.Report" %>
<%
HMaster master = (HMaster) getServletContext().getAttribute(HMaster.MASTER);
pageContext.setAttribute("pageTitle", "HBase Master HBCK Report: " + master.getServerName());
HbckChore hbckChore = master.getHbckChore();
Map<String, Pair<ServerName, List<ServerName>>> inconsistentRegions = null;
Map<String, ServerName> orphanRegionsOnRS = null;
Map<String, Path> orphanRegionsOnFS = null;
long startTimestamp = 0;
long endTimestamp = 0;
if (hbckChore != null) {
inconsistentRegions = hbckChore.getInconsistentRegions();
orphanRegionsOnRS = hbckChore.getOrphanRegionsOnRS();
orphanRegionsOnFS = hbckChore.getOrphanRegionsOnFS();
startTimestamp = hbckChore.getCheckingStartTimestamp();
endTimestamp = hbckChore.getCheckingEndTimestamp();
}
ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochMilli(startTimestamp),
ZoneId.systemDefault());
String iso8601start = startTimestamp == 0? "-1": zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
zdt = ZonedDateTime.ofInstant(Instant.ofEpochMilli(endTimestamp),
ZoneId.systemDefault());
String iso8601end = startTimestamp == 0? "-1": zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
CatalogJanitor cj = master.getCatalogJanitor();
CatalogJanitor.Report report = cj == null? null: cj.getLastReport();
%>
<jsp:include page="header.jsp">
<jsp:param name="pageTitle" value="${pageTitle}"/>
</jsp:include>
<div class="container-fluid content">
<% if (!master.isInitialized()) { %>
<div class="row">
<div class="page-header">
<h1>Master is not initialized</h1>
</div>
</div>
<jsp:include page="redirect.jsp" />
<% } else { %>
<div class="row">
<div class="page-header">
<p><span>This page displays two reports: the 'HBCK Chore Report' and the 'CatalogJanitor Consistency Issues' report. Only titles show if there are no problems to report. Note some conditions are transitory as regions migrate.</span></p>
</div>
</div>
<div class="row">
<div class="page-header">
<h1>HBCK Chore Report</h1>
<p>
<% if (hbckChore.isDisabled()) { %>
<span>HBCK chore is currently disabled. Set hbase.master.hbck.chore.interval > 0 in the config & do a rolling-restart to enable it.</span>
<% } else if (startTimestamp == 0 && endTimestamp == 0){ %>
<span>No report created. Execute <i>hbck_chore_run</i> in hbase shell to generate a new sub-report.</span>
<% } else if (startTimestamp > 0 && endTimestamp == 0){ %>
<span>Checking started at <%= iso8601start %>. Please wait for checking to generate a new sub-report.</span>
<% } else { %>
<span>Checking started at <%= iso8601start %> and generated report at <%= iso8601end %>. Execute <i>hbck_chore_run</i> in hbase shell to generate a new sub-report.</span>
<% } %>
</p>
</div>
</div>
<% if (inconsistentRegions != null && inconsistentRegions.size() > 0) { %>
<div class="row">
<div class="page-header">
<h2>Inconsistent Regions</h2>
</div>
</div>
<p>
<span>
There are three cases: 1. Master thought this region opened, but no regionserver reported it (Fix: use assigns
command); 2. Master thought this region opened on Server1, but regionserver reported Server2 (Fix:
need to check the server is still exist. If not, schedule SCP for it. If exist, restart Server2 and Server1):
3. More than one regionservers reported opened this region (Fix: restart the RegionServers).
Notice: the reported online regionservers may be not right when there are regions in transition.
Please check them in regionserver's web UI.
</span>
</p>
<table class="table table-striped">
<tr>
<th>Region Encoded Name</th>
<th>Location in META</th>
<th>Reported Online RegionServers</th>
</tr>
<% for (Map.Entry<String, Pair<ServerName, List<ServerName>>> entry : inconsistentRegions.entrySet()) { %>
<tr>
<td><%= entry.getKey() %></td>
<td><%= entry.getValue().getFirst() %></td>
<td><%= entry.getValue().getSecond().stream().map(ServerName::getServerName)
.collect(Collectors.joining(", ")) %></td>
</tr>
<% } %>
<p><%= inconsistentRegions.size() %> region(s) in set.</p>
</table>
<% } %>
<% if (orphanRegionsOnRS != null && orphanRegionsOnRS.size() > 0) { %>
<div class="row">
<div class="page-header">
<h2>Orphan Regions on RegionServer</h2>
</div>
</div>
<table class="table table-striped">
<tr>
<th>Region Encoded Name</th>
<th>Reported Online RegionServer</th>
</tr>
<% for (Map.Entry<String, ServerName> entry : orphanRegionsOnRS.entrySet()) { %>
<tr>
<td><%= entry.getKey() %></td>
<td><%= entry.getValue() %></td>
</tr>
<% } %>
<p><%= orphanRegionsOnRS.size() %> region(s) in set.</p>
</table>
<% } %>
<% if (orphanRegionsOnFS != null && orphanRegionsOnFS.size() > 0) { %>
<div class="row">
<div class="page-header">
<h2>Orphan Regions on FileSystem</h2>
</div>
</div>
<table class="table table-striped">
<tr>
<th>Region Encoded Name</th>
<th>FileSystem Path</th>
</tr>
<% for (Map.Entry<String, Path> entry : orphanRegionsOnFS.entrySet()) { %>
<tr>
<td><%= entry.getKey() %></td>
<td><%= entry.getValue() %></td>
</tr>
<% } %>
<p><%= orphanRegionsOnFS.size() %> region(s) in set.</p>
</table>
<% } %>
<%
zdt = ZonedDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()),
ZoneId.systemDefault());
String iso8601Now = zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
String iso8601reportTime = "-1";
if (report != null) {
zdt = ZonedDateTime.ofInstant(Instant.ofEpochMilli(report.getCreateTime()),
ZoneId.systemDefault());
iso8601reportTime = zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}
%>
<div class="row inner_header">
<div class="page-header">
<h1>CatalogJanitor <em>hbase:meta</em> Consistency Issues</h1>
<p>
<% if (report != null) { %>
<span>Report created: <%= iso8601reportTime %> (now=<%= iso8601Now %>). Run <i>catalogjanitor_run</i> in hbase shell to generate a new sub-report.</span></p>
<% } else { %>
<span>No report created. Run <i>catalogjanitor_run</i> in hbase shell to generate a new sub-report.</span>
<% } %>
</div>
</div>
<% if (report != null && !report.isEmpty()) { %>
<% if (!report.getHoles().isEmpty()) { %>
<div class="row inner_header">
<div class="page-header">
<h2>Holes</h2>
</div>
</div>
<table class="table table-striped">
<tr>
<th>RegionInfo</th>
<th>RegionInfo</th>
</tr>
<% for (Pair<RegionInfo, RegionInfo> p : report.getHoles()) { %>
<tr>
<td><%= p.getFirst() %></td>
<td><%= p.getSecond() %></td>
</tr>
<% } %>
<p><%= report.getHoles().size() %> hole(s).</p>
</table>
<% } %>
<% if (!report.getOverlaps().isEmpty()) { %>
<div class="row inner_header">
<div class="page-header">
<h2>Overlaps</h2>
</div>
</div>
<table class="table table-striped">
<tr>
<th>RegionInfo</th>
<th>Other RegionInfo</th>
</tr>
<% for (Pair<RegionInfo, RegionInfo> p : report.getOverlaps()) { %>
<tr>
<td><%= p.getFirst() %></td>
<td><%= p.getSecond() %></td>
</tr>
<% } %>
<p><%= report.getOverlaps().size() %> overlap(s).</p>
</table>
<% } %>
<% if (!report.getUnknownServers().isEmpty()) { %>
<div class="row inner_header">
<div class="page-header">
<h2>Unknown Servers</h2>
</div>
</div>
<table class="table table-striped">
<tr>
<th>RegionInfo</th>
<th>ServerName</th>
</tr>
<% for (Pair<RegionInfo, ServerName> p: report.getUnknownServers()) { %>
<tr>
<td><%= p.getFirst() %></td>
<td><%= p.getSecond() %></td>
</tr>
<% } %>
<p><%= report.getUnknownServers().size() %> unknown servers(s).</p>
</table>
<% } %>
<% if (!report.getEmptyRegionInfo().isEmpty()) { %>
<div class="row inner_header">
<div class="page-header">
<h2>Empty <em>info:regioninfo</em></h2>
</div>
</div>
<table class="table table-striped">
<tr>
<th>Row</th>
</tr>
<% for (byte [] row: report.getEmptyRegionInfo()) { %>
<tr>
<td><%= Bytes.toStringBinary(row) %></td>
</tr>
<% } %>
<p><%= report.getEmptyRegionInfo().size() %> emptyRegionInfo(s).</p>
</table>
<% } %>
<% } %>
<% } %>
</div>
<jsp:include page="footer.jsp"/>