001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import java.io.DataInputStream;
021import java.io.IOException;
022import java.util.ArrayList;
023import java.util.Arrays;
024import java.util.List;
025import java.util.stream.Collectors;
026import org.apache.hadoop.conf.Configuration;
027import org.apache.hadoop.hbase.KeyValue.KVComparator;
028import org.apache.hadoop.hbase.client.RegionInfo;
029import org.apache.hadoop.hbase.client.RegionInfoBuilder;
030import org.apache.hadoop.hbase.client.RegionInfoDisplay;
031import org.apache.hadoop.hbase.exceptions.DeserializationException;
032import org.apache.hadoop.hbase.master.RegionState;
033import org.apache.hadoop.hbase.util.Bytes;
034import org.apache.hadoop.io.DataInputBuffer;
035import org.apache.yetus.audience.InterfaceAudience;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038
039import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
040import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
041
042/**
043 * Information about a region. A region is a range of keys in the whole keyspace of a table, an
044 * identifier (a timestamp) for differentiating between subset ranges (after region split) and a
045 * replicaId for differentiating the instance for the same range and some status information about
046 * the region. The region has a unique name which consists of the following fields:
047 * <ul>
048 * <li>tableName : The name of the table</li>
049 * <li>startKey : The startKey for the region.</li>
050 * <li>regionId : A timestamp when the region is created.</li>
051 * <li>replicaId : An id starting from 0 to differentiate replicas of the same region range but
052 * hosted in separated servers. The same region range can be hosted in multiple locations.</li>
053 * <li>encodedName : An MD5 encoded string for the region name.</li>
054 * </ul>
055 * <br>
056 * Other than the fields in the region name, region info contains:
057 * <ul>
058 * <li>endKey : the endKey for the region (exclusive)</li>
059 * <li>split : Whether the region is split</li>
060 * <li>offline : Whether the region is offline</li>
061 * </ul>
062 * In 0.98 or before, a list of table's regions would fully cover the total keyspace, and at any
063 * point in time, a row key always belongs to a single region, which is hosted in a single server.
064 * In 0.99+, a region can have multiple instances (called replicas), and thus a range (or row) can
065 * correspond to multiple HRegionInfo's. These HRI's share the same fields however except the
066 * replicaId field. If the replicaId is not set, it defaults to 0, which is compatible with the
067 * previous behavior of a range corresponding to 1 region.
068 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. use
069 *             {@link RegionInfoBuilder} to build {@link RegionInfo}.
070 */
071@Deprecated
072@InterfaceAudience.Public
073public class HRegionInfo implements RegionInfo {
074  private static final Logger LOG = LoggerFactory.getLogger(HRegionInfo.class);
075
076  /**
077   * The new format for a region name contains its encodedName at the end. The encoded name also
078   * serves as the directory name for the region in the filesystem. New region name format:
079   * &lt;tablename>,,&lt;startkey>,&lt;regionIdTimestamp>.&lt;encodedName>. where, &lt;encodedName>
080   * is a hex version of the MD5 hash of &lt;tablename>,&lt;startkey>,&lt;regionIdTimestamp> The old
081   * region name format: &lt;tablename>,&lt;startkey>,&lt;regionIdTimestamp> For region names in the
082   * old format, the encoded name is a 32-bit JenkinsHash integer value (in its decimal notation,
083   * string form).
084   * <p>
085   * **NOTE** The first hbase:meta region, and regions created by an older version of HBase (0.20 or
086   * prior) will continue to use the old region name format.
087   */
088
089  /** A non-capture group so that this can be embedded. */
090  public static final String ENCODED_REGION_NAME_REGEX =
091    RegionInfoBuilder.ENCODED_REGION_NAME_REGEX;
092
093  private static final int MAX_REPLICA_ID = 0xFFFF;
094
095  /**
096   * @return the encodedName
097   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
098   *             {@link org.apache.hadoop.hbase.client.RegionInfo#encodeRegionName(byte[])}.
099   */
100  @Deprecated
101  public static String encodeRegionName(final byte[] regionName) {
102    return RegionInfo.encodeRegionName(regionName);
103  }
104
105  /**
106   * Returns Return a short, printable name for this region (usually encoded name) for us logging.
107   */
108  @Override
109  public String getShortNameToLog() {
110    return prettyPrint(this.getEncodedName());
111  }
112
113  /**
114   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
115   *             {@link org.apache.hadoop.hbase.client.RegionInfo#getShortNameToLog(RegionInfo...)}.
116   */
117  @Deprecated
118  public static String getShortNameToLog(HRegionInfo... hris) {
119    return RegionInfo.getShortNameToLog(Arrays.asList(hris));
120  }
121
122  /**
123   * @return Return a String of short, printable names for <code>hris</code> (usually encoded name)
124   *         for us logging.
125   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
126   *             {@link org.apache.hadoop.hbase.client.RegionInfo#getShortNameToLog(List)})}.
127   */
128  @Deprecated
129  public static String getShortNameToLog(final List<HRegionInfo> hris) {
130    return RegionInfo.getShortNameToLog(hris.stream().collect(Collectors.toList()));
131  }
132
133  /**
134   * Use logging.
135   * @param encodedRegionName The encoded regionname.
136   * @return <code>hbase:meta</code> if passed <code>1028785192</code> else returns
137   *         <code>encodedRegionName</code>
138   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
139   *             {@link RegionInfo#prettyPrint(String)}.
140   */
141  @Deprecated
142  @InterfaceAudience.Private
143  public static String prettyPrint(final String encodedRegionName) {
144    return RegionInfo.prettyPrint(encodedRegionName);
145  }
146
147  private byte[] endKey = HConstants.EMPTY_BYTE_ARRAY;
148  // This flag is in the parent of a split while the parent is still referenced by daughter regions.
149  // We USED to set this flag when we disabled a table but now table state is kept up in zookeeper
150  // as of 0.90.0 HBase. And now in DisableTableProcedure, finally we will create bunch of
151  // UnassignProcedures and at the last of the procedure we will set the region state to CLOSED, and
152  // will not change the offLine flag.
153  private boolean offLine = false;
154  private long regionId = -1;
155  private transient byte[] regionName = HConstants.EMPTY_BYTE_ARRAY;
156  private boolean split = false;
157  private byte[] startKey = HConstants.EMPTY_BYTE_ARRAY;
158  private int hashCode = -1;
159  // TODO: Move NO_HASH to HStoreFile which is really the only place it is used.
160  public static final String NO_HASH = null;
161  private String encodedName = null;
162  private byte[] encodedNameAsBytes = null;
163  private int replicaId = DEFAULT_REPLICA_ID;
164
165  // Current TableName
166  private TableName tableName = null;
167
168  // Duplicated over in RegionInfoDisplay
169  final static String DISPLAY_KEYS_KEY = RegionInfoDisplay.DISPLAY_KEYS_KEY;
170  public final static byte[] HIDDEN_END_KEY = RegionInfoDisplay.HIDDEN_END_KEY;
171  public final static byte[] HIDDEN_START_KEY = RegionInfoDisplay.HIDDEN_START_KEY;
172
173  /** HRegionInfo for first meta region */
174  // TODO: How come Meta regions still do not have encoded region names? Fix.
175  public static final HRegionInfo FIRST_META_REGIONINFO =
176    new HRegionInfo(1L, TableName.META_TABLE_NAME);
177
178  private void setHashCode() {
179    int result = Arrays.hashCode(this.regionName);
180    result = (int) (result ^ this.regionId);
181    result ^= Arrays.hashCode(this.startKey);
182    result ^= Arrays.hashCode(this.endKey);
183    result ^= Boolean.valueOf(this.offLine).hashCode();
184    result ^= Arrays.hashCode(this.tableName.getName());
185    result ^= this.replicaId;
186    this.hashCode = result;
187  }
188
189  /**
190   * Private constructor used constructing HRegionInfo for the first meta regions
191   */
192  private HRegionInfo(long regionId, TableName tableName) {
193    this(regionId, tableName, DEFAULT_REPLICA_ID);
194  }
195
196  public HRegionInfo(long regionId, TableName tableName, int replicaId) {
197    super();
198    this.regionId = regionId;
199    this.tableName = tableName;
200    this.replicaId = replicaId;
201    // Note: First Meta region replicas names are in old format
202    this.regionName = createRegionName(tableName, null, regionId, replicaId, false);
203    setHashCode();
204  }
205
206  public HRegionInfo(final TableName tableName) {
207    this(tableName, null, null);
208  }
209
210  /**
211   * Construct HRegionInfo with explicit parameters
212   * @param tableName the table name
213   * @param startKey  first key in region
214   * @param endKey    end of key range
215   */
216  public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey)
217    throws IllegalArgumentException {
218    this(tableName, startKey, endKey, false);
219  }
220
221  /**
222   * Construct HRegionInfo with explicit parameters
223   * @param tableName the table descriptor
224   * @param startKey  first key in region
225   * @param endKey    end of key range
226   * @param split     true if this region has split and we have daughter regions regions that may or
227   *                  may not hold references to this region.
228   */
229  public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
230    final boolean split) throws IllegalArgumentException {
231    this(tableName, startKey, endKey, split, System.currentTimeMillis());
232  }
233
234  /**
235   * Construct HRegionInfo with explicit parameters
236   * @param tableName the table descriptor
237   * @param startKey  first key in region
238   * @param endKey    end of key range
239   * @param split     true if this region has split and we have daughter regions regions that may or
240   *                  may not hold references to this region.
241   * @param regionid  Region id to use.
242   */
243  public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
244    final boolean split, final long regionid) throws IllegalArgumentException {
245    this(tableName, startKey, endKey, split, regionid, DEFAULT_REPLICA_ID);
246  }
247
248  /**
249   * Construct HRegionInfo with explicit parameters
250   * @param tableName the table descriptor
251   * @param startKey  first key in region
252   * @param endKey    end of key range
253   * @param split     true if this region has split and we have daughter regions regions that may or
254   *                  may not hold references to this region.
255   * @param regionid  Region id to use.
256   * @param replicaId the replicaId to use
257   */
258  public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
259    final boolean split, final long regionid, final int replicaId) throws IllegalArgumentException {
260    super();
261    if (tableName == null) {
262      throw new IllegalArgumentException("TableName cannot be null");
263    }
264    this.tableName = tableName;
265    this.offLine = false;
266    this.regionId = regionid;
267    this.replicaId = replicaId;
268    if (this.replicaId > MAX_REPLICA_ID) {
269      throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID);
270    }
271
272    this.regionName = createRegionName(this.tableName, startKey, regionId, replicaId, true);
273
274    this.split = split;
275    this.endKey = endKey == null ? HConstants.EMPTY_END_ROW : endKey.clone();
276    this.startKey = startKey == null ? HConstants.EMPTY_START_ROW : startKey.clone();
277    this.tableName = tableName;
278    setHashCode();
279  }
280
281  /**
282   * Costruct a copy of another HRegionInfo
283   */
284  public HRegionInfo(RegionInfo other) {
285    super();
286    this.endKey = other.getEndKey();
287    this.offLine = other.isOffline();
288    this.regionId = other.getRegionId();
289    this.regionName = other.getRegionName();
290    this.split = other.isSplit();
291    this.startKey = other.getStartKey();
292    this.hashCode = other.hashCode();
293    this.encodedName = other.getEncodedName();
294    this.tableName = other.getTable();
295    this.replicaId = other.getReplicaId();
296  }
297
298  public HRegionInfo(HRegionInfo other, int replicaId) {
299    this(other);
300    this.replicaId = replicaId;
301    this.setHashCode();
302  }
303
304  /**
305   * Make a region name of passed parameters.
306   * @param startKey  Can be null
307   * @param regionid  Region id (Usually timestamp from when region was created).
308   * @param newFormat should we create the region name in the new format (such that it contains its
309   *                  encoded name?).
310   * @return Region name made of passed tableName, startKey and id
311   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
312   *             {@link RegionInfo#createRegionName(TableName, byte[], long, boolean)}.
313   */
314  @Deprecated
315  @InterfaceAudience.Private
316  public static byte[] createRegionName(final TableName tableName, final byte[] startKey,
317    final long regionid, boolean newFormat) {
318    return RegionInfo.createRegionName(tableName, startKey, Long.toString(regionid), newFormat);
319  }
320
321  /**
322   * Make a region name of passed parameters.
323   * @param startKey  Can be null
324   * @param id        Region id (Usually timestamp from when region was created).
325   * @param newFormat should we create the region name in the new format (such that it contains its
326   *                  encoded name?).
327   * @return Region name made of passed tableName, startKey and id
328   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
329   *             {@link RegionInfo#createRegionName(TableName, byte[], String, boolean)}.
330   */
331  @Deprecated
332  @InterfaceAudience.Private
333  public static byte[] createRegionName(final TableName tableName, final byte[] startKey,
334    final String id, boolean newFormat) {
335    return RegionInfo.createRegionName(tableName, startKey, Bytes.toBytes(id), newFormat);
336  }
337
338  /**
339   * Make a region name of passed parameters.
340   * @param startKey  Can be null
341   * @param regionid  Region id (Usually timestamp from when region was created).
342   * @param newFormat should we create the region name in the new format (such that it contains its
343   *                  encoded name?).
344   * @return Region name made of passed tableName, startKey, id and replicaId
345   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
346   *             {@link RegionInfo#createRegionName(TableName, byte[], long, int, boolean)}.
347   */
348  @Deprecated
349  @InterfaceAudience.Private
350  public static byte[] createRegionName(final TableName tableName, final byte[] startKey,
351    final long regionid, int replicaId, boolean newFormat) {
352    return RegionInfo.createRegionName(tableName, startKey, Bytes.toBytes(Long.toString(regionid)),
353      replicaId, newFormat);
354  }
355
356  /**
357   * Make a region name of passed parameters.
358   * @param startKey  Can be null
359   * @param id        Region id (Usually timestamp from when region was created).
360   * @param newFormat should we create the region name in the new format (such that it contains its
361   *                  encoded name?).
362   * @return Region name made of passed tableName, startKey and id
363   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
364   *             {@link RegionInfo#createRegionName(TableName, byte[], byte[], boolean)}.
365   */
366  @Deprecated
367  @InterfaceAudience.Private
368  public static byte[] createRegionName(final TableName tableName, final byte[] startKey,
369    final byte[] id, boolean newFormat) {
370    return RegionInfo.createRegionName(tableName, startKey, id, DEFAULT_REPLICA_ID, newFormat);
371  }
372
373  /**
374   * Make a region name of passed parameters.
375   * @param startKey  Can be null
376   * @param id        Region id (Usually timestamp from when region was created).
377   * @param newFormat should we create the region name in the new format
378   * @return Region name made of passed tableName, startKey, id and replicaId
379   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
380   *             {@link RegionInfo#createRegionName(TableName, byte[], byte[], int, boolean)}.
381   */
382  @Deprecated
383  @InterfaceAudience.Private
384  public static byte[] createRegionName(final TableName tableName, final byte[] startKey,
385    final byte[] id, final int replicaId, boolean newFormat) {
386    return RegionInfo.createRegionName(tableName, startKey, id, replicaId, newFormat);
387  }
388
389  /**
390   * Gets the table name from the specified region name.
391   * @param regionName to extract the table name from
392   * @return Table name
393   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
394   *             {@link org.apache.hadoop.hbase.client.RegionInfo#getTable(byte[])}.
395   */
396  @Deprecated
397  public static TableName getTable(final byte[] regionName) {
398    return RegionInfo.getTable(regionName);
399  }
400
401  /**
402   * Gets the start key from the specified region name.
403   * @return Start key.
404   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
405   *             {@link org.apache.hadoop.hbase.client.RegionInfo#getStartKey(byte[])}.
406   */
407  @Deprecated
408  public static byte[] getStartKey(final byte[] regionName) throws IOException {
409    return RegionInfo.getStartKey(regionName);
410  }
411
412  /**
413   * Separate elements of a regionName.
414   * @return Array of byte[] containing tableName, startKey and id
415   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
416   *             {@link RegionInfo#parseRegionName(byte[])}.
417   */
418  @Deprecated
419  @InterfaceAudience.Private
420  public static byte[][] parseRegionName(final byte[] regionName) throws IOException {
421    return RegionInfo.parseRegionName(regionName);
422  }
423
424  /**
425   * @return if region name is encoded.
426   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
427   *             {@link org.apache.hadoop.hbase.client.RegionInfo#isEncodedRegionName(byte[])}.
428   */
429  @Deprecated
430  public static boolean isEncodedRegionName(byte[] regionName) throws IOException {
431    return RegionInfo.isEncodedRegionName(regionName);
432  }
433
434  /** Returns the regionId */
435  @Override
436  public long getRegionId() {
437    return regionId;
438  }
439
440  /**
441   * @return the regionName as an array of bytes.
442   * @see #getRegionNameAsString()
443   */
444  @Override
445  public byte[] getRegionName() {
446    return regionName;
447  }
448
449  /** Returns Region name as a String for use in logging, etc. */
450  @Override
451  public String getRegionNameAsString() {
452    if (RegionInfo.hasEncodedName(this.regionName)) {
453      // new format region names already have their encoded name.
454      return Bytes.toStringBinary(this.regionName);
455    }
456
457    // old format. regionNameStr doesn't have the region name.
458    //
459    //
460    return Bytes.toStringBinary(this.regionName) + "." + this.getEncodedName();
461  }
462
463  /** Returns the encoded region name */
464  @Override
465  public synchronized String getEncodedName() {
466    if (this.encodedName == null) {
467      this.encodedName = RegionInfo.encodeRegionName(this.regionName);
468    }
469    return this.encodedName;
470  }
471
472  @Override
473  public synchronized byte[] getEncodedNameAsBytes() {
474    if (this.encodedNameAsBytes == null) {
475      this.encodedNameAsBytes = Bytes.toBytes(getEncodedName());
476    }
477    return this.encodedNameAsBytes;
478  }
479
480  /** Returns the startKey */
481  @Override
482  public byte[] getStartKey() {
483    return startKey;
484  }
485
486  /** Returns the endKey */
487  @Override
488  public byte[] getEndKey() {
489    return endKey;
490  }
491
492  /**
493   * Get current table name of the region
494   */
495  @Override
496  public TableName getTable() {
497    // This method name should be getTableName but there was already a method getTableName
498    // that returned a byte array. It is unfortunate given everywhere else, getTableName returns
499    // a TableName instance.
500    if (tableName == null || tableName.getName().length == 0) {
501      tableName = getTable(getRegionName());
502    }
503    return this.tableName;
504  }
505
506  /**
507   * Returns true if the given inclusive range of rows is fully contained by this region. For
508   * example, if the region is foo,a,g and this is passed ["b","c"] or ["a","c"] it will return
509   * true, but if this is passed ["b","z"] it will return false.
510   * @throws IllegalArgumentException if the range passed is invalid (ie. end &lt; start)
511   */
512  @Override
513  public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) {
514    if (Bytes.compareTo(rangeStartKey, rangeEndKey) > 0) {
515      throw new IllegalArgumentException("Invalid range: " + Bytes.toStringBinary(rangeStartKey)
516        + " > " + Bytes.toStringBinary(rangeEndKey));
517    }
518
519    boolean firstKeyInRange = Bytes.compareTo(rangeStartKey, startKey) >= 0;
520    boolean lastKeyInRange =
521      Bytes.compareTo(rangeEndKey, endKey) < 0 || Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY);
522    return firstKeyInRange && lastKeyInRange;
523  }
524
525  /** Returns true if the given row falls in this region. */
526  @Override
527  public boolean containsRow(byte[] row) {
528    return Bytes.compareTo(row, startKey) >= 0
529      && (Bytes.compareTo(row, endKey) < 0 || Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY));
530  }
531
532  /** Returns true if this region is from hbase:meta */
533  public boolean isMetaTable() {
534    return isMetaRegion();
535  }
536
537  /** Returns true if this region is a meta region */
538  @Override
539  public boolean isMetaRegion() {
540    return tableName.equals(HRegionInfo.FIRST_META_REGIONINFO.getTable());
541  }
542
543  /** Returns true if this region is from a system table */
544  public boolean isSystemTable() {
545    return tableName.isSystemTable();
546  }
547
548  /** Returns true if has been split and has daughters. */
549  @Override
550  public boolean isSplit() {
551    return this.split;
552  }
553
554  /**
555   * @param split set split status
556   */
557  public void setSplit(boolean split) {
558    this.split = split;
559  }
560
561  /** Returns true if this region is offline. */
562  @Override
563  public boolean isOffline() {
564    return this.offLine;
565  }
566
567  /**
568   * The parent of a region split is offline while split daughters hold references to the parent.
569   * Offlined regions are closed.
570   * @param offLine Set online/offline status.
571   */
572  public void setOffline(boolean offLine) {
573    this.offLine = offLine;
574  }
575
576  /** Returns true if this is a split parent region. */
577  @Override
578  public boolean isSplitParent() {
579    if (!isSplit()) return false;
580    if (!isOffline()) {
581      LOG.warn("Region is split but NOT offline: " + getRegionNameAsString());
582    }
583    return true;
584  }
585
586  /**
587   * Returns the region replica id
588   * @return returns region replica id
589   */
590  @Override
591  public int getReplicaId() {
592    return replicaId;
593  }
594
595  /**
596   * @see java.lang.Object#toString()
597   */
598  @Override
599  public String toString() {
600    return "{ENCODED => " + getEncodedName() + ", " + HConstants.NAME + " => '"
601      + Bytes.toStringBinary(this.regionName) + "', STARTKEY => '"
602      + Bytes.toStringBinary(this.startKey) + "', ENDKEY => '" + Bytes.toStringBinary(this.endKey)
603      + "'" + (isOffline() ? ", OFFLINE => true" : "") + (isSplit() ? ", SPLIT => true" : "")
604      + ((replicaId > 0) ? ", REPLICA_ID => " + replicaId : "") + "}";
605  }
606
607  /**
608   * @see java.lang.Object#equals(java.lang.Object)
609   */
610  @Override
611  public boolean equals(Object o) {
612    if (this == o) {
613      return true;
614    }
615    if (o == null) {
616      return false;
617    }
618    if (!(o instanceof HRegionInfo)) {
619      return false;
620    }
621    return this.compareTo((HRegionInfo) o) == 0;
622  }
623
624  /**
625   * @see java.lang.Object#hashCode()
626   */
627  @Override
628  public int hashCode() {
629    return this.hashCode;
630  }
631
632  /**
633   * @return Comparator to use comparing {@link KeyValue}s.
634   * @deprecated Use Region#getCellComparator(). deprecated for hbase 2.0, remove for hbase 3.0
635   */
636  @Deprecated
637  public KVComparator getComparator() {
638    return isMetaRegion() ? KeyValue.META_COMPARATOR : KeyValue.COMPARATOR;
639  }
640
641  /**
642   * Convert a HRegionInfo to the protobuf RegionInfo
643   * @return the converted RegionInfo
644   */
645  HBaseProtos.RegionInfo convert() {
646    return convert(this);
647  }
648
649  /**
650   * Convert a HRegionInfo to a RegionInfo
651   * @param info the HRegionInfo to convert
652   * @return the converted RegionInfo
653   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
654   *             toRegionInfo(org.apache.hadoop.hbase.client.RegionInfo) in
655   *             org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil.
656   */
657  @Deprecated
658  @InterfaceAudience.Private
659  public static HBaseProtos.RegionInfo convert(final HRegionInfo info) {
660    return ProtobufUtil.toRegionInfo(info);
661  }
662
663  /**
664   * Convert a RegionInfo to a HRegionInfo
665   * @param proto the RegionInfo to convert
666   * @return the converted HRegionInfo
667   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
668   *             toRegionInfo(HBaseProtos.RegionInfo) in
669   *             org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil.
670   */
671  @Deprecated
672  @InterfaceAudience.Private
673  public static HRegionInfo convert(final HBaseProtos.RegionInfo proto) {
674    RegionInfo ri = ProtobufUtil.toRegionInfo(proto);
675    // This is hack of what is in RegionReplicaUtil but it is doing translation of
676    // RegionInfo into HRegionInfo which is what is wanted here.
677    HRegionInfo hri;
678    if (ri.isMetaRegion()) {
679      hri = ri.getReplicaId() == RegionInfo.DEFAULT_REPLICA_ID
680        ? HRegionInfo.FIRST_META_REGIONINFO
681        : new HRegionInfo(ri.getRegionId(), ri.getTable(), ri.getReplicaId());
682    } else {
683      hri = new HRegionInfo(ri.getTable(), ri.getStartKey(), ri.getEndKey(), ri.isSplit(),
684        ri.getRegionId(), ri.getReplicaId());
685      if (proto.hasOffline()) {
686        hri.setOffline(proto.getOffline());
687      }
688    }
689    return hri;
690  }
691
692  /**
693   * @return This instance serialized as protobuf w/ a magic pb prefix.
694   * @see #parseFrom(byte[])
695   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
696   *             {@link org.apache.hadoop.hbase.client.RegionInfo#toByteArray(RegionInfo)}.
697   */
698  @Deprecated
699  public byte[] toByteArray() {
700    return RegionInfo.toByteArray(this);
701  }
702
703  /**
704   * @return A deserialized {@link HRegionInfo} or null if we failed deserialize or passed bytes
705   *         null
706   * @see #toByteArray()
707   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
708   *             {@link org.apache.hadoop.hbase.client.RegionInfo#parseFromOrNull(byte[])}.
709   */
710  @Deprecated
711  public static HRegionInfo parseFromOrNull(final byte[] bytes) {
712    if (bytes == null) return null;
713    return parseFromOrNull(bytes, 0, bytes.length);
714  }
715
716  /**
717   * @return A deserialized {@link HRegionInfo} or null if we failed deserialize or passed bytes
718   *         null
719   * @see #toByteArray()
720   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
721   *             {@link org.apache.hadoop.hbase.client.RegionInfo#parseFromOrNull(byte[], int, int)}.
722   */
723  @Deprecated
724  public static HRegionInfo parseFromOrNull(final byte[] bytes, int offset, int len) {
725    if (bytes == null || len <= 0) return null;
726    try {
727      return parseFrom(bytes, offset, len);
728    } catch (DeserializationException e) {
729      return null;
730    }
731  }
732
733  /**
734   * @param bytes A pb RegionInfo serialized with a pb magic prefix.
735   * @return A deserialized {@link HRegionInfo}
736   * @see #toByteArray()
737   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
738   *             {@link org.apache.hadoop.hbase.client.RegionInfo#parseFrom(byte[])}.
739   */
740  public static HRegionInfo parseFrom(final byte[] bytes) throws DeserializationException {
741    if (bytes == null) return null;
742    return parseFrom(bytes, 0, bytes.length);
743  }
744
745  /**
746   * @param bytes  A pb RegionInfo serialized with a pb magic prefix.
747   * @param offset starting point in the byte array
748   * @param len    length to read on the byte array
749   * @return A deserialized {@link HRegionInfo}
750   * @see #toByteArray()
751   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
752   *             {@link org.apache.hadoop.hbase.client.RegionInfo#parseFrom(byte[], int, int)}.
753   */
754  @Deprecated
755  public static HRegionInfo parseFrom(final byte[] bytes, int offset, int len)
756    throws DeserializationException {
757    if (ProtobufUtil.isPBMagicPrefix(bytes, offset, len)) {
758      int pblen = ProtobufUtil.lengthOfPBMagic();
759      try {
760        HBaseProtos.RegionInfo.Builder builder = HBaseProtos.RegionInfo.newBuilder();
761        ProtobufUtil.mergeFrom(builder, bytes, pblen + offset, len - pblen);
762        HBaseProtos.RegionInfo ri = builder.build();
763        return convert(ri);
764      } catch (IOException e) {
765        throw new DeserializationException(e);
766      }
767    } else {
768      throw new DeserializationException("PB encoded HRegionInfo expected");
769    }
770  }
771
772  /**
773   * Use this instead of {@link #toByteArray()} when writing to a stream and you want to use the pb
774   * mergeDelimitedFrom (w/o the delimiter, pb reads to EOF which may not be what you want).
775   * @return This instance serialized as a delimited protobuf w/ a magic pb prefix.
776   * @see #toByteArray()
777   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
778   *             {@link RegionInfo#toDelimitedByteArray(RegionInfo)}.
779   */
780  @Deprecated
781  public byte[] toDelimitedByteArray() throws IOException {
782    return RegionInfo.toDelimitedByteArray(this);
783  }
784
785  /**
786   * Get the descriptive name as {@link RegionState} does it but with hidden startkey optionally
787   * @return descriptive string
788   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
789   *             RegionInfoDisplay#getDescriptiveNameFromRegionStateForDisplay(RegionState,
790   *             Configuration) over in hbase-server module.
791   */
792  @Deprecated
793  @InterfaceAudience.Private
794  public static String getDescriptiveNameFromRegionStateForDisplay(RegionState state,
795    Configuration conf) {
796    return RegionInfoDisplay.getDescriptiveNameFromRegionStateForDisplay(state, conf);
797  }
798
799  /**
800   * Get the end key for display. Optionally hide the real end key.
801   * @return the endkey
802   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
803   *             RegionInfoDisplay#getEndKeyForDisplay(RegionInfo, Configuration) over in
804   *             hbase-server module.
805   */
806  @Deprecated
807  @InterfaceAudience.Private
808  public static byte[] getEndKeyForDisplay(HRegionInfo hri, Configuration conf) {
809    return RegionInfoDisplay.getEndKeyForDisplay(hri, conf);
810  }
811
812  /**
813   * Get the start key for display. Optionally hide the real start key.
814   * @return the startkey
815   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
816   *             RegionInfoDisplay#getStartKeyForDisplay(RegionInfo, Configuration) over in
817   *             hbase-server module.
818   */
819  @Deprecated
820  @InterfaceAudience.Private
821  public static byte[] getStartKeyForDisplay(HRegionInfo hri, Configuration conf) {
822    return RegionInfoDisplay.getStartKeyForDisplay(hri, conf);
823  }
824
825  /**
826   * Get the region name for display. Optionally hide the start key.
827   * @return region name as String
828   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
829   *             RegionInfoDisplay#getRegionNameAsStringForDisplay(RegionInfo, Configuration) over
830   *             in hbase-server module.
831   */
832  @Deprecated
833  @InterfaceAudience.Private
834  public static String getRegionNameAsStringForDisplay(HRegionInfo hri, Configuration conf) {
835    return RegionInfoDisplay.getRegionNameAsStringForDisplay(hri, conf);
836  }
837
838  /**
839   * Get the region name for display. Optionally hide the start key.
840   * @return region name bytes
841   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
842   *             RegionInfoDisplay#getRegionNameForDisplay(RegionInfo, Configuration) over in
843   *             hbase-server module.
844   */
845  @Deprecated
846  @InterfaceAudience.Private
847  public static byte[] getRegionNameForDisplay(HRegionInfo hri, Configuration conf) {
848    return RegionInfoDisplay.getRegionNameForDisplay(hri, conf);
849  }
850
851  /**
852   * Parses an HRegionInfo instance from the passed in stream. Presumes the HRegionInfo was
853   * serialized to the stream with {@link #toDelimitedByteArray()}
854   * @return An instance of HRegionInfo.
855   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
856   *             {@link RegionInfo#parseFrom(DataInputStream)}.
857   */
858  @Deprecated
859  @InterfaceAudience.Private
860  public static HRegionInfo parseFrom(final DataInputStream in) throws IOException {
861    // I need to be able to move back in the stream if this is not a pb serialization so I can
862    // do the Writable decoding instead.
863    int pblen = ProtobufUtil.lengthOfPBMagic();
864    byte[] pbuf = new byte[pblen];
865    if (in.markSupported()) { // read it with mark()
866      in.mark(pblen);
867    }
868
869    // assumption: if Writable serialization, it should be longer than pblen.
870    in.readFully(pbuf, 0, pblen);
871    if (ProtobufUtil.isPBMagicPrefix(pbuf)) {
872      return convert(HBaseProtos.RegionInfo.parseDelimitedFrom(in));
873    } else {
874      throw new IOException("PB encoded HRegionInfo expected");
875    }
876  }
877
878  /**
879   * Serializes given HRegionInfo's as a byte array. Use this instead of {@link #toByteArray()} when
880   * writing to a stream and you want to use the pb mergeDelimitedFrom (w/o the delimiter, pb reads
881   * to EOF which may not be what you want). {@link #parseDelimitedFrom(byte[], int, int)} can be
882   * used to read back the instances.
883   * @param infos HRegionInfo objects to serialize
884   * @return This instance serialized as a delimited protobuf w/ a magic pb prefix.
885   * @see #toByteArray()
886   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
887   *             {@link RegionInfo#toDelimitedByteArray(RegionInfo...)}.
888   */
889  @Deprecated
890  @InterfaceAudience.Private
891  public static byte[] toDelimitedByteArray(HRegionInfo... infos) throws IOException {
892    return RegionInfo.toDelimitedByteArray(infos);
893  }
894
895  /**
896   * Parses all the HRegionInfo instances from the passed in stream until EOF. Presumes the
897   * HRegionInfo's were serialized to the stream with {@link #toDelimitedByteArray()}
898   * @param bytes  serialized bytes
899   * @param offset the start offset into the byte[] buffer
900   * @param length how far we should read into the byte[] buffer
901   * @return All the hregioninfos that are in the byte array. Keeps reading till we hit the end.
902   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
903   *             {@link RegionInfo#parseDelimitedFrom(byte[], int, int)}.
904   */
905  @Deprecated
906  public static List<HRegionInfo> parseDelimitedFrom(final byte[] bytes, final int offset,
907    final int length) throws IOException {
908    if (bytes == null) {
909      throw new IllegalArgumentException("Can't build an object with empty bytes array");
910    }
911    DataInputBuffer in = new DataInputBuffer();
912    List<HRegionInfo> hris = new ArrayList<>();
913    try {
914      in.reset(bytes, offset, length);
915      while (in.available() > 0) {
916        HRegionInfo hri = parseFrom(in);
917        hris.add(hri);
918      }
919    } finally {
920      in.close();
921    }
922    return hris;
923  }
924
925  /**
926   * Check whether two regions are adjacent
927   * @return true if two regions are adjacent
928   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
929   *             {@link org.apache.hadoop.hbase.client.RegionInfo#areAdjacent(RegionInfo, RegionInfo)}.
930   */
931  @Deprecated
932  public static boolean areAdjacent(HRegionInfo regionA, HRegionInfo regionB) {
933    return RegionInfo.areAdjacent(regionA, regionB);
934  }
935}