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