-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]> Signed-off-by: Duo Zhang <[email protected]>
- Loading branch information
1 parent
d2b530a
commit 50838ba
Showing
3 changed files
with
344 additions
and
318 deletions.
There are no files selected for viewing
336 changes: 336 additions & 0 deletions
336
hbase-client/src/main/java/org/apache/hadoop/hbase/client/MutableRegionInfo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.