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