Copilot commented on code in PR #8256:
URL: https://github.com/apache/hbase/pull/8256#discussion_r3263728973


##########
hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp:
##########
@@ -95,7 +100,51 @@
 
          <p> <%= count %> StoreFile(s) in set. <%= isReplicaRegion ? "The 
information about storefile(s) may not up-to-date because it's not the primary 
region." : "" %></p>
          </table>
-   <%  }
+
+       <% if (store instanceof HMobStore) { %>
+       <h4>MOB Files</h4>
+       <table class="table table-striped">
+         <tr>
+           <th>MOB File</th>
+           <th>Size (MB)</th>
+           <th>Modification time</th>
+         </tr>
+
+         <%
+         int mobCnt = 0;
+         for (HStoreFile sf : storeFiles) {
+           try {
+             byte[] value = sf.getMetadataValue(HStoreFile.MOB_FILE_REFS);
+             if (value == null) {
+               continue;
+             }
+
+             Collection<String> fileNames = 
MobUtils.deserializeMobFileRefs(value).build().values();
+             mobCnt += fileNames.size();
+             for (String fileName : fileNames) {
+               Path mobPath = new Path(((HMobStore) store).getPath(), 
fileName);
+               FileStatus status = fs.getFileStatus(mobPath);

Review Comment:
   The MOB file list is built by iterating each HStoreFile’s MOB_FILE_REFS and 
printing every referenced MOB filename. The same MOB file can be referenced by 
multiple store files, which will lead to duplicate rows and an inflated mobCnt. 
Consider deduplicating (e.g., collect into a Set, optionally sort) before 
rendering and counting, and then fetch FileStatus once per unique MOB path.



##########
hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp:
##########
@@ -95,7 +100,51 @@
 
          <p> <%= count %> StoreFile(s) in set. <%= isReplicaRegion ? "The 
information about storefile(s) may not up-to-date because it's not the primary 
region." : "" %></p>
          </table>
-   <%  }
+
+       <% if (store instanceof HMobStore) { %>
+       <h4>MOB Files</h4>
+       <table class="table table-striped">
+         <tr>
+           <th>MOB File</th>
+           <th>Size (MB)</th>
+           <th>Modification time</th>
+         </tr>
+
+         <%
+         int mobCnt = 0;
+         for (HStoreFile sf : storeFiles) {
+           try {
+             byte[] value = sf.getMetadataValue(HStoreFile.MOB_FILE_REFS);
+             if (value == null) {
+               continue;
+             }
+
+             Collection<String> fileNames = 
MobUtils.deserializeMobFileRefs(value).build().values();
+             mobCnt += fileNames.size();
+             for (String fileName : fileNames) {
+               Path mobPath = new Path(((HMobStore) store).getPath(), 
fileName);
+               FileStatus status = fs.getFileStatus(mobPath);
+               String mobPathStr = mobPath.toString();
+               String encodedStr = URLEncoder.encode(mobPathStr, 
StandardCharsets.UTF_8.toString()); %>
+
+               <tr>
+                 <td><a href="storeFile.jsp?name=<%= encodedStr %>"><%= 
mobPathStr %></a></td>
+                 <td><%= status.getLen() / 1024 / 1024 %></td>
+                 <td><%= new Date(status.getModificationTime()) %></td>

Review Comment:
   In the MOB files loop, we call fs.getFileStatus(mobPath) unconditionally. 
For replica regions, the store-file section skips files that are not present on 
the local FS (fs.exists(...)); the MOB section should do the same (or otherwise 
handle missing MOB files) to avoid throwing FileNotFoundException and rendering 
it to the page.



##########
hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp:
##########
@@ -95,7 +100,51 @@
 
          <p> <%= count %> StoreFile(s) in set. <%= isReplicaRegion ? "The 
information about storefile(s) may not up-to-date because it's not the primary 
region." : "" %></p>
          </table>
-   <%  }
+
+       <% if (store instanceof HMobStore) { %>
+       <h4>MOB Files</h4>
+       <table class="table table-striped">
+         <tr>
+           <th>MOB File</th>
+           <th>Size (MB)</th>
+           <th>Modification time</th>
+         </tr>
+
+         <%
+         int mobCnt = 0;
+         for (HStoreFile sf : storeFiles) {
+           try {
+             byte[] value = sf.getMetadataValue(HStoreFile.MOB_FILE_REFS);
+             if (value == null) {
+               continue;
+             }
+
+             Collection<String> fileNames = 
MobUtils.deserializeMobFileRefs(value).build().values();
+             mobCnt += fileNames.size();
+             for (String fileName : fileNames) {
+               Path mobPath = new Path(((HMobStore) store).getPath(), 
fileName);
+               FileStatus status = fs.getFileStatus(mobPath);
+               String mobPathStr = mobPath.toString();
+               String encodedStr = URLEncoder.encode(mobPathStr, 
StandardCharsets.UTF_8.toString()); %>
+
+               <tr>
+                 <td><a href="storeFile.jsp?name=<%= encodedStr %>"><%= 
mobPathStr %></a></td>
+                 <td><%= status.getLen() / 1024 / 1024 %></td>
+                 <td><%= new Date(status.getModificationTime()) %></td>
+               </tr>
+
+             <% }
+           } catch (Exception e) { %>
+             <tr>
+               <td colspan="3"><%= e %></td>
+             </tr>
+           <% }

Review Comment:
   Catching a generic Exception and printing it directly into the HTML table 
leaks internal details (paths, stack context in the message) and makes the UI 
noisy. Prefer catching expected exceptions (e.g., 
FileNotFoundException/IOException), logging server-side, and rendering a short, 
user-friendly message instead of dumping the exception object.



##########
hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp:
##########
@@ -95,7 +100,51 @@
 
          <p> <%= count %> StoreFile(s) in set. <%= isReplicaRegion ? "The 
information about storefile(s) may not up-to-date because it's not the primary 
region." : "" %></p>
          </table>
-   <%  }
+
+       <% if (store instanceof HMobStore) { %>
+       <h4>MOB Files</h4>
+       <table class="table table-striped">
+         <tr>
+           <th>MOB File</th>
+           <th>Size (MB)</th>
+           <th>Modification time</th>
+         </tr>
+
+         <%
+         int mobCnt = 0;
+         for (HStoreFile sf : storeFiles) {
+           try {
+             byte[] value = sf.getMetadataValue(HStoreFile.MOB_FILE_REFS);
+             if (value == null) {
+               continue;
+             }
+
+             Collection<String> fileNames = 
MobUtils.deserializeMobFileRefs(value).build().values();
+             mobCnt += fileNames.size();
+             for (String fileName : fileNames) {
+               Path mobPath = new Path(((HMobStore) store).getPath(), 
fileName);
+               FileStatus status = fs.getFileStatus(mobPath);
+               String mobPathStr = mobPath.toString();
+               String encodedStr = URLEncoder.encode(mobPathStr, 
StandardCharsets.UTF_8.toString()); %>
+
+               <tr>
+                 <td><a href="storeFile.jsp?name=<%= encodedStr %>"><%= 
mobPathStr %></a></td>
+                 <td><%= status.getLen() / 1024 / 1024 %></td>
+                 <td><%= new Date(status.getModificationTime()) %></td>
+               </tr>
+
+             <% }
+           } catch (Exception e) { %>
+             <tr>
+               <td colspan="3"><%= e %></td>
+             </tr>
+           <% }
+         } %>
+
+         <p> <%= mobCnt %> MobFile(s) in set.</p>
+       </table>

Review Comment:
   The summary paragraph ("<%= mobCnt %> MobFile(s) in set") is nested directly 
inside the <table>, which is invalid HTML (tables should contain 
caption/thead/tbody/tfoot/tr). Move the summary outside the table (or use a 
<caption>/<tfoot>) to keep the markup valid and consistent with HTML semantics.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to