2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
.client
;
19 import java
.util
.Arrays
;
20 import org
.apache
.hadoop
.hbase
.CellComparator
;
21 import org
.apache
.hadoop
.hbase
.CellComparatorImpl
;
22 import org
.apache
.hadoop
.hbase
.HConstants
;
23 import org
.apache
.hadoop
.hbase
.TableName
;
24 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
25 import org
.apache
.yetus
.audience
.InterfaceAudience
;
26 import org
.slf4j
.Logger
;
27 import org
.slf4j
.LoggerFactory
;
30 * An implementation of RegionInfo that adds mutable methods so can build a RegionInfo instance.
31 * Package private. Use {@link RegionInfoBuilder} creating instances of {@link RegionInfo}s.
33 @InterfaceAudience.Private
34 class MutableRegionInfo
implements RegionInfo
{
35 private static final Logger LOG
= LoggerFactory
.getLogger(MutableRegionInfo
.class);
36 private static final int MAX_REPLICA_ID
= 0xFFFF;
39 * The new format for a region name contains its encodedName at the end.
40 * The encoded name also serves as the directory name for the region
43 * New region name format:
44 * <tablename>,,<startkey>,<regionIdTimestamp>.<encodedName>.
46 * <encodedName> is a hex version of the MD5 hash of
47 * <tablename>,<startkey>,<regionIdTimestamp>
49 * The old region name format:
50 * <tablename>,<startkey>,<regionIdTimestamp>
51 * For region names in the old format, the encoded name is a 32-bit
52 * JenkinsHash integer value (in its decimal notation, string form).
56 * The first hbase:meta region, and regions created by an older
57 * version of HBase (0.20 or prior) will continue to use the
58 * old region name format.
61 // This flag is in the parent of a split while the parent is still referenced by daughter
62 // regions. We USED to set this flag when we disabled a table but now table state is kept up in
63 // zookeeper as of 0.90.0 HBase. And now in DisableTableProcedure, finally we will create bunch
64 // of UnassignProcedures and at the last of the procedure we will set the region state to
65 // CLOSED, and will not change the offLine flag.
66 private boolean offLine
;
67 private boolean split
;
68 private final long regionId
;
69 private final int replicaId
;
70 private final byte[] regionName
;
71 private final byte[] startKey
;
72 private final byte[] endKey
;
73 private final int hashCode
;
74 private final String encodedName
;
75 private final byte[] encodedNameAsBytes
;
76 private final TableName tableName
;
78 private static int generateHashCode(final TableName tableName
, final byte[] startKey
,
79 final byte[] endKey
, final long regionId
,
80 final int replicaId
, boolean offLine
, byte[] regionName
) {
81 int result
= Arrays
.hashCode(regionName
);
82 result
= (int) (result ^ regionId
);
83 result ^
= Arrays
.hashCode(checkStartKey(startKey
));
84 result ^
= Arrays
.hashCode(checkEndKey(endKey
));
85 result ^
= Boolean
.valueOf(offLine
).hashCode();
86 result ^
= Arrays
.hashCode(tableName
.getName());
91 private static byte[] checkStartKey(byte[] startKey
) {
92 return startKey
== null? HConstants
.EMPTY_START_ROW
: startKey
;
95 private static byte[] checkEndKey(byte[] endKey
) {
96 return endKey
== null? HConstants
.EMPTY_END_ROW
: endKey
;
99 private static TableName
checkTableName(TableName tableName
) {
100 if (tableName
== null) {
101 throw new IllegalArgumentException("TableName cannot be null");
106 private static int checkReplicaId(int regionId
) {
107 if (regionId
> MAX_REPLICA_ID
) {
108 throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID
);
114 * Package private constructor used constructing MutableRegionInfo for the first meta regions
116 MutableRegionInfo(long regionId
, TableName tableName
, int replicaId
) {
117 this(tableName
, HConstants
.EMPTY_START_ROW
, HConstants
.EMPTY_END_ROW
, false, regionId
,
121 MutableRegionInfo(final TableName tableName
, final byte[] startKey
, final byte[] endKey
,
122 final boolean split
, final long regionId
, final int replicaId
, boolean offLine
) {
123 this.tableName
= checkTableName(tableName
);
124 this.startKey
= checkStartKey(startKey
);
125 this.endKey
= checkEndKey(endKey
);
127 this.regionId
= regionId
;
128 this.replicaId
= checkReplicaId(replicaId
);
129 this.offLine
= offLine
;
130 this.regionName
= RegionInfo
.createRegionName(this.tableName
, this.startKey
, this.regionId
,
131 this.replicaId
, !this.tableName
.equals(TableName
.META_TABLE_NAME
));
132 this.encodedName
= RegionInfo
.encodeRegionName(this.regionName
);
133 this.hashCode
= generateHashCode(this.tableName
, this.startKey
, this.endKey
, this.regionId
,
134 this.replicaId
, this.offLine
, this.regionName
);
135 this.encodedNameAsBytes
= Bytes
.toBytes(this.encodedName
);
139 * @return Return a short, printable name for this region (usually encoded name) for us logging.
142 public String
getShortNameToLog() {
143 return RegionInfo
.prettyPrint(this.getEncodedName());
146 /** @return the regionId */
148 public long getRegionId(){
154 * @return the regionName as an array of bytes.
155 * @see #getRegionNameAsString()
158 public byte[] getRegionName() {
163 * @return Region name as a String for use in logging, etc.
166 public String
getRegionNameAsString() {
167 return RegionInfo
.getRegionNameAsString(this, this.regionName
);
170 /** @return the encoded region name */
172 public String
getEncodedName() {
173 return this.encodedName
;
177 public byte[] getEncodedNameAsBytes() {
178 return this.encodedNameAsBytes
;
181 /** @return the startKey */
183 public byte[] getStartKey() {
187 /** @return the endKey */
189 public byte[] getEndKey() {
194 * Get current table name of the region
198 public TableName
getTable() {
199 return this.tableName
;
203 * Returns true if the given inclusive range of rows is fully contained
204 * by this region. For example, if the region is foo,a,g and this is
205 * passed ["b","c"] or ["a","c"] it will return true, but if this is passed
206 * ["b","z"] it will return false.
207 * @throws IllegalArgumentException if the range passed is invalid (ie. end < start)
210 public boolean containsRange(byte[] rangeStartKey
, byte[] rangeEndKey
) {
211 CellComparator cellComparator
= CellComparatorImpl
.getCellComparator(tableName
);
212 if (cellComparator
.compareRows(rangeStartKey
, rangeEndKey
) > 0) {
213 throw new IllegalArgumentException(
214 "Invalid range: " + Bytes
.toStringBinary(rangeStartKey
) +
215 " > " + Bytes
.toStringBinary(rangeEndKey
));
218 boolean firstKeyInRange
= cellComparator
.compareRows(rangeStartKey
, startKey
) >= 0;
219 boolean lastKeyInRange
=
220 cellComparator
.compareRows(rangeEndKey
, endKey
) < 0 ||
221 Bytes
.equals(endKey
, HConstants
.EMPTY_BYTE_ARRAY
);
222 return firstKeyInRange
&& lastKeyInRange
;
226 * Return true if the given row falls in this region.
229 public boolean containsRow(byte[] row
) {
230 CellComparator cellComparator
= CellComparatorImpl
.getCellComparator(tableName
);
231 return cellComparator
.compareRows(row
, startKey
) >= 0 &&
232 (cellComparator
.compareRows(row
, endKey
) < 0 ||
233 Bytes
.equals(endKey
, HConstants
.EMPTY_BYTE_ARRAY
));
236 /** @return true if this region is a meta region */
238 public boolean isMetaRegion() {
239 return tableName
.equals(TableName
.META_TABLE_NAME
);
243 * @return True if has been split and has daughters.
246 public boolean isSplit() {
251 * @param split set split status
252 * @return MutableRegionInfo
254 public MutableRegionInfo
setSplit(boolean split
) {
260 * @return True if this region is offline.
261 * @deprecated since 3.0.0 and will be removed in 4.0.0
262 * @see <a href="https://issues.apache.org/jira/browse/HBASE-25210">HBASE-25210</a>
266 public boolean isOffline() {
271 * The parent of a region split is offline while split daughters hold
272 * references to the parent. Offlined regions are closed.
273 * @param offLine Set online/offline status.
274 * @return MutableRegionInfo
276 public MutableRegionInfo
setOffline(boolean offLine
) {
277 this.offLine
= offLine
;
282 * @return True if this is a split parent region.
283 * @deprecated since 3.0.0 and will be removed in 4.0.0, Use {@link #isSplit()} instead.
284 * @see <a href="https://issues.apache.org/jira/browse/HBASE-25210">HBASE-25210</a>
288 public boolean isSplitParent() {
293 LOG
.warn("Region is split but NOT offline: " + getRegionNameAsString());
299 * Returns the region replica id
300 * @return returns region replica id
303 public int getReplicaId() {
308 * @see Object#toString()
311 public String
toString() {
312 return "{ENCODED => " + getEncodedName() + ", " +
313 HConstants
.NAME
+ " => '" + Bytes
.toStringBinary(this.regionName
)
314 + "', STARTKEY => '" +
315 Bytes
.toStringBinary(this.startKey
) + "', ENDKEY => '" +
316 Bytes
.toStringBinary(this.endKey
) + "'" +
317 (isOffline()?
", OFFLINE => true": "") +
318 (isSplit()?
", SPLIT => true": "") +
319 ((replicaId
> 0)?
", REPLICA_ID => " + replicaId
: "") + "}";
323 * @see Object#equals(Object)
326 public boolean equals(Object o
) {
333 if (!(o
instanceof RegionInfo
)) {
336 return compareTo((RegionInfo
)o
) == 0;
340 * @see Object#hashCode()
343 public int hashCode() {
344 return this.hashCode
;