<commit_before><%--
/**
 * 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. Only the report titles show if reports are empty.</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 { %>
        <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><span>Report created: <%= iso8601reportTime %> (now=<%= iso8601Now %>). Run <i>catalogjanitor_run</i> in hbase shell to generate a new sub-report.</span></p>
    </div>
  </div>
  <% if (report != null && !report.isEmpty()) { %>
      <% if (!report.getHoles().isEmpty()) { %>
          <div class="row inner_header">
            <div class="page-header">
              <h2>Holes</h2><commit_msg>HBASE-22993 HBCK report UI showed -1 if hbck chore not running (#610)<commit_after><%--
/**
 * 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. Only the report titles show if reports are empty.</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>
{'fraction_non_alphanumeric': 0.15609907120743033, 'fraction_numerical': 0.010092879256965944, 'mean_word_length': 3.363955687651986, 'pattern_counts': {'":': 4, '<': 381, '<?xml version=': 0, '>': 390, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4891347', 'n_tokens_mistral': 5512, 'n_tokens_neox': 5177, 'n_words': 1254}