You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by bu...@apache.org on 2017/09/24 00:34:10 UTC
[10/47] hbase git commit: HBASE-17980 Any HRegionInfo we give out
should be immutable
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java
new file mode 100644
index 0000000..a76767d
--- /dev/null
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java
@@ -0,0 +1,624 @@
+/**
+ *
+ * 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.
+ */
+package org.apache.hadoop.hbase.client;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.yetus.audience.InterfaceAudience;
+
+import java.util.Arrays;
+
+@InterfaceAudience.Private
+public class RegionInfoBuilder {
+ private static final Log LOG = LogFactory.getLog(RegionInfoBuilder.class);
+
+ /** A non-capture group so that this can be embedded. */
+ public static final String ENCODED_REGION_NAME_REGEX = "(?:[a-f0-9]+)";
+
+ private static final int MAX_REPLICA_ID = 0xFFFF;
+
+ //TODO: Move NO_HASH to HStoreFile which is really the only place it is used.
+ public static final String NO_HASH = null;
+
+ /**
+ * RegionInfo for first meta region
+ * You cannot use this builder to make an instance of the {@link #FIRST_META_REGIONINFO}.
+ * Just refer to this instance. Also, while the instance is actually a MutableRI, its type is
+ * just RI so the mutable methods are not available (unless you go casting); it appears
+ * as immutable (I tried adding Immutable type but it just makes a mess).
+ */
+ // TODO: How come Meta regions still do not have encoded region names? Fix.
+ // hbase:meta,,1.1588230740 should be the hbase:meta first region name.
+ public static final RegionInfo FIRST_META_REGIONINFO =
+ new MutableRegionInfo(1L, TableName.META_TABLE_NAME, RegionInfo.DEFAULT_REPLICA_ID);
+
+ private MutableRegionInfo content = null;
+
+ public static RegionInfoBuilder newBuilder(TableName tableName) {
+ return new RegionInfoBuilder(tableName);
+ }
+
+ public static RegionInfoBuilder newBuilder(RegionInfo regionInfo) {
+ return new RegionInfoBuilder(regionInfo);
+ }
+
+ private RegionInfoBuilder(TableName tableName) {
+ this.content = new MutableRegionInfo(tableName);
+ }
+
+ private RegionInfoBuilder(RegionInfo regionInfo) {
+ this.content = new MutableRegionInfo(regionInfo);
+ }
+
+ public RegionInfoBuilder setStartKey(byte[] startKey) {
+ content.setStartKey(startKey);
+ return this;
+ }
+
+ public RegionInfoBuilder setEndKey(byte[] endKey) {
+ content.setEndKey(endKey);
+ return this;
+ }
+
+ public RegionInfoBuilder setRegionId(long regionId) {
+ content.setRegionId(regionId);
+ return this;
+ }
+
+ public RegionInfoBuilder setReplicaId(int replicaId) {
+ content.setReplicaId(replicaId);
+ return this;
+ }
+
+ public RegionInfoBuilder setSplit(boolean isSplit) {
+ content.setSplit(isSplit);
+ return this;
+ }
+
+ public RegionInfoBuilder setOffline(boolean isOffline) {
+ content.setOffline(isOffline);
+ return this;
+ }
+
+ public RegionInfo build() {
+ RegionInfo ri = new MutableRegionInfo(content);
+ // Run a late check that we are not creating default meta region.
+ if (ri.getTable().equals(TableName.META_TABLE_NAME) &&
+ ri.getReplicaId() == RegionInfo.DEFAULT_REPLICA_ID) {
+ throw new IllegalArgumentException("Cannot create the default meta region; " +
+ "use static define FIRST_META_REGIONINFO");
+ }
+ return new MutableRegionInfo(content);
+ }
+
+ /**
+ * An implementation of RegionInfo that adds mutable methods so can build a RegionInfo instance.
+ */
+ @InterfaceAudience.Private
+ static class MutableRegionInfo implements RegionInfo, Comparable<RegionInfo> {
+ /**
+ * The new format for a region name contains its encodedName at the end.
+ * The encoded name also serves as the directory name for the region
+ * in the filesystem.
+ *
+ * New region name format:
+ * <tablename>,,<startkey>,<regionIdTimestamp>.<encodedName>.
+ * where,
+ * <encodedName> is a hex version of the MD5 hash of
+ * <tablename>,<startkey>,<regionIdTimestamp>
+ *
+ * The old region name format:
+ * <tablename>,<startkey>,<regionIdTimestamp>
+ * For region names in the old format, the encoded name is a 32-bit
+ * JenkinsHash integer value (in its decimal notation, string form).
+ *<p>
+ * **NOTE**
+ *
+ * The first hbase:meta region, and regions created by an older
+ * version of HBase (0.20 or prior) will continue to use the
+ * old region name format.
+ */
+
+ // This flag is in the parent of a split while the parent is still referenced
+ // by daughter regions. We USED to set this flag when we disabled a table
+ // but now table state is kept up in zookeeper as of 0.90.0 HBase.
+ private boolean offLine = false;
+ private boolean split = false;
+ private long regionId = -1;
+ private int replicaId = RegionInfo.DEFAULT_REPLICA_ID;
+ private transient byte [] regionName = HConstants.EMPTY_BYTE_ARRAY;
+ private byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
+ private byte [] endKey = HConstants.EMPTY_BYTE_ARRAY;
+ private int hashCode = -1;
+ private String encodedName;
+ private byte [] encodedNameAsBytes;
+ // Current TableName
+ private TableName tableName;
+
+ private void setHashCode() {
+ int result = Arrays.hashCode(this.regionName);
+ result ^= this.regionId;
+ result ^= Arrays.hashCode(this.startKey);
+ result ^= Arrays.hashCode(this.endKey);
+ result ^= Boolean.valueOf(this.offLine).hashCode();
+ result ^= Arrays.hashCode(this.tableName.getName());
+ result ^= this.replicaId;
+ this.hashCode = result;
+ }
+
+ /**
+ * Private constructor used constructing MutableRegionInfo for the
+ * first meta regions
+ */
+ private MutableRegionInfo(long regionId, TableName tableName, int replicaId) {
+ // This constructor is currently private for making hbase:meta region only.
+ super();
+ this.regionId = regionId;
+ this.tableName = tableName;
+ this.replicaId = replicaId;
+ // Note: First Meta region replicas names are in old format so we pass false here.
+ this.regionName =
+ RegionInfo.createRegionName(tableName, null, regionId, replicaId, false);
+ setHashCode();
+ }
+
+ MutableRegionInfo(final TableName tableName) {
+ this(tableName, null, null);
+ }
+
+ /**
+ * Construct MutableRegionInfo with explicit parameters
+ *
+ * @param tableName the table name
+ * @param startKey first key in region
+ * @param endKey end of key range
+ * @throws IllegalArgumentException
+ */
+ MutableRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey)
+ throws IllegalArgumentException {
+ this(tableName, startKey, endKey, false);
+ }
+
+ /**
+ * Construct MutableRegionInfo with explicit parameters
+ *
+ * @param tableName the table descriptor
+ * @param startKey first key in region
+ * @param endKey end of key range
+ * @param split true if this region has split and we have daughter regions
+ * regions that may or may not hold references to this region.
+ * @throws IllegalArgumentException
+ */
+ MutableRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
+ final boolean split)
+ throws IllegalArgumentException {
+ this(tableName, startKey, endKey, split, System.currentTimeMillis());
+ }
+
+ /**
+ * Construct MutableRegionInfo with explicit parameters
+ *
+ * @param tableName the table descriptor
+ * @param startKey first key in region
+ * @param endKey end of key range
+ * @param split true if this region has split and we have daughter regions
+ * regions that may or may not hold references to this region.
+ * @param regionid Region id to use.
+ * @throws IllegalArgumentException
+ */
+ MutableRegionInfo(final TableName tableName, final byte[] startKey,
+ final byte[] endKey, final boolean split, final long regionid)
+ throws IllegalArgumentException {
+ this(tableName, startKey, endKey, split, regionid, RegionInfo.DEFAULT_REPLICA_ID);
+ }
+
+ /**
+ * Construct MutableRegionInfo with explicit parameters
+ *
+ * @param tableName the table descriptor
+ * @param startKey first key in region
+ * @param endKey end of key range
+ * @param split true if this region has split and we have daughter regions
+ * regions that may or may not hold references to this region.
+ * @param regionid Region id to use.
+ * @param replicaId the replicaId to use
+ * @throws IllegalArgumentException
+ */
+ MutableRegionInfo(final TableName tableName, final byte[] startKey,
+ final byte[] endKey, final boolean split, final long regionid,
+ final int replicaId)
+ throws IllegalArgumentException {
+ super();
+ if (tableName == null) {
+ throw new IllegalArgumentException("TableName cannot be null");
+ }
+ this.tableName = tableName;
+ this.offLine = false;
+ this.regionId = regionid;
+ this.replicaId = replicaId;
+ if (this.replicaId > MAX_REPLICA_ID) {
+ throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID);
+ }
+
+ this.regionName = RegionInfo.createRegionName(this.tableName, startKey, regionId, replicaId,
+ !this.tableName.equals(TableName.META_TABLE_NAME));
+
+ this.split = split;
+ this.endKey = endKey == null? HConstants.EMPTY_END_ROW: endKey.clone();
+ this.startKey = startKey == null?
+ HConstants.EMPTY_START_ROW: startKey.clone();
+ this.tableName = tableName;
+ setHashCode();
+ }
+
+ /**
+ * Construct MutableRegionInfo.
+ * Only for RegionInfoBuilder to use.
+ * @param other
+ */
+ MutableRegionInfo(MutableRegionInfo other, boolean isMetaRegion) {
+ super();
+ if (other.getTable() == null) {
+ throw new IllegalArgumentException("TableName cannot be null");
+ }
+ this.tableName = other.getTable();
+ this.offLine = other.isOffline();
+ this.regionId = other.getRegionId();
+ this.replicaId = other.getReplicaId();
+ if (this.replicaId > MAX_REPLICA_ID) {
+ throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID);
+ }
+
+ if(isMetaRegion) {
+ // Note: First Meta region replicas names are in old format
+ this.regionName = RegionInfo.createRegionName(
+ other.getTable(), null, other.getRegionId(),
+ other.getReplicaId(), false);
+ } else {
+ this.regionName = RegionInfo.createRegionName(
+ other.getTable(), other.getStartKey(), other.getRegionId(),
+ other.getReplicaId(), true);
+ }
+
+ this.split = other.isSplit();
+ this.endKey = other.getEndKey() == null? HConstants.EMPTY_END_ROW: other.getEndKey().clone();
+ this.startKey = other.getStartKey() == null?
+ HConstants.EMPTY_START_ROW: other.getStartKey().clone();
+ this.tableName = other.getTable();
+ setHashCode();
+ }
+
+ /**
+ * Construct a copy of RegionInfo as MutableRegionInfo.
+ * Only for RegionInfoBuilder to use.
+ * @param regionInfo
+ */
+ MutableRegionInfo(RegionInfo regionInfo) {
+ super();
+ this.endKey = regionInfo.getEndKey();
+ this.offLine = regionInfo.isOffline();
+ this.regionId = regionInfo.getRegionId();
+ this.regionName = regionInfo.getRegionName();
+ this.split = regionInfo.isSplit();
+ this.startKey = regionInfo.getStartKey();
+ this.hashCode = regionInfo.hashCode();
+ this.encodedName = regionInfo.getEncodedName();
+ this.tableName = regionInfo.getTable();
+ this.replicaId = regionInfo.getReplicaId();
+ }
+
+ /**
+ * @return Return a short, printable name for this region
+ * (usually encoded name) for us logging.
+ */
+ @Override
+ public String getShortNameToLog() {
+ return RegionInfo.prettyPrint(this.getEncodedName());
+ }
+
+ /** @return the regionId */
+ @Override
+ public long getRegionId(){
+ return regionId;
+ }
+
+ /**
+ * set region id.
+ * @param regionId
+ * @return MutableRegionInfo
+ */
+ public MutableRegionInfo setRegionId(long regionId) {
+ this.regionId = regionId;
+ return this;
+ }
+
+ /**
+ * @return the regionName as an array of bytes.
+ * @see #getRegionNameAsString()
+ */
+ @Override
+ public byte [] getRegionName(){
+ return regionName;
+ }
+
+ /**
+ * set region name.
+ * @param regionName
+ * @return MutableRegionInfo
+ */
+ public MutableRegionInfo setRegionName(byte[] regionName) {
+ this.regionName = regionName;
+ return this;
+ }
+
+ /**
+ * @return Region name as a String for use in logging, etc.
+ */
+ @Override
+ public String getRegionNameAsString() {
+ if (RegionInfo.hasEncodedName(this.regionName)) {
+ // new format region names already have their encoded name.
+ return Bytes.toStringBinary(this.regionName);
+ }
+
+ // old format. regionNameStr doesn't have the region name.
+ //
+ //
+ return Bytes.toStringBinary(this.regionName) + "." + this.getEncodedName();
+ }
+
+ /** @return the encoded region name */
+ @Override
+ public synchronized String getEncodedName() {
+ if (this.encodedName == null) {
+ this.encodedName = RegionInfo.encodeRegionName(this.regionName);
+ }
+ return this.encodedName;
+ }
+
+ @Override
+ public synchronized byte [] getEncodedNameAsBytes() {
+ if (this.encodedNameAsBytes == null) {
+ this.encodedNameAsBytes = Bytes.toBytes(getEncodedName());
+ }
+ return this.encodedNameAsBytes;
+ }
+
+ /** @return the startKey */
+ @Override
+ public byte [] getStartKey(){
+ return startKey;
+ }
+
+ /**
+ * @param startKey
+ * @return MutableRegionInfo
+ */
+ public MutableRegionInfo setStartKey(byte[] startKey) {
+ this.startKey = startKey;
+ return this;
+ }
+
+ /** @return the endKey */
+ @Override
+ public byte [] getEndKey(){
+ return endKey;
+ }
+
+ /**
+ * @param endKey
+ * @return MutableRegionInfo
+ */
+ public MutableRegionInfo setEndKey(byte[] endKey) {
+ this.endKey = endKey;
+ return this;
+ }
+
+ /**
+ * Get current table name of the region
+ * @return TableName
+ */
+ @Override
+ public TableName getTable() {
+ // This method name should be getTableName but there was already a method getTableName
+ // that returned a byte array. It is unfortunate given everywhere else, getTableName returns
+ // a TableName instance.
+ if (tableName == null || tableName.getName().length == 0) {
+ tableName = RegionInfo.getTable(getRegionName());
+ }
+ return this.tableName;
+ }
+
+ /**
+ * Returns true if the given inclusive range of rows is fully contained
+ * by this region. For example, if the region is foo,a,g and this is
+ * passed ["b","c"] or ["a","c"] it will return true, but if this is passed
+ * ["b","z"] it will return false.
+ * @throws IllegalArgumentException if the range passed is invalid (ie. end < start)
+ */
+ @Override
+ public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) {
+ if (Bytes.compareTo(rangeStartKey, rangeEndKey) > 0) {
+ throw new IllegalArgumentException(
+ "Invalid range: " + Bytes.toStringBinary(rangeStartKey) +
+ " > " + Bytes.toStringBinary(rangeEndKey));
+ }
+
+ boolean firstKeyInRange = Bytes.compareTo(rangeStartKey, startKey) >= 0;
+ boolean lastKeyInRange =
+ Bytes.compareTo(rangeEndKey, endKey) < 0 ||
+ Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY);
+ return firstKeyInRange && lastKeyInRange;
+ }
+
+ /**
+ * Return true if the given row falls in this region.
+ */
+ @Override
+ public boolean containsRow(byte[] row) {
+ return Bytes.compareTo(row, startKey) >= 0 &&
+ (Bytes.compareTo(row, endKey) < 0 ||
+ Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY));
+ }
+
+ /**
+ * @return true if this region is from hbase:meta
+ */
+ @Override
+ public boolean isMetaTable() {
+ return isMetaRegion();
+ }
+
+ /** @return true if this region is a meta region */
+ @Override
+ public boolean isMetaRegion() {
+ return tableName.equals(FIRST_META_REGIONINFO.getTable());
+ }
+
+ /**
+ * @return true if this region is from a system table
+ */
+ @Override
+ public boolean isSystemTable() {
+ return tableName.isSystemTable();
+ }
+
+ /**
+ * @return True if has been split and has daughters.
+ */
+ @Override
+ public boolean isSplit() {
+ return this.split;
+ }
+
+ /**
+ * @param split set split status
+ * @return MutableRegionInfo
+ */
+ public MutableRegionInfo setSplit(boolean split) {
+ this.split = split;
+ return this;
+ }
+
+ /**
+ * @return True if this region is offline.
+ */
+ @Override
+ public boolean isOffline() {
+ return this.offLine;
+ }
+
+ /**
+ * The parent of a region split is offline while split daughters hold
+ * references to the parent. Offlined regions are closed.
+ * @param offLine Set online/offline status.
+ * @return MutableRegionInfo
+ */
+ public MutableRegionInfo setOffline(boolean offLine) {
+ this.offLine = offLine;
+ return this;
+ }
+
+ /**
+ * @return True if this is a split parent region.
+ */
+ @Override
+ public boolean isSplitParent() {
+ if (!isSplit()) return false;
+ if (!isOffline()) {
+ LOG.warn("Region is split but NOT offline: " + getRegionNameAsString());
+ }
+ return true;
+ }
+
+ /**
+ * Returns the region replica id
+ * @return returns region replica id
+ */
+ @Override
+ public int getReplicaId() {
+ return replicaId;
+ }
+
+ public MutableRegionInfo setReplicaId(int replicaId) {
+ this.replicaId = replicaId;
+ return this;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "{ENCODED => " + getEncodedName() + ", " +
+ HConstants.NAME + " => '" + Bytes.toStringBinary(this.regionName)
+ + "', STARTKEY => '" +
+ Bytes.toStringBinary(this.startKey) + "', ENDKEY => '" +
+ Bytes.toStringBinary(this.endKey) + "'" +
+ (isOffline()? ", OFFLINE => true": "") +
+ (isSplit()? ", SPLIT => true": "") +
+ ((replicaId > 0)? ", REPLICA_ID => " + replicaId : "") + "}";
+ }
+
+ /**
+ * @param o
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null) {
+ return false;
+ }
+ if (!(o instanceof RegionInfo)) {
+ return false;
+ }
+ return this.compareTo((RegionInfo)o) == 0;
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return this.hashCode;
+ }
+
+ @Override
+ public int compareTo(RegionInfo other) {
+ return RegionInfo.COMPARATOR.compare(this, other);
+ }
+
+ /**
+ * @return Comparator to use comparing {@link KeyValue}s.
+ * @deprecated Use Region#getCellComparator(). deprecated for hbase 2.0, remove for hbase 3.0
+ */
+ @Deprecated
+ public KeyValue.KVComparator getComparator() {
+ return isMetaRegion()?
+ KeyValue.META_COMPARATOR: KeyValue.COMPARATOR;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoDisplay.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoDisplay.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoDisplay.java
new file mode 100644
index 0000000..7ced1b3
--- /dev/null
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoDisplay.java
@@ -0,0 +1,135 @@
+/*
+ *
+ * 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.
+ */
+package org.apache.hadoop.hbase.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.RegionInfo;
+import org.apache.hadoop.hbase.client.RegionInfoBuilder;
+import org.apache.hadoop.hbase.master.RegionState;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.yetus.audience.InterfaceAudience;
+
+import java.io.IOException;
+
+/**
+ * Utility used composing RegionInfo for 'display'; e.g. on the web UI
+ */
+@InterfaceAudience.Private
+public class RegionInfoDisplay {
+ public final static String DISPLAY_KEYS_KEY = "hbase.display.keys";
+ public final static byte[] HIDDEN_END_KEY = Bytes.toBytes("hidden-end-key");
+ public final static byte[] HIDDEN_START_KEY = Bytes.toBytes("hidden-start-key");
+
+ /**
+ * Get the descriptive name as {@link RegionState} does it but with hidden
+ * startkey optionally
+ * @return descriptive string
+ */
+ public static String getDescriptiveNameFromRegionStateForDisplay(RegionState state,
+ Configuration conf) {
+ if (conf.getBoolean(DISPLAY_KEYS_KEY, true)) return state.toDescriptiveString();
+ String descriptiveStringFromState = state.toDescriptiveString();
+ int idx = descriptiveStringFromState.lastIndexOf(" state=");
+ String regionName = getRegionNameAsStringForDisplay(
+ RegionInfoBuilder.newBuilder(state.getRegion()).build(), conf);
+ return regionName + descriptiveStringFromState.substring(idx);
+ }
+
+ /**
+ * Get the end key for display. Optionally hide the real end key.
+ * @return the endkey
+ */
+ public static byte[] getEndKeyForDisplay(RegionInfo ri, Configuration conf) {
+ boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
+ if (displayKey) return ri.getEndKey();
+ return HIDDEN_END_KEY;
+ }
+
+ /**
+ * Get the start key for display. Optionally hide the real start key.
+ * @param ri
+ * @param conf
+ * @return the startkey
+ */
+ public static byte[] getStartKeyForDisplay(RegionInfo ri, Configuration conf) {
+ boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
+ if (displayKey) return ri.getStartKey();
+ return HIDDEN_START_KEY;
+ }
+
+ /**
+ * Get the region name for display. Optionally hide the start key.
+ * @param ri
+ * @param conf
+ * @return region name as String
+ */
+ public static String getRegionNameAsStringForDisplay(RegionInfo ri, Configuration conf) {
+ return Bytes.toStringBinary(getRegionNameForDisplay(ri, conf));
+ }
+
+ /**
+ * Get the region name for display. Optionally hide the start key.
+ * @param ri
+ * @param conf
+ * @return region name bytes
+ */
+ public static byte[] getRegionNameForDisplay(RegionInfo ri, Configuration conf) {
+ boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
+ if (displayKey || ri.getTable().equals(TableName.META_TABLE_NAME)) {
+ return ri.getRegionName();
+ } else {
+ // create a modified regionname with the startkey replaced but preserving
+ // the other parts including the encodedname.
+ try {
+ byte[][]regionNameParts = RegionInfo.parseRegionName(ri.getRegionName());
+ regionNameParts[1] = HIDDEN_START_KEY; //replace the real startkey
+ int len = 0;
+ // get the total length
+ for (byte[] b : regionNameParts) {
+ len += b.length;
+ }
+ byte[] encodedRegionName =
+ Bytes.toBytes(RegionInfo.encodeRegionName(ri.getRegionName()));
+ len += encodedRegionName.length;
+ //allocate some extra bytes for the delimiters and the last '.'
+ byte[] modifiedName = new byte[len + regionNameParts.length + 1];
+ int lengthSoFar = 0;
+ int loopCount = 0;
+ for (byte[] b : regionNameParts) {
+ System.arraycopy(b, 0, modifiedName, lengthSoFar, b.length);
+ lengthSoFar += b.length;
+ if (loopCount++ == 2) modifiedName[lengthSoFar++] = RegionInfo.REPLICA_ID_DELIMITER;
+ else modifiedName[lengthSoFar++] = HConstants.DELIMITER;
+ }
+ // replace the last comma with '.'
+ modifiedName[lengthSoFar - 1] = RegionInfo.ENC_SEPARATOR;
+ System.arraycopy(encodedRegionName, 0, modifiedName, lengthSoFar,
+ encodedRegionName.length);
+ lengthSoFar += encodedRegionName.length;
+ modifiedName[lengthSoFar] = RegionInfo.ENC_SEPARATOR;
+ return modifiedName;
+ } catch (IOException e) {
+ //LOG.warn("Encountered exception " + e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java
index 502e0a5..2c1d478 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java
@@ -57,6 +57,7 @@ public class RegionReplicaUtil {
* @return an HRegionInfo object corresponding to the same range (table, start and
* end key), but for the given replicaId.
*/
+ @Deprecated // Deprecated for HBase-2.0.0, use #getRegionInfoForReplica
public static HRegionInfo getRegionInfoForReplica(HRegionInfo regionInfo, int replicaId) {
if (regionInfo.getReplicaId() == replicaId) {
return regionInfo;
@@ -73,6 +74,37 @@ public class RegionReplicaUtil {
}
/**
+ * Returns the RegionInfo for the given replicaId.
+ * RegionInfo's correspond to a range of a table, but more than one
+ * "instance" of the same range can be deployed which are differentiated by
+ * the replicaId.
+ * @param regionInfo
+ * @param replicaId the replicaId to use
+ * @return an RegionInfo object corresponding to the same range (table, start and
+ * end key), but for the given replicaId.
+ */
+ public static RegionInfo getRegionInfoForReplica(RegionInfo regionInfo, int replicaId) {
+ if (regionInfo.getReplicaId() == replicaId) {
+ return regionInfo;
+ }
+ RegionInfoBuilder replicaInfo;
+ RegionInfo ri;
+ if (regionInfo.isMetaRegion()) {
+ ri = RegionInfoBuilder.FIRST_META_REGIONINFO;
+ } else {
+ replicaInfo = RegionInfoBuilder.newBuilder(regionInfo.getTable())
+ .setStartKey(regionInfo.getStartKey())
+ .setEndKey(regionInfo.getEndKey())
+ .setSplit(regionInfo.isSplit())
+ .setRegionId(regionInfo.getRegionId())
+ .setReplicaId(replicaId);
+ replicaInfo.setOffline(regionInfo.isOffline());
+ ri = replicaInfo.build();
+ }
+ return ri;
+ }
+
+ /**
* Returns the HRegionInfo for the default replicaId (0). HRegionInfo's correspond to
* a range of a table, but more than one "instance" of the same range can be
* deployed which are differentiated by the replicaId.
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/main/java/org/apache/hadoop/hbase/client/UnmodifyableHRegionInfo.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/UnmodifyableHRegionInfo.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/UnmodifyableHRegionInfo.java
index 89900d4..dfe04e7 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/UnmodifyableHRegionInfo.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/UnmodifyableHRegionInfo.java
@@ -22,7 +22,7 @@ package org.apache.hadoop.hbase.client;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.yetus.audience.InterfaceAudience;
-@InterfaceAudience.Public
+@InterfaceAudience.Private
class UnmodifyableHRegionInfo extends HRegionInfo {
/*
* Creates an unmodifyable copy of an HRegionInfo
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
index 711315f..3c9738e 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
@@ -79,7 +79,9 @@ import org.apache.hadoop.hbase.client.Increment;
import org.apache.hadoop.hbase.client.Mutation;
import org.apache.hadoop.hbase.client.PackagePrivateFieldAccessor;
import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.RegionInfoBuilder;
import org.apache.hadoop.hbase.client.RegionLoadStats;
+import org.apache.hadoop.hbase.client.RegionReplicaUtil;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.SnapshotDescription;
@@ -3306,4 +3308,66 @@ public final class ProtobufUtil {
}
return lockedResourceJsons.toString();
}
+
+ /**
+ * Convert a RegionInfo to a Proto RegionInfo
+ *
+ * @param info the RegionInfo to convert
+ * @return the converted Proto RegionInfo
+ */
+ public static HBaseProtos.RegionInfo toProtoRegionInfo(final org.apache.hadoop.hbase.client.RegionInfo info) {
+ if (info == null) return null;
+ HBaseProtos.RegionInfo.Builder builder = HBaseProtos.RegionInfo.newBuilder();
+ builder.setTableName(ProtobufUtil.toProtoTableName(info.getTable()));
+ builder.setRegionId(info.getRegionId());
+ if (info.getStartKey() != null) {
+ builder.setStartKey(UnsafeByteOperations.unsafeWrap(info.getStartKey()));
+ }
+ if (info.getEndKey() != null) {
+ builder.setEndKey(UnsafeByteOperations.unsafeWrap(info.getEndKey()));
+ }
+ builder.setOffline(info.isOffline());
+ builder.setSplit(info.isSplit());
+ builder.setReplicaId(info.getReplicaId());
+ return builder.build();
+ }
+
+ /**
+ * Convert HBaseProto.RegionInfo to a RegionInfo
+ *
+ * @param proto the RegionInfo to convert
+ * @return the converted RegionInfo
+ */
+ public static org.apache.hadoop.hbase.client.RegionInfo toRegionInfo(final HBaseProtos.RegionInfo proto) {
+ if (proto == null) return null;
+ TableName tableName = ProtobufUtil.toTableName(proto.getTableName());
+ long regionId = proto.getRegionId();
+ int defaultReplicaId = org.apache.hadoop.hbase.client.RegionInfo.DEFAULT_REPLICA_ID;
+ int replicaId = proto.hasReplicaId()? proto.getReplicaId(): defaultReplicaId;
+ if (tableName.equals(TableName.META_TABLE_NAME) && replicaId == defaultReplicaId) {
+ return RegionInfoBuilder.FIRST_META_REGIONINFO;
+ }
+ byte[] startKey = null;
+ byte[] endKey = null;
+ if (proto.hasStartKey()) {
+ startKey = proto.getStartKey().toByteArray();
+ }
+ if (proto.hasEndKey()) {
+ endKey = proto.getEndKey().toByteArray();
+ }
+ boolean split = false;
+ if (proto.hasSplit()) {
+ split = proto.getSplit();
+ }
+ RegionInfoBuilder rib = RegionInfoBuilder.newBuilder(tableName)
+ .setStartKey(startKey)
+ .setEndKey(endKey)
+ .setRegionId(regionId)
+ .setReplicaId(replicaId)
+ .setSplit(split);
+ if (proto.hasOffline()) {
+ rib.setOffline(proto.getOffline());
+ }
+ return rib.build();
+ }
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/MetaTableLocator.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/MetaTableLocator.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/MetaTableLocator.java
index 0787f11..dada632 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/MetaTableLocator.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/MetaTableLocator.java
@@ -443,7 +443,8 @@ public class MetaTableLocator {
LOG.warn("Tried to set null ServerName in hbase:meta; skipping -- ServerName required");
return;
}
- LOG.info("Setting hbase:meta region location in ZooKeeper as " + serverName);
+ LOG.info("Setting hbase:meta (replicaId=" + replicaId + ") location in ZooKeeper as " +
+ serverName);
// Make the MetaRegionServer pb and then get its bytes and save this as
// the znode content.
MetaRegionServer pbrsr = MetaRegionServer.newBuilder()
@@ -458,7 +459,7 @@ public class MetaTableLocator {
if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
LOG.debug("META region location doesn't exist, create it");
} else {
- LOG.debug("META region location doesn't exist for replicaId " + replicaId +
+ LOG.debug("META region location doesn't exist for replicaId=" + replicaId +
", create it");
}
ZKUtil.createAndWatch(zookeeper, zookeeper.znodePaths.getZNodeForReplica(replicaId), data);
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestImmutableHRegionInfo.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestImmutableHRegionInfo.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestImmutableHRegionInfo.java
new file mode 100644
index 0000000..4644641
--- /dev/null
+++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestImmutableHRegionInfo.java
@@ -0,0 +1,61 @@
+/**
+ * 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.
+ */
+package org.apache.hadoop.hbase.client;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.testclassification.ClientTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import static org.junit.Assert.fail;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+
+/**
+ * Test ImmutableHRegionInfo
+ */
+@Category({ClientTests.class, SmallTests.class})
+public class TestImmutableHRegionInfo {
+
+ @Rule
+ public TestName name = new TestName();
+
+ private final List<Consumer<ImmutableHRegionInfo>> TEST_FUNCTIONS = Arrays.asList(
+ hri -> hri.setOffline(true),
+ hri -> hri.setSplit(true)
+ );
+
+ @Test
+ public void testImmutable() {
+ HRegionInfo hri = new HRegionInfo(TableName.valueOf(name.getMethodName()));
+ ImmutableHRegionInfo immutableHri = new ImmutableHRegionInfo(hri);
+
+ TEST_FUNCTIONS.forEach(f -> {
+ try {
+ f.accept(immutableHri);
+ fail("ImmutableHRegionInfo can't be modified !!!");
+ } catch(UnsupportedOperationException e) {
+ }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoDisplay.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoDisplay.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoDisplay.java
new file mode 100644
index 0000000..978e8c8
--- /dev/null
+++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestRegionInfoDisplay.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+package org.apache.hadoop.hbase.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.CategoryBasedTimeout;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.RegionInfo;
+import org.apache.hadoop.hbase.client.RegionInfoBuilder;
+import org.apache.hadoop.hbase.client.RegionInfoDisplay;
+import org.apache.hadoop.hbase.master.RegionState;
+import org.apache.hadoop.hbase.testclassification.MasterTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+import org.junit.rules.TestRule;
+
+import java.io.IOException;
+
+@Category({MasterTests.class, SmallTests.class})
+public class TestRegionInfoDisplay {
+ @Rule
+ public final TestRule timeout = CategoryBasedTimeout.builder().withTimeout(this.getClass()).
+ withLookingForStuckThread(true).build();
+ @Rule public TestName name = new TestName();
+
+ @Test
+ public void testRegionDetailsForDisplay() throws IOException {
+ byte[] startKey = new byte[] {0x01, 0x01, 0x02, 0x03};
+ byte[] endKey = new byte[] {0x01, 0x01, 0x02, 0x04};
+ Configuration conf = new Configuration();
+ conf.setBoolean("hbase.display.keys", false);
+ RegionInfo ri = RegionInfoBuilder.newBuilder(TableName.valueOf(name.getMethodName()))
+ .setStartKey(startKey).setEndKey(endKey).build();
+ checkEquality(ri, conf);
+ // check HRIs with non-default replicaId
+ ri = RegionInfoBuilder.newBuilder(TableName.valueOf(name.getMethodName()))
+ .setStartKey(startKey)
+ .setEndKey(endKey)
+ .setSplit(false)
+ .setRegionId(System.currentTimeMillis())
+ .setReplicaId(1).build();
+ checkEquality(ri, conf);
+ Assert.assertArrayEquals(RegionInfoDisplay.HIDDEN_END_KEY,
+ RegionInfoDisplay.getEndKeyForDisplay(ri, conf));
+ Assert.assertArrayEquals(RegionInfoDisplay.HIDDEN_START_KEY,
+ RegionInfoDisplay.getStartKeyForDisplay(ri, conf));
+
+ RegionState state = new RegionState(convert(ri), RegionState.State.OPEN);
+ String descriptiveNameForDisplay =
+ RegionInfoDisplay.getDescriptiveNameFromRegionStateForDisplay(state, conf);
+ checkDescriptiveNameEquality(descriptiveNameForDisplay,state.toDescriptiveString(), startKey);
+
+ conf.setBoolean("hbase.display.keys", true);
+ Assert.assertArrayEquals(endKey, RegionInfoDisplay.getEndKeyForDisplay(ri, conf));
+ Assert.assertArrayEquals(startKey, RegionInfoDisplay.getStartKeyForDisplay(ri, conf));
+ Assert.assertEquals(state.toDescriptiveString(),
+ RegionInfoDisplay.getDescriptiveNameFromRegionStateForDisplay(state, conf));
+ }
+
+ private void checkDescriptiveNameEquality(String descriptiveNameForDisplay, String origDesc,
+ byte[] startKey) {
+ // except for the "hidden-start-key" substring everything else should exactly match
+ String firstPart = descriptiveNameForDisplay.substring(0,
+ descriptiveNameForDisplay.indexOf(new String(RegionInfoDisplay.HIDDEN_START_KEY)));
+ String secondPart = descriptiveNameForDisplay.substring(
+ descriptiveNameForDisplay.indexOf(new String(RegionInfoDisplay.HIDDEN_START_KEY)) +
+ RegionInfoDisplay.HIDDEN_START_KEY.length);
+ String firstPartOrig = origDesc.substring(0,
+ origDesc.indexOf(Bytes.toStringBinary(startKey)));
+ String secondPartOrig = origDesc.substring(
+ origDesc.indexOf(Bytes.toStringBinary(startKey)) +
+ Bytes.toStringBinary(startKey).length());
+ assert(firstPart.equals(firstPartOrig));
+ assert(secondPart.equals(secondPartOrig));
+ }
+
+ private void checkEquality(RegionInfo ri, Configuration conf) throws IOException {
+ byte[] modifiedRegionName = RegionInfoDisplay.getRegionNameForDisplay(ri, conf);
+ System.out.println(Bytes.toString(modifiedRegionName) + " " + ri.toString());
+ byte[][] modifiedRegionNameParts = RegionInfo.parseRegionName(modifiedRegionName);
+ byte[][] regionNameParts = RegionInfo.parseRegionName(ri.getRegionName());
+
+ //same number of parts
+ assert(modifiedRegionNameParts.length == regionNameParts.length);
+ for (int i = 0; i < regionNameParts.length; i++) {
+ // all parts should match except for [1] where in the modified one,
+ // we should have "hidden_start_key"
+ if (i != 1) {
+ System.out.println("" + i + " " + Bytes.toString(regionNameParts[i]) + " " +
+ Bytes.toString(modifiedRegionNameParts[i]));
+ Assert.assertArrayEquals(regionNameParts[i], modifiedRegionNameParts[i]);
+ } else {
+ System.out.println("" + i + " " + Bytes.toString(regionNameParts[i]) + " " +
+ Bytes.toString(modifiedRegionNameParts[i]));
+ Assert.assertNotEquals(regionNameParts[i], modifiedRegionNameParts[i]);
+ Assert.assertArrayEquals(modifiedRegionNameParts[1],
+ RegionInfoDisplay.getStartKeyForDisplay(ri, conf));
+ }
+ }
+ }
+
+ private HRegionInfo convert(RegionInfo ri) {
+ HRegionInfo hri = new HRegionInfo(
+ ri.getTable(), ri.getStartKey(), ri.getEndKey(), ri.isSplit(), ri.getRegionId());
+ hri.setOffline(ri.isOffline());
+ return hri;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
index b5e6dd0..bb3686b 100644
--- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
+++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
@@ -17,7 +17,6 @@ See the License for the specific language governing permissions and
limitations under the License.
</%doc>
<%import>
-org.apache.hadoop.hbase.HRegionInfo;
org.apache.hadoop.hbase.master.assignment.AssignmentManager;
org.apache.hadoop.hbase.master.assignment.AssignmentManager.RegionInTransitionStat;
org.apache.hadoop.hbase.master.assignment.RegionStates.RegionFailedOpen;
@@ -25,6 +24,7 @@ org.apache.hadoop.hbase.master.RegionState;
org.apache.hadoop.conf.Configuration;
org.apache.hadoop.hbase.HBaseConfiguration;
org.apache.hadoop.hbase.HConstants;
+org.apache.hadoop.hbase.client.RegionInfoDisplay;
java.util.HashSet;
java.util.SortedSet;
java.util.Map;
@@ -94,7 +94,7 @@ int numOfPages = (int) Math.ceil(numOfRITs * 1.0 / ritsPerPage);
}
</%java>
<td><% rs.getRegion().getEncodedName() %></td><td>
- <% HRegionInfo.getDescriptiveNameFromRegionStateForDisplay(rs,
+ <% RegionInfoDisplay.getDescriptiveNameFromRegionStateForDisplay(rs,
assignmentManager.getConfiguration()) %></td>
<td><% (currentTime - rs.getStamp()) %> </td>
<td> <% retryStatus %> </td>
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java
index f58cbaf..3a9c34a 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java
@@ -19,37 +19,36 @@
package org.apache.hadoop.hbase.master.assignment;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListMap;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
-import org.apache.yetus.audience.InterfaceAudience;
import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
import org.apache.hadoop.hbase.master.RegionState;
import org.apache.hadoop.hbase.master.RegionState.State;
import org.apache.hadoop.hbase.procedure2.ProcedureEvent;
+import org.apache.hadoop.hbase.shaded.com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
+import org.apache.yetus.audience.InterfaceAudience;
-import org.apache.hadoop.hbase.shaded.com.google.common.annotations.VisibleForTesting;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
/**
* RegionStates contains a set of Maps that describes the in-memory state of the AM, with
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-server/src/test/java/org/apache/hadoop/hbase/MetaMockingUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/MetaMockingUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/MetaMockingUtil.java
index 9a1515b..a89237e 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/MetaMockingUtil.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/MetaMockingUtil.java
@@ -105,17 +105,4 @@ public class MetaMockingUtil {
return Result.create(kvs);
}
- /**
- * @param sn ServerName to use making startcode and server in meta
- * @param hri Region to serialize into HRegionInfo
- * @return A mocked up Result that fakes a Get on a row in the <code>hbase:meta</code> table.
- * @throws IOException
- */
- public static Result getMetaTableRowResultAsSplitRegion(final HRegionInfo hri,
- final ServerName sn) throws IOException {
- hri.setOffline(true);
- hri.setSplit(true);
- return getMetaTableRowResult(hri, sn);
- }
-
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStates.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStates.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStates.java
index 003dfdd..0087ecd 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStates.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStates.java
@@ -18,16 +18,6 @@
package org.apache.hadoop.hbase.master.assignment;
-import static org.junit.Assert.assertEquals;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.Future;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HBaseTestingUtility;
@@ -45,6 +35,16 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
@Category({MasterTests.class, MediumTests.class})
public class TestRegionStates {
private static final Log LOG = LogFactory.getLog(TestRegionStates.class);
@@ -217,8 +217,4 @@ public class TestRegionStates {
StringUtils.humanTimeDiff(et - st),
StringUtils.humanSize(NRUNS / ((et - st) / 1000.0f))));
}
-
- // ==========================================================================
- // Server related
- // ==========================================================================
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/58988cb5/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfoBuilder.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfoBuilder.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfoBuilder.java
new file mode 100644
index 0000000..497ecc4
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionInfoBuilder.java
@@ -0,0 +1,323 @@
+/**
+ *
+ * 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.
+ */
+package org.apache.hadoop.hbase.regionserver;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.RegionInfo;
+import org.apache.hadoop.hbase.client.RegionInfoBuilder;
+import org.apache.hadoop.hbase.client.TableDescriptor;
+import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
+import org.apache.hadoop.hbase.exceptions.DeserializationException;
+import org.apache.hadoop.hbase.shaded.com.google.protobuf.UnsafeByteOperations;
+import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
+import org.apache.hadoop.hbase.testclassification.RegionServerTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.FSTableDescriptors;
+import org.apache.hadoop.hbase.util.MD5Hash;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+
+@Category({RegionServerTests.class, SmallTests.class})
+public class TestRegionInfoBuilder {
+ @Rule
+ public TestName name = new TestName();
+
+ @Test
+ public void testBuilder() {
+ TableName tn = TableName.valueOf("test");
+ RegionInfoBuilder builder = RegionInfoBuilder.newBuilder(tn);
+ byte[] startKey = Bytes.toBytes("a");
+ builder.setStartKey(startKey);
+ byte[] endKey = Bytes.toBytes("z");
+ builder.setEndKey(endKey);
+ int regionId = 1;
+ builder.setRegionId(1);
+ int replicaId = 2;
+ builder.setReplicaId(replicaId);
+ boolean offline = true;
+ builder.setOffline(offline);
+ boolean isSplit = true;
+ builder.setSplit(isSplit);
+ RegionInfo ri = builder.build();
+
+ assertEquals(tn, ri.getTable());
+ assertArrayEquals(startKey, ri.getStartKey());
+ assertArrayEquals(endKey, ri.getEndKey());
+ assertEquals(regionId, ri.getRegionId());
+ assertEquals(replicaId, ri.getReplicaId());
+ assertEquals(offline, ri.isOffline());
+ assertEquals(isSplit, ri.isSplit());
+ }
+
+ @Test
+ public void testPb() throws DeserializationException {
+ RegionInfo ri = RegionInfoBuilder.FIRST_META_REGIONINFO;
+ byte [] bytes = RegionInfo.toByteArray(ri);
+ RegionInfo pbri = RegionInfo.parseFrom(bytes);
+ assertTrue(ri.equals(pbri));
+ }
+
+ @Test
+ public void testReadAndWriteRegionInfoFile() throws IOException, InterruptedException {
+ HBaseTestingUtility htu = new HBaseTestingUtility();
+ RegionInfo ri = RegionInfoBuilder.FIRST_META_REGIONINFO;
+ Path basedir = htu.getDataTestDir();
+ // Create a region. That'll write the .regioninfo file.
+ FSTableDescriptors fsTableDescriptors = new FSTableDescriptors(htu.getConfiguration());
+ HRegion r = HBaseTestingUtility.createRegionAndWAL(convert(ri), basedir, htu.getConfiguration(),
+ fsTableDescriptors.get(TableName.META_TABLE_NAME));
+ // Get modtime on the file.
+ long modtime = getModTime(r);
+ HBaseTestingUtility.closeRegionAndWAL(r);
+ Thread.sleep(1001);
+ r = HRegion.openHRegion(basedir, convert(ri), fsTableDescriptors.get(TableName.META_TABLE_NAME),
+ null, htu.getConfiguration());
+ // Ensure the file is not written for a second time.
+ long modtime2 = getModTime(r);
+ assertEquals(modtime, modtime2);
+ // Now load the file.
+ RegionInfo deserializedRi = HRegionFileSystem.loadRegionInfoFileContent(
+ r.getRegionFileSystem().getFileSystem(), r.getRegionFileSystem().getRegionDir());
+ HBaseTestingUtility.closeRegionAndWAL(r);
+ }
+
+ long getModTime(final HRegion r) throws IOException {
+ FileStatus[] statuses = r.getRegionFileSystem().getFileSystem().listStatus(
+ new Path(r.getRegionFileSystem().getRegionDir(), HRegionFileSystem.REGION_INFO_FILE));
+ assertTrue(statuses != null && statuses.length == 1);
+ return statuses[0].getModificationTime();
+ }
+
+ @Test
+ public void testCreateRegionInfoName() throws Exception {
+ final String tableName = name.getMethodName();
+ final TableName tn = TableName.valueOf(tableName);
+ String startKey = "startkey";
+ final byte[] sk = Bytes.toBytes(startKey);
+ String id = "id";
+
+ // old format region name
+ byte [] name = RegionInfo.createRegionName(tn, sk, id, false);
+ String nameStr = Bytes.toString(name);
+ assertEquals(tableName + "," + startKey + "," + id, nameStr);
+
+
+ // new format region name.
+ String md5HashInHex = MD5Hash.getMD5AsHex(name);
+ assertEquals(RegionInfo.MD5_HEX_LENGTH, md5HashInHex.length());
+ name = RegionInfo.createRegionName(tn, sk, id, true);
+ nameStr = Bytes.toString(name);
+ assertEquals(tableName + "," + startKey + ","
+ + id + "." + md5HashInHex + ".",
+ nameStr);
+ }
+
+ @Test
+ public void testContainsRange() {
+ TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(
+ TableName.valueOf(name.getMethodName())).build();
+ RegionInfo ri = RegionInfoBuilder.newBuilder(tableDesc.getTableName())
+ .setStartKey(Bytes.toBytes("a"))
+ .setEndKey(Bytes.toBytes("g")).build();
+ // Single row range at start of region
+ assertTrue(ri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("a")));
+ // Fully contained range
+ assertTrue(ri.containsRange(Bytes.toBytes("b"), Bytes.toBytes("c")));
+ // Range overlapping start of region
+ assertTrue(ri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("c")));
+ // Fully contained single-row range
+ assertTrue(ri.containsRange(Bytes.toBytes("c"), Bytes.toBytes("c")));
+ // Range that overlaps end key and hence doesn't fit
+ assertFalse(ri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("g")));
+ // Single row range on end key
+ assertFalse(ri.containsRange(Bytes.toBytes("g"), Bytes.toBytes("g")));
+ // Single row range entirely outside
+ assertFalse(ri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("z")));
+
+ // Degenerate range
+ try {
+ ri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("a"));
+ fail("Invalid range did not throw IAE");
+ } catch (IllegalArgumentException iae) {
+ }
+ }
+
+ @Test
+ public void testLastRegionCompare() {
+ TableDescriptor tableDesc = TableDescriptorBuilder
+ .newBuilder(TableName.valueOf(name.getMethodName())).build();
+ RegionInfo rip = RegionInfoBuilder.newBuilder(tableDesc.getTableName())
+ .setStartKey(Bytes.toBytes("a"))
+ .setEndKey(new byte[0]).build();
+ RegionInfo ric = RegionInfoBuilder.newBuilder(tableDesc.getTableName())
+ .setStartKey(Bytes.toBytes("a"))
+ .setEndKey(Bytes.toBytes("b")).build();
+ assertTrue(RegionInfo.COMPARATOR.compare(rip, ric) > 0);
+ }
+
+ @Test
+ public void testMetaTables() {
+ assertTrue(RegionInfoBuilder.FIRST_META_REGIONINFO.isMetaTable());
+ }
+
+ @Test
+ public void testComparator() {
+ final TableName tableName = TableName.valueOf(name.getMethodName());
+ byte[] empty = new byte[0];
+ RegionInfo older = RegionInfoBuilder.newBuilder(tableName)
+ .setStartKey(empty)
+ .setEndKey(empty)
+ .setSplit(false)
+ .setRegionId(0L).build();
+ RegionInfo newer = RegionInfoBuilder.newBuilder(tableName)
+ .setStartKey(empty)
+ .setEndKey(empty)
+ .setSplit(false)
+ .setRegionId(1L).build();
+ assertTrue(RegionInfo.COMPARATOR.compare(older, newer) < 0);
+ assertTrue(RegionInfo.COMPARATOR.compare(newer, older) > 0);
+ assertTrue(RegionInfo.COMPARATOR.compare(older, older) == 0);
+ assertTrue(RegionInfo.COMPARATOR.compare(newer, newer) == 0);
+ }
+
+ @Test
+ public void testRegionNameForRegionReplicas() throws Exception {
+ String tableName = name.getMethodName();
+ final TableName tn = TableName.valueOf(tableName);
+ String startKey = "startkey";
+ final byte[] sk = Bytes.toBytes(startKey);
+ String id = "id";
+
+ // assert with only the region name without encoding
+
+ // primary, replicaId = 0
+ byte [] name = RegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0, false);
+ String nameStr = Bytes.toString(name);
+ assertEquals(tableName + "," + startKey + "," + id, nameStr);
+
+ // replicaId = 1
+ name = RegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 1, false);
+ nameStr = Bytes.toString(name);
+ assertEquals(tableName + "," + startKey + "," + id + "_" +
+ String.format(RegionInfo.REPLICA_ID_FORMAT, 1), nameStr);
+
+ // replicaId = max
+ name = RegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0xFFFF, false);
+ nameStr = Bytes.toString(name);
+ assertEquals(tableName + "," + startKey + "," + id + "_" +
+ String.format(RegionInfo.REPLICA_ID_FORMAT, 0xFFFF), nameStr);
+ }
+
+ @Test
+ public void testParseName() throws IOException {
+ final TableName tableName = TableName.valueOf(name.getMethodName());
+ byte[] startKey = Bytes.toBytes("startKey");
+ long regionId = System.currentTimeMillis();
+ int replicaId = 42;
+
+ // test without replicaId
+ byte[] regionName = RegionInfo.createRegionName(tableName, startKey, regionId, false);
+
+ byte[][] fields = RegionInfo.parseRegionName(regionName);
+ assertArrayEquals(Bytes.toString(fields[0]),tableName.getName(), fields[0]);
+ assertArrayEquals(Bytes.toString(fields[1]),startKey, fields[1]);
+ assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)),fields[2]);
+ assertEquals(3, fields.length);
+
+ // test with replicaId
+ regionName = RegionInfo.createRegionName(tableName, startKey, regionId,
+ replicaId, false);
+
+ fields = RegionInfo.parseRegionName(regionName);
+ assertArrayEquals(Bytes.toString(fields[0]),tableName.getName(), fields[0]);
+ assertArrayEquals(Bytes.toString(fields[1]),startKey, fields[1]);
+ assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)),fields[2]);
+ assertArrayEquals(Bytes.toString(fields[3]), Bytes.toBytes(
+ String.format(RegionInfo.REPLICA_ID_FORMAT, replicaId)), fields[3]);
+ }
+
+ @Test
+ public void testConvert() {
+ final TableName tableName = TableName.valueOf("ns1:" + name.getMethodName());
+ byte[] startKey = Bytes.toBytes("startKey");
+ byte[] endKey = Bytes.toBytes("endKey");
+ boolean split = false;
+ long regionId = System.currentTimeMillis();
+ int replicaId = 42;
+
+
+ RegionInfo ri = RegionInfoBuilder.newBuilder(tableName)
+ .setStartKey(startKey)
+ .setEndKey(endKey)
+ .setSplit(split)
+ .setRegionId(regionId)
+ .setReplicaId(replicaId).build();
+
+ // convert two times, compare
+ RegionInfo convertedRi = ProtobufUtil.toRegionInfo(ProtobufUtil.toProtoRegionInfo(ri));
+
+ assertEquals(ri, convertedRi);
+
+ // test convert RegionInfo without replicaId
+ HBaseProtos.RegionInfo info = HBaseProtos.RegionInfo.newBuilder()
+ .setTableName(HBaseProtos.TableName.newBuilder()
+ .setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier()))
+ .setNamespace(UnsafeByteOperations.unsafeWrap(tableName.getNamespace()))
+ .build())
+ .setStartKey(UnsafeByteOperations.unsafeWrap(startKey))
+ .setEndKey(UnsafeByteOperations.unsafeWrap(endKey))
+ .setSplit(split)
+ .setRegionId(regionId)
+ .build();
+
+ convertedRi = ProtobufUtil.toRegionInfo(info);
+ RegionInfo expectedRi = RegionInfoBuilder.newBuilder(tableName)
+ .setStartKey(startKey)
+ .setEndKey(endKey)
+ .setSplit(split)
+ .setRegionId(regionId)
+ .setReplicaId(0).build();
+
+ assertEquals(expectedRi, convertedRi);
+ }
+
+ // Duplicated method in TestRegionInfoDisplay too.
+ private HRegionInfo convert(RegionInfo ri) {
+ HRegionInfo hri = new HRegionInfo(
+ ri.getTable(), ri.getStartKey(), ri.getEndKey(), ri.isSplit(), ri.getRegionId());
+ hri.setOffline(ri.isOffline());
+ return hri;
+ }
+}
\ No newline at end of file