<%doc>
Copyright The Apache Software Foundation

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.
 </%doc>

<%args>
HMaster master;
ServerManager serverManager;
</%args>

<%import>
    java.util.Collections;
    java.util.List;
    java.util.Map;
    java.util.Set;
    java.util.stream.Collectors;
    org.apache.hadoop.hbase.master.HMaster;
    org.apache.hadoop.hbase.RegionMetrics;
    org.apache.hadoop.hbase.ServerMetrics;
    org.apache.hadoop.hbase.Size;
    org.apache.hadoop.hbase.RSGroupTableAccessor;
    org.apache.hadoop.hbase.master.ServerManager;
    org.apache.hadoop.hbase.net.Address;
    org.apache.hadoop.hbase.rsgroup.RSGroupInfo;
    org.apache.hadoop.util.StringUtils;
    org.apache.hadoop.util.StringUtils.TraditionalBinaryPrefix;
</%import>
<%java>
List<RSGroupInfo> groups = RSGroupTableAccessor.getAllRSGroupInfo(master.getConnection());
</%java>
<%if (groups != null && groups.size() > 0)%>

<%java>
RSGroupInfo [] rsGroupInfos = groups.toArray(new RSGroupInfo[groups.size()]);
Map<Address, ServerMetrics> collectServers = Collections.emptyMap();
if (master.getServerManager() != null) {
  collectServers =
      master.getServerManager().getOnlineServers().entrySet().stream()
          .collect(Collectors.toMap(p -> p.getKey().getAddress(), Map.Entry::getValue));
}
</%java>

<div class="tabbable">
    <ul class="nav nav-pills">
        <li class="active"><a href="#tab_rsgroup_baseStats" data-toggle="tab">Base Stats</a></li>
        <li class=""><a href="#tab_rsgroup_memoryStats" data-toggle="tab">Memory</a></li>
        <li class=""><a href="#tab_rsgroup_requestStats" data-toggle="tab">Requests</a></li>
        <li class=""><a href="#tab_rsgroup_storeStats" data-toggle="tab">Storefiles</a></li>
        <li class=""><a href="#tab_rsgroup_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_rsgroup_baseStats">
            <& rsgroup_baseStats; rsGroupInfos = rsGroupInfos; collectServers= collectServers &>
        </div>
        <div class="tab-pane" id="tab_rsgroup_memoryStats">
            <& rsgroup_memoryStats; rsGroupInfos = rsGroupInfos; collectServers= collectServers &>
        </div>
        <div class="tab-pane" id="tab_rsgroup_requestStats">
            <& rsgroup_requestStats; rsGroupInfos = rsGroupInfos; collectServers= collectServers &>
        </div>
        <div class="tab-pane" id="tab_rsgroup_storeStats">
            <& rsgroup_storeStats; rsGroupInfos = rsGroupInfos; collectServers= collectServers &>
        </div>
        <div class="tab-pane" id="tab_rsgroup_compactStats">
            <& rsgroup_compactStats; rsGroupInfos = rsGroupInfos; collectServers= collectServers &>
        </div>
    </div>
</div>

</%if>

<%def rsgroup_baseStats>
<%args>
    RSGroupInfo [] rsGroupInfos;
    Map<Address, ServerMetrics> collectServers;
</%args>
<table class="table table-striped">
<tr>
    <th>RSGroup Name</th>
    <th>Num. Online Servers</th>
    <th>Num. Dead Servers</th>
    <th>Num. Tables</th>
    <th>Requests Per Second</th>
    <th>Num. Regions</th>
    <th>Average Load</th>
</tr>
<%java>
    int totalOnlineServers = 0;
    int totalDeadServers = 0;
    int totalTables = 0;
    int totalRequests = 0;
    int totalRegions = 0;
    for (RSGroupInfo rsGroupInfo: rsGroupInfos) {
      String rsGroupName = rsGroupInfo.getName();
      int onlineServers = 0;
      int deadServers = 0;
      int tables = 0;
      long requestsPerSecond = 0;
      int numRegionsOnline = 0;
      Set<Address> servers = rsGroupInfo.getServers();
      for (Address server : servers) {
        ServerMetrics sl = collectServers.get(server);
        if (sl != null) {
          requestsPerSecond += sl.getRequestCountPerSecond();
          numRegionsOnline += sl.getRegionMetrics().size();
          //rsgroup total
          totalRegions += sl.getRegionMetrics().size();
          totalRequests += sl.getRequestCountPerSecond();
          totalOnlineServers++;
          onlineServers++;
        } else {
          totalDeadServers++;
          deadServers++;
        }
      }
      tables = rsGroupInfo.getTables().size();
      totalTables += tables;
      double avgLoad = onlineServers == 0 ? 0 :
            (double)numRegionsOnline / (double)onlineServers;
</%java>
<tr>
    <td><& rsGroupLink; rsGroupName=rsGroupName; &></td>
    <td><% onlineServers %></td>
    <td><% deadServers %></td>
    <td><% tables %></td>
    <td><% requestsPerSecond %></td>
    <td><% numRegionsOnline %></td>
    <td><% StringUtils.limitDecimalTo2(avgLoad) %></td>
</tr>
<%java>
}
</%java>
<tr><td>Total:<% rsGroupInfos.length %></td>
<td><% totalOnlineServers %></td>
<td><% totalDeadServers %></td>
<td><% totalTables %></td>
<td><% totalRequests %></td>
<td><% totalRegions %></td>
<td><% StringUtils.limitDecimalTo2(master.getServerManager().getAverageLoad()) %></td>
</tr>
</table>
</%def>

<%def rsgroup_memoryStats>
<%args>
  RSGroupInfo [] rsGroupInfos;
  Map<Address, ServerMetrics> collectServers;
</%args>
<table class="table table-striped">
<tr>
    <th>RSGroup Name</th>
    <th>Used Heap</th>
    <th>Max Heap</th>
    <th>Memstore Size</th>

</tr>
<%java>
    final String ZEROMB = "0 MB";
    String usedHeapStr = ZEROMB;
    String maxHeapStr = ZEROMB;
    String memstoreSizeStr = ZEROMB;
    for (RSGroupInfo rsGroupInfo: rsGroupInfos) {
      String rsGroupName = rsGroupInfo.getName();
      long usedHeap = 0;
      long maxHeap = 0;
      long memstoreSize = 0;
      for (Address server : rsGroupInfo.getServers()) {
        ServerMetrics sl = collectServers.get(server);
        if (sl != null) {
          usedHeap += (long) sl.getUsedHeapSize().get(Size.Unit.MEGABYTE);
          maxHeap += (long) sl.getMaxHeapSize().get(Size.Unit.MEGABYTE);
          memstoreSize += (long) sl.getRegionMetrics().values().stream().mapToDouble(
            rm -> rm.getMemStoreSize().get(Size.Unit.MEGABYTE)).sum();
        }
      }

      if (usedHeap > 0) {
        usedHeapStr = TraditionalBinaryPrefix.long2String(usedHeap
                                      * TraditionalBinaryPrefix.MEGA.value, "B", 1);
      }
      if (maxHeap > 0) {
        maxHeapStr = TraditionalBinaryPrefix.long2String(maxHeap
                                      * TraditionalBinaryPrefix.MEGA.value, "B", 1);
      }
      if (memstoreSize > 0) {
        memstoreSizeStr = TraditionalBinaryPrefix.long2String(memstoreSize
                                      * TraditionalBinaryPrefix.MEGA.value, "B", 1);
      }
</%java>
<tr>
    <td><& rsGroupLink; rsGroupName=rsGroupName; &></td>
    <td><% usedHeapStr %></td>
    <td><% maxHeapStr %></td>
    <td><% memstoreSizeStr %></td>

</tr>
<%java>
}
</%java>
</table>
</%def>

<%def rsgroup_requestStats>
<%args>
  RSGroupInfo [] rsGroupInfos;
  Map<Address, ServerMetrics> collectServers;
</%args>
<table class="table table-striped">
<tr>
    <th>RSGroup Name</th>
    <th>Request Per Second</th>
    <th>Read Request Count</th>
    <th>Write Request Count</th>
</tr>
<%java>
    for (RSGroupInfo rsGroupInfo: rsGroupInfos) {
      String rsGroupName = rsGroupInfo.getName();
      long requestsPerSecond = 0;
      long readRequests = 0;
      long writeRequests = 0;
      for (Address server : rsGroupInfo.getServers()) {
        ServerMetrics sl = collectServers.get(server);
        if (sl != null) {
          for (RegionMetrics rm : sl.getRegionMetrics().values()) {
            readRequests += rm.getReadRequestCount();
            writeRequests += rm.getWriteRequestCount();
          }
          requestsPerSecond += sl.getRequestCountPerSecond();
        }
      }
</%java>
<tr>
<td><& rsGroupLink; rsGroupName=rsGroupName; &></td>
<td><% requestsPerSecond %></td>
<td><% readRequests %></td>
<td><% writeRequests %></td>
</tr>
<%java>
}
</%java>
</table>
</%def>


<%def rsgroup_storeStats>
<%args>
  RSGroupInfo [] rsGroupInfos;
  Map<Address, ServerMetrics> collectServers;
</%args>
<table class="table table-striped">
<tr>
    <th>RSGroup Name</th>
    <th>Num. Stores</th>
    <th>Num. Storefiles</th>
    <th>Storefile Size Uncompressed</th>
    <th>Storefile Size</th>
    <th>Index Size</th>
    <th>Bloom Size</th>
</tr>
<%java>
    final String ZEROKB = "0 KB";
    final String ZEROMB = "0 MB";
    String uncompressedStorefileSizeStr = ZEROMB;
    String storefileSizeStr = ZEROMB;
    String indexSizeStr = ZEROKB;
    String bloomSizeStr = ZEROKB;
    for (RSGroupInfo rsGroupInfo: rsGroupInfos) {
      String rsGroupName = rsGroupInfo.getName();
      int numStores = 0;
      long numStorefiles = 0;
      long uncompressedStorefileSize  = 0;
      long storefileSize  = 0;
      long indexSize  = 0;
      long bloomSize  = 0;
      int count = 0;
      for (Address server : rsGroupInfo.getServers()) {
        ServerMetrics sl = collectServers.get(server);
        if (sl != null) {
          for (RegionMetrics rm : sl.getRegionMetrics().values()) {
            numStores += rm.getStoreCount();
            numStorefiles += rm.getStoreFileCount();
            uncompressedStorefileSize += rm.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
            storefileSize += rm.getStoreFileSize().get(Size.Unit.MEGABYTE);
            indexSize += rm.getStoreFileUncompressedDataIndexSize().get(Size.Unit.KILOBYTE);
            bloomSize += rm.getBloomFilterSize().get(Size.Unit.KILOBYTE);
          }
          count++;
        }
      }
       if (uncompressedStorefileSize > 0) {
          uncompressedStorefileSizeStr = TraditionalBinaryPrefix.
          long2String(uncompressedStorefileSize * TraditionalBinaryPrefix.MEGA.value, "B", 1);
       }
       if (storefileSize > 0) {
           storefileSizeStr = TraditionalBinaryPrefix.
           long2String(storefileSize * TraditionalBinaryPrefix.MEGA.value, "B", 1);
       }
       if (indexSize > 0) {
          indexSizeStr = TraditionalBinaryPrefix.
          long2String(indexSize * TraditionalBinaryPrefix.KILO.value, "B", 1);
       }
       if (bloomSize > 0) {
           bloomSizeStr = TraditionalBinaryPrefix.
           long2String(bloomSize * TraditionalBinaryPrefix.KILO.value, "B", 1);
       }
</%java>
<tr>
<td><& rsGroupLink; rsGroupName=rsGroupName; &></td>
<td><% numStores %></td>
<td><% numStorefiles %></td>
<td><% uncompressedStorefileSizeStr %></td>
<td><% storefileSizeStr %></td>
<td><% indexSizeStr %></td>
<td><% bloomSizeStr %></td>
</tr>
<%java>
}
</%java>
</table>
</%def>

<%def rsgroup_compactStats>
<%args>
  RSGroupInfo [] rsGroupInfos;
  Map<Address, ServerMetrics> collectServers;
</%args>
<table class="table table-striped">
<tr>
    <th>RSGroup Name</th>
    <th>Num. Compacting Cells</th>
    <th>Num. Compacted Cells</th>
    <th>Remaining Cells</th>
    <th>Compaction Progress</th>
</tr>
<%java>
    for (RSGroupInfo rsGroupInfo: rsGroupInfos) {
      String rsGroupName = rsGroupInfo.getName();
      int numStores = 0;
      long totalCompactingCells = 0;
      long totalCompactedCells = 0;
      long remainingCells = 0;
      long compactionProgress  = 0;
      for (Address server : rsGroupInfo.getServers()) {
        ServerMetrics sl = collectServers.get(server);
        if (sl != null) {
          for (RegionMetrics rl : sl.getRegionMetrics().values()) {
            totalCompactingCells += rl.getCompactingCellCount();
            totalCompactedCells += rl.getCompactedCellCount();
          }
        }
      }
      remainingCells = totalCompactingCells - totalCompactedCells;
      String percentDone = "";
      if  (totalCompactingCells > 0) {
           percentDone = String.format("%.2f", 100 *
              ((float) totalCompactedCells / totalCompactingCells)) + "%";
      }
</%java>
<tr>
<td><& rsGroupLink; rsGroupName=rsGroupName; &></td>
<td><% totalCompactingCells %></td>
<td><% totalCompactedCells %></td>
<td><% remainingCells %></td>
<td><% percentDone %></td>
</tr>
<%java>
}
</%java>
</table>
</%def>


<%def rsGroupLink>
    <%args>
    String rsGroupName;
    </%args>
    <a href=rsgroup.jsp?name=<% rsGroupName %>><% rsGroupName %></a>
</%def>
