You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by nd...@apache.org on 2020/05/18 18:48:56 UTC
[hbase] branch branch-2 updated: HBASE-23969 Meta browser should
show all `info` columns (#1710)
This is an automated email from the ASF dual-hosted git repository.
ndimiduk pushed a commit to branch branch-2
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-2 by this push:
new 5893c4f HBASE-23969 Meta browser should show all `info` columns (#1710)
5893c4f is described below
commit 5893c4f393f4ef407e73aa44164d0ff1a7ec2ba6
Author: Mingliang Liu <li...@apache.org>
AuthorDate: Mon May 18 11:48:36 2020 -0700
HBASE-23969 Meta browser should show all `info` columns (#1710)
Signed-off-by: Nick Dimiduk <nd...@apache.org>
Signed-off-by: Viraj Jasani <vj...@apache.org>
---
.../org/apache/hadoop/hbase/MetaTableAccessor.java | 52 +++++++--
.../java/org/apache/hadoop/hbase/HConstants.java | 8 +-
.../hbase/master/assignment/RegionStateStore.java | 40 +------
.../hbase/master/webapp/RegionReplicaInfo.java | 60 ++++++++++-
.../main/resources/hbase-webapps/master/table.jsp | 116 +++++++++++++--------
.../resources/hbase-webapps/static/css/hbase.css | 4 +
6 files changed, 189 insertions(+), 91 deletions(-)
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
index e345483..dd0d1ff 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
@@ -383,33 +383,43 @@ public class MetaTableAccessor {
}
/**
- * @return Deserialized regioninfo values taken from column values that match
+ * @return Deserialized values of <qualifier,regioninfo> pairs taken from column values that match
* the regex 'info:merge.*' in array of <code>cells</code>.
*/
@Nullable
- public static List<RegionInfo> getMergeRegions(Cell [] cells) {
+ public static Map<String, RegionInfo> getMergeRegionsWithName(Cell [] cells) {
if (cells == null) {
return null;
}
- List<RegionInfo> regionsToMerge = null;
+ Map<String, RegionInfo> regionsToMerge = null;
for (Cell cell: cells) {
if (!isMergeQualifierPrefix(cell)) {
continue;
}
// Ok. This cell is that of a info:merge* column.
RegionInfo ri = RegionInfo.parseFromOrNull(cell.getValueArray(), cell.getValueOffset(),
- cell.getValueLength());
+ cell.getValueLength());
if (ri != null) {
if (regionsToMerge == null) {
- regionsToMerge = new ArrayList<>();
+ regionsToMerge = new LinkedHashMap<>();
}
- regionsToMerge.add(ri);
+ regionsToMerge.put(Bytes.toString(CellUtil.cloneQualifier(cell)), ri);
}
}
return regionsToMerge;
}
/**
+ * @return Deserialized regioninfo values taken from column values that match
+ * the regex 'info:merge.*' in array of <code>cells</code>.
+ */
+ @Nullable
+ public static List<RegionInfo> getMergeRegions(Cell [] cells) {
+ Map<String, RegionInfo> mergeRegionsWithName = getMergeRegionsWithName(cells);
+ return (mergeRegionsWithName == null) ? null : new ArrayList<>(mergeRegionsWithName.values());
+ }
+
+ /**
* @return True if any merge regions present in <code>cells</code>; i.e.
* the column in <code>cell</code> matches the regex 'info:merge.*'.
*/
@@ -904,8 +914,7 @@ public class MetaTableAccessor {
* @param replicaId the replicaId of the region
* @return a byte[] for sn column qualifier
*/
- @VisibleForTesting
- static byte[] getServerNameColumn(int replicaId) {
+ public static byte[] getServerNameColumn(int replicaId) {
return replicaId == 0 ? HConstants.SERVERNAME_QUALIFIER
: Bytes.toBytes(HConstants.SERVERNAME_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
+ String.format(RegionInfo.REPLICA_ID_FORMAT, replicaId));
@@ -998,6 +1007,33 @@ public class MetaTableAccessor {
}
/**
+ * Returns the {@link ServerName} from catalog table {@link Result} where the region is
+ * transitioning on. It should be the same as {@link MetaTableAccessor#getServerName(Result,int)}
+ * if the server is at OPEN state.
+ *
+ * @param r Result to pull the transitioning server name from
+ * @return A ServerName instance or {@link MetaTableAccessor#getServerName(Result,int)}
+ * if necessary fields not found or empty.
+ */
+ @Nullable
+ public static ServerName getTargetServerName(final Result r, final int replicaId) {
+ final Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY,
+ getServerNameColumn(replicaId));
+ if (cell == null || cell.getValueLength() == 0) {
+ RegionLocations locations = MetaTableAccessor.getRegionLocations(r);
+ if (locations != null) {
+ HRegionLocation location = locations.getRegionLocation(replicaId);
+ if (location != null) {
+ return location.getServerName();
+ }
+ }
+ return null;
+ }
+ return ServerName.parseServerName(Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
+ cell.getValueLength()));
+ }
+
+ /**
* The latest seqnum that the server writing to meta observed when opening the region.
* E.g. the seqNum when the result of {@link #getServerName(Result, int)} was written.
* @param r Result to pull the seqNum from
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
index b8098f4..fdc3532 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
@@ -535,11 +535,15 @@ public final class HConstants {
public static final byte [] SERVERNAME_QUALIFIER = Bytes.toBytes(SERVERNAME_QUALIFIER_STR);
+ /** The lower-half split region column qualifier string. */
+ public static final String SPLITA_QUALIFIER_STR = "splitA";
/** The lower-half split region column qualifier */
- public static final byte [] SPLITA_QUALIFIER = Bytes.toBytes("splitA");
+ public static final byte [] SPLITA_QUALIFIER = Bytes.toBytes(SPLITA_QUALIFIER_STR);
+ /** The upper-half split region column qualifier String. */
+ public static final String SPLITB_QUALIFIER_STR = "splitB";
/** The upper-half split region column qualifier */
- public static final byte [] SPLITB_QUALIFIER = Bytes.toBytes("splitB");
+ public static final byte [] SPLITB_QUALIFIER = Bytes.toBytes(SPLITB_QUALIFIER_STR);
/**
* Merge qualifier prefix.
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
index 808b2e5..c353161 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
@@ -134,7 +134,7 @@ public class RegionStateStore {
final State state = getRegionState(result, regionInfo);
final ServerName lastHost = hrl.getServerName();
- final ServerName regionLocation = getRegionServer(result, replicaId);
+ ServerName regionLocation = MetaTableAccessor.getTargetServerName(result, replicaId);
final long openSeqNum = hrl.getSeqNum();
// TODO: move under trace, now is visible for debugging
@@ -199,7 +199,7 @@ public class RegionStateStore {
put.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY)
.setRow(put.getRow())
.setFamily(HConstants.CATALOG_FAMILY)
- .setQualifier(getServerNameColumn(replicaId))
+ .setQualifier(MetaTableAccessor.getServerNameColumn(replicaId))
.setTimestamp(put.getTimestamp())
.setType(Cell.Type.Put)
.setValue(Bytes.toBytes(regionLocation.getServerName()))
@@ -300,42 +300,6 @@ public class RegionStateStore {
}
// ==========================================================================
- // Server Name
- // ==========================================================================
-
- /**
- * Returns the {@link ServerName} from catalog table {@link Result}
- * where the region is transitioning. It should be the same as
- * {@link MetaTableAccessor#getServerName(Result,int)} if the server is at OPEN state.
- * @param r Result to pull the transitioning server name from
- * @return A ServerName instance or {@link MetaTableAccessor#getServerName(Result,int)}
- * if necessary fields not found or empty.
- */
- static ServerName getRegionServer(final Result r, int replicaId) {
- final Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY,
- getServerNameColumn(replicaId));
- if (cell == null || cell.getValueLength() == 0) {
- RegionLocations locations = MetaTableAccessor.getRegionLocations(r);
- if (locations != null) {
- HRegionLocation location = locations.getRegionLocation(replicaId);
- if (location != null) {
- return location.getServerName();
- }
- }
- return null;
- }
- return ServerName.parseServerName(Bytes.toString(cell.getValueArray(),
- cell.getValueOffset(), cell.getValueLength()));
- }
-
- private static byte[] getServerNameColumn(int replicaId) {
- return replicaId == 0
- ? HConstants.SERVERNAME_QUALIFIER
- : Bytes.toBytes(HConstants.SERVERNAME_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
- + String.format(RegionInfo.REPLICA_ID_FORMAT, replicaId));
- }
-
- // ==========================================================================
// Region State
// ==========================================================================
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/webapp/RegionReplicaInfo.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/webapp/RegionReplicaInfo.java
index 554d49b..3e47d2a 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/webapp/RegionReplicaInfo.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/webapp/RegionReplicaInfo.java
@@ -18,13 +18,16 @@
package org.apache.hadoop.hbase.master.webapp;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.RegionLocations;
@@ -34,6 +37,7 @@ import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.master.RegionState;
import org.apache.hadoop.hbase.master.assignment.RegionStateStore;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.PairOfSameType;
import org.apache.yetus.audience.InterfaceAudience;
/**
@@ -45,6 +49,11 @@ public final class RegionReplicaInfo {
private final RegionInfo regionInfo;
private final RegionState.State regionState;
private final ServerName serverName;
+ private final long seqNum;
+ /** See {@link org.apache.hadoop.hbase.HConstants#SERVERNAME_QUALIFIER_STR}. */
+ private final ServerName targetServerName;
+ private final Map<String, RegionInfo> mergeRegionInfo;
+ private final Map<String, RegionInfo> splitRegionInfo;
private RegionReplicaInfo(final Result result, final HRegionLocation location) {
this.row = result != null ? result.getRow() : null;
@@ -53,6 +62,26 @@ public final class RegionReplicaInfo {
? RegionStateStore.getRegionState(result, regionInfo)
: null;
this.serverName = location != null ? location.getServerName() : null;
+ this.seqNum = (location != null) ? location.getSeqNum() : HConstants.NO_SEQNUM;
+ this.targetServerName = (result != null && regionInfo != null)
+ ? MetaTableAccessor.getTargetServerName(result, regionInfo.getReplicaId())
+ : null;
+ this.mergeRegionInfo = (result != null)
+ ? MetaTableAccessor.getMergeRegionsWithName(result.rawCells())
+ : null;
+
+ if (result != null) {
+ PairOfSameType<RegionInfo> daughterRegions = MetaTableAccessor.getDaughterRegions(result);
+ this.splitRegionInfo = new LinkedHashMap<>();
+ if (daughterRegions.getFirst() != null) {
+ splitRegionInfo.put(HConstants.SPLITA_QUALIFIER_STR, daughterRegions.getFirst());
+ }
+ if (daughterRegions.getSecond() != null) {
+ splitRegionInfo.put(HConstants.SPLITB_QUALIFIER_STR, daughterRegions.getSecond());
+ }
+ } else {
+ this.splitRegionInfo = null;
+ }
}
public static List<RegionReplicaInfo> from(final Result result) {
@@ -102,6 +131,22 @@ public final class RegionReplicaInfo {
return serverName;
}
+ public long getSeqNum() {
+ return seqNum;
+ }
+
+ public ServerName getTargetServerName() {
+ return targetServerName;
+ }
+
+ public Map<String, RegionInfo> getMergeRegionInfo() {
+ return mergeRegionInfo;
+ }
+
+ public Map<String, RegionInfo> getSplitRegionInfo() {
+ return splitRegionInfo;
+ }
+
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -119,6 +164,10 @@ public final class RegionReplicaInfo {
.append(regionInfo, that.regionInfo)
.append(regionState, that.regionState)
.append(serverName, that.serverName)
+ .append(seqNum, that.seqNum)
+ .append(targetServerName, that.targetServerName)
+ .append(mergeRegionInfo, that.mergeRegionInfo)
+ .append(splitRegionInfo, that.splitRegionInfo)
.isEquals();
}
@@ -129,15 +178,24 @@ public final class RegionReplicaInfo {
.append(regionInfo)
.append(regionState)
.append(serverName)
+ .append(seqNum)
+ .append(targetServerName)
+ .append(mergeRegionInfo)
+ .append(splitRegionInfo)
.toHashCode();
}
- @Override public String toString() {
+ @Override
+ public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("row", Bytes.toStringBinary(row))
.append("regionInfo", regionInfo)
.append("regionState", regionState)
.append("serverName", serverName)
+ .append("seqNum", seqNum)
+ .append("transitioningOnServerName", targetServerName)
+ .append("merge*", mergeRegionInfo)
+ .append("split*", splitRegionInfo)
.toString();
}
}
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
index 5a40139..8f9673c 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
@@ -70,6 +70,7 @@
<%@ 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.net.URLEncoder" %>
+<%@ page import="java.util.stream.Collectors" %>
<%!
/**
* @return An empty region load stamped with the passed in <code>regionInfo</code>
@@ -385,16 +386,27 @@
<%
}
}
+
+ 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;
%>
- <table class="table table-striped">
- <tr>
- <th>RegionName</th>
- <th>Start Key</th>
- <th>End Key</th>
- <th>Replica ID</th>
- <th>RegionState</th>
- <th>ServerName</th>
- </tr>
+ <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;
@@ -405,49 +417,69 @@
.orElse(null);
if (regionReplicaInfo == null) {
%>
- <tr>
- <td colspan="6">Null result</td>
- </tr>
+ <tr>
+ <td colspan="6">Null result</td>
+ </tr>
<%
- continue;
- }
+ 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 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 long seqNum = regionReplicaInfo.getSeqNum();
- final RegionInfo regionInfo = regionReplicaInfo.getRegionInfo();
- final ServerName serverName = regionReplicaInfo.getServerName();
- final RegionState.State regionState = regionReplicaInfo.getRegionState();
- final int rsPort = master.getRegionServerInfoPort(serverName);
+ 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><%= regionNameDisplay %></td>
- <td><%= startKeyDisplay %></td>
- <td><%= endKeyDisplay %></td>
- <td><%= replicaIdDisplay %></td>
- <td><%= regionStateDisplay %></td>
- <td><%= buildRegionServerLink(serverName, rsPort, regionInfo, regionState) %></td>
- </tr>
+ <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 %>"><%= buildRegionServerLink(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>
+ </table>
+ </div>
<div class="row">
<div class="col-md-4">
<ul class="pagination" style="margin: 20px 0">
diff --git a/hbase-server/src/main/resources/hbase-webapps/static/css/hbase.css b/hbase-server/src/main/resources/hbase-webapps/static/css/hbase.css
index 04eb496..182f2ae 100644
--- a/hbase-server/src/main/resources/hbase-webapps/static/css/hbase.css
+++ b/hbase-server/src/main/resources/hbase-webapps/static/css/hbase.css
@@ -54,3 +54,7 @@ table.tablesorter thead tr .headerSortUp {
table.tablesorter thead tr .headerSortDown {
background-image: url(desc.gif);
}
+
+table.nowrap th, table.nowrap td {
+ white-space: nowrap;
+}