HBASE-24918 Make RegionInfo#UNDEFINED IA.Private (#2289)
Mark RegionInfo#UNDEFINED IA.Private and deprecated; it is for internal use only and likely to be removed in hbase4. Move MutableRegionInfo out of RegionInfoBuilder and have it as a stanadlone task; a nice-to-have. Signed-off-by: Viraj Jasani <vjasani@apache.org> Signed-off-by: Bharath Vissapragada <bharathv@apache.org> Signed-off-by: Duo Zhang <zhangduo@apache.org>
This commit is contained in:
parent
5c298790f2
commit
5af9852397
|
@ -0,0 +1,336 @@
|
||||||
|
/*
|
||||||
|
* 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 org.apache.hadoop.hbase.HConstants;
|
||||||
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of RegionInfo that adds mutable methods so can build a RegionInfo instance.
|
||||||
|
* Package private. Use {@link RegionInfoBuilder} creating instances of {@link RegionInfo}s.
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
class MutableRegionInfo implements RegionInfo {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(MutableRegionInfo.class);
|
||||||
|
private static final int MAX_REPLICA_ID = 0xFFFF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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. And now in DisableTableProcedure, finally we will create bunch
|
||||||
|
// of UnassignProcedures and at the last of the procedure we will set the region state to
|
||||||
|
// CLOSED, and will not change the offLine flag.
|
||||||
|
private boolean offLine;
|
||||||
|
private boolean split;
|
||||||
|
private final long regionId;
|
||||||
|
private final int replicaId;
|
||||||
|
private final byte[] regionName;
|
||||||
|
private final byte[] startKey;
|
||||||
|
private final byte[] endKey;
|
||||||
|
private final int hashCode;
|
||||||
|
private final String encodedName;
|
||||||
|
private final byte[] encodedNameAsBytes;
|
||||||
|
private final TableName tableName;
|
||||||
|
|
||||||
|
private static int generateHashCode(final TableName tableName, final byte[] startKey,
|
||||||
|
final byte[] endKey, final long regionId,
|
||||||
|
final int replicaId, boolean offLine, byte[] regionName) {
|
||||||
|
int result = Arrays.hashCode(regionName);
|
||||||
|
result = (int) (result ^ regionId);
|
||||||
|
result ^= Arrays.hashCode(checkStartKey(startKey));
|
||||||
|
result ^= Arrays.hashCode(checkEndKey(endKey));
|
||||||
|
result ^= Boolean.valueOf(offLine).hashCode();
|
||||||
|
result ^= Arrays.hashCode(tableName.getName());
|
||||||
|
result ^= replicaId;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] checkStartKey(byte[] startKey) {
|
||||||
|
return startKey == null? HConstants.EMPTY_START_ROW: startKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] checkEndKey(byte[] endKey) {
|
||||||
|
return endKey == null? HConstants.EMPTY_END_ROW: endKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TableName checkTableName(TableName tableName) {
|
||||||
|
if (tableName == null) {
|
||||||
|
throw new IllegalArgumentException("TableName cannot be null");
|
||||||
|
}
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int checkReplicaId(int regionId) {
|
||||||
|
if (regionId > MAX_REPLICA_ID) {
|
||||||
|
throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID);
|
||||||
|
}
|
||||||
|
return regionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package private constructor used constructing MutableRegionInfo for the first meta regions
|
||||||
|
*/
|
||||||
|
MutableRegionInfo(long regionId, TableName tableName, int replicaId) {
|
||||||
|
this(tableName, HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId,
|
||||||
|
replicaId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
|
||||||
|
final boolean split, final long regionId, final int replicaId, boolean offLine) {
|
||||||
|
this.tableName = checkTableName(tableName);
|
||||||
|
this.startKey = checkStartKey(startKey);
|
||||||
|
this.endKey = checkEndKey(endKey);
|
||||||
|
this.split = split;
|
||||||
|
this.regionId = regionId;
|
||||||
|
this.replicaId = checkReplicaId(replicaId);
|
||||||
|
this.offLine = offLine;
|
||||||
|
this.regionName = RegionInfo.createRegionName(this.tableName, this.startKey, this.regionId,
|
||||||
|
this.replicaId, !this.tableName.equals(TableName.META_TABLE_NAME));
|
||||||
|
this.encodedName = RegionInfo.encodeRegionName(this.regionName);
|
||||||
|
this.hashCode = generateHashCode(this.tableName, this.startKey, this.endKey, this.regionId,
|
||||||
|
this.replicaId, this.offLine, this.regionName);
|
||||||
|
this.encodedNameAsBytes = Bytes.toBytes(this.encodedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the regionName as an array of bytes.
|
||||||
|
* @see #getRegionNameAsString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] getRegionName() {
|
||||||
|
return regionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Region name as a String for use in logging, etc.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getRegionNameAsString() {
|
||||||
|
return RegionInfo.getRegionNameAsString(this, this.regionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the encoded region name */
|
||||||
|
@Override
|
||||||
|
public String getEncodedName() {
|
||||||
|
return this.encodedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getEncodedNameAsBytes() {
|
||||||
|
return this.encodedNameAsBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the startKey */
|
||||||
|
@Override
|
||||||
|
public byte[] getStartKey() {
|
||||||
|
return startKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the endKey */
|
||||||
|
@Override
|
||||||
|
public byte[] getEndKey() {
|
||||||
|
return endKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current table name of the region
|
||||||
|
* @return TableName
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TableName getTable() {
|
||||||
|
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 a meta region */
|
||||||
|
@Override
|
||||||
|
public boolean isMetaRegion() {
|
||||||
|
return tableName.equals(TableName.META_TABLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see 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 : "") + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Object#equals(Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(o instanceof RegionInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return compareTo((RegionInfo)o) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Object#hashCode()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.hashCode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,6 @@
|
||||||
package org.apache.hadoop.hbase.client;
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.CheckForNull;
|
import edu.umd.cs.findbugs.annotations.CheckForNull;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -27,7 +26,6 @@ import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||||
|
@ -38,7 +36,6 @@ import org.apache.hadoop.hbase.util.JenkinsHash;
|
||||||
import org.apache.hadoop.hbase.util.MD5Hash;
|
import org.apache.hadoop.hbase.util.MD5Hash;
|
||||||
import org.apache.hadoop.io.DataInputBuffer;
|
import org.apache.hadoop.io.DataInputBuffer;
|
||||||
import org.apache.yetus.audience.InterfaceAudience;
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
|
||||||
|
|
||||||
|
@ -69,7 +66,13 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Public
|
||||||
public interface RegionInfo extends Comparable<RegionInfo> {
|
public interface RegionInfo extends Comparable<RegionInfo> {
|
||||||
|
/**
|
||||||
|
* @deprecated since 2.3.2/3.0.0; to be removed in 4.0.0 with no replacement (for internal use).
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@InterfaceAudience.Private
|
||||||
RegionInfo UNDEFINED = RegionInfoBuilder.newBuilder(TableName.valueOf("__UNDEFINED__")).build();
|
RegionInfo UNDEFINED = RegionInfoBuilder.newBuilder(TableName.valueOf("__UNDEFINED__")).build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Separator used to demarcate the encodedName in a region name
|
* Separator used to demarcate the encodedName in a region name
|
||||||
* in the new format. See description on new format above.
|
* in the new format. See description on new format above.
|
||||||
|
@ -585,8 +588,8 @@ public interface RegionInfo extends Comparable<RegionInfo> {
|
||||||
* @return the MOB {@link RegionInfo}.
|
* @return the MOB {@link RegionInfo}.
|
||||||
*/
|
*/
|
||||||
static RegionInfo createMobRegionInfo(TableName tableName) {
|
static RegionInfo createMobRegionInfo(TableName tableName) {
|
||||||
return RegionInfoBuilder.newBuilder(tableName)
|
return RegionInfoBuilder.newBuilder(tableName).setStartKey(Bytes.toBytes(".mob")).
|
||||||
.setStartKey(Bytes.toBytes(".mob")).setRegionId(0).build();
|
setRegionId(0).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,10 +17,8 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hbase.client;
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
|
||||||
import org.apache.yetus.audience.InterfaceAudience;
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -32,8 +30,6 @@ public class RegionInfoBuilder {
|
||||||
/** A non-capture group so that this can be embedded. */
|
/** A non-capture group so that this can be embedded. */
|
||||||
public static final String ENCODED_REGION_NAME_REGEX = "(?:[a-f0-9]+)";
|
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.
|
//TODO: Move NO_HASH to HStoreFile which is really the only place it is used.
|
||||||
public static final String NO_HASH = null;
|
public static final String NO_HASH = null;
|
||||||
|
|
||||||
|
@ -114,313 +110,4 @@ public class RegionInfoBuilder {
|
||||||
regionId, replicaId, offLine);
|
regionId, replicaId, offLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of RegionInfo that adds mutable methods so can build a RegionInfo instance.
|
|
||||||
*/
|
|
||||||
@InterfaceAudience.Private
|
|
||||||
static class MutableRegionInfo implements 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. And now in DisableTableProcedure, finally we will create bunch
|
|
||||||
// of UnassignProcedures and at the last of the procedure we will set the region state to
|
|
||||||
// CLOSED, and will not change the offLine flag.
|
|
||||||
private boolean offLine = false;
|
|
||||||
private boolean split = false;
|
|
||||||
private final long regionId;
|
|
||||||
private final int replicaId;
|
|
||||||
private final byte[] regionName;
|
|
||||||
private final byte[] startKey;
|
|
||||||
private final byte[] endKey;
|
|
||||||
private final int hashCode;
|
|
||||||
private final String encodedName;
|
|
||||||
private final byte[] encodedNameAsBytes;
|
|
||||||
private final TableName tableName;
|
|
||||||
|
|
||||||
private static int generateHashCode(final TableName tableName, final byte[] startKey,
|
|
||||||
final byte[] endKey, final long regionId,
|
|
||||||
final int replicaId, boolean offLine, byte[] regionName) {
|
|
||||||
int result = Arrays.hashCode(regionName);
|
|
||||||
result = (int) (result ^ regionId);
|
|
||||||
result ^= Arrays.hashCode(checkStartKey(startKey));
|
|
||||||
result ^= Arrays.hashCode(checkEndKey(endKey));
|
|
||||||
result ^= Boolean.valueOf(offLine).hashCode();
|
|
||||||
result ^= Arrays.hashCode(tableName.getName());
|
|
||||||
result ^= replicaId;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] checkStartKey(byte[] startKey) {
|
|
||||||
return startKey == null? HConstants.EMPTY_START_ROW: startKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] checkEndKey(byte[] endKey) {
|
|
||||||
return endKey == null? HConstants.EMPTY_END_ROW: endKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TableName checkTableName(TableName tableName) {
|
|
||||||
if (tableName == null) {
|
|
||||||
throw new IllegalArgumentException("TableName cannot be null");
|
|
||||||
}
|
|
||||||
return tableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int checkReplicaId(int regionId) {
|
|
||||||
if (regionId > MAX_REPLICA_ID) {
|
|
||||||
throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID);
|
|
||||||
}
|
|
||||||
return regionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor used constructing MutableRegionInfo for the
|
|
||||||
* first meta regions
|
|
||||||
*/
|
|
||||||
private MutableRegionInfo(long regionId, TableName tableName, int replicaId) {
|
|
||||||
this(tableName, HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId,
|
|
||||||
replicaId, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
MutableRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
|
|
||||||
final boolean split, final long regionId, final int replicaId, boolean offLine) {
|
|
||||||
this.tableName = checkTableName(tableName);
|
|
||||||
this.startKey = checkStartKey(startKey);
|
|
||||||
this.endKey = checkEndKey(endKey);
|
|
||||||
this.split = split;
|
|
||||||
this.regionId = regionId;
|
|
||||||
this.replicaId = checkReplicaId(replicaId);
|
|
||||||
this.offLine = offLine;
|
|
||||||
this.regionName = RegionInfo.createRegionName(this.tableName, this.startKey, this.regionId,
|
|
||||||
this.replicaId, !this.tableName.equals(TableName.META_TABLE_NAME));
|
|
||||||
this.encodedName = RegionInfo.encodeRegionName(this.regionName);
|
|
||||||
this.hashCode = generateHashCode(this.tableName, this.startKey, this.endKey, this.regionId,
|
|
||||||
this.replicaId, this.offLine, this.regionName);
|
|
||||||
this.encodedNameAsBytes = Bytes.toBytes(this.encodedName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the regionName as an array of bytes.
|
|
||||||
* @see #getRegionNameAsString()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public byte[] getRegionName() {
|
|
||||||
return regionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Region name as a String for use in logging, etc.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getRegionNameAsString() {
|
|
||||||
return RegionInfo.getRegionNameAsString(this, this.regionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the encoded region name */
|
|
||||||
@Override
|
|
||||||
public String getEncodedName() {
|
|
||||||
return this.encodedName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getEncodedNameAsBytes() {
|
|
||||||
return this.encodedNameAsBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the startKey */
|
|
||||||
@Override
|
|
||||||
public byte[] getStartKey() {
|
|
||||||
return startKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the endKey */
|
|
||||||
@Override
|
|
||||||
public byte[] getEndKey() {
|
|
||||||
return endKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current table name of the region
|
|
||||||
* @return TableName
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public TableName getTable() {
|
|
||||||
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 a meta region */
|
|
||||||
@Override
|
|
||||||
public boolean isMetaRegion() {
|
|
||||||
return tableName.equals(FIRST_META_REGIONINFO.getTable());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 compareTo((RegionInfo)o) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see java.lang.Object#hashCode()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue