1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.DataInputStream;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31 import org.apache.hadoop.hbase.classification.InterfaceStability;
32 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
33 import org.apache.hadoop.hbase.KeyValue.KVComparator;
34 import org.apache.hadoop.hbase.exceptions.DeserializationException;
35 import org.apache.hadoop.hbase.master.RegionState;
36 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
37 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
38 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
39 import org.apache.hadoop.hbase.util.ByteStringer;
40 import org.apache.hadoop.hbase.util.Bytes;
41 import org.apache.hadoop.hbase.util.JenkinsHash;
42 import org.apache.hadoop.hbase.util.MD5Hash;
43 import org.apache.hadoop.io.DataInputBuffer;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 @InterfaceAudience.Public
76 @InterfaceStability.Evolving
77 public class HRegionInfo implements Comparable<HRegionInfo> {
78
79 private static final Log LOG = LogFactory.getLog(HRegionInfo.class);
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 private static final int ENC_SEPARATOR = '.';
108 public static final int MD5_HEX_LENGTH = 32;
109
110
111 public static final String ENCODED_REGION_NAME_REGEX = "(?:[a-f0-9]+)";
112
113
114
115 public static final String REPLICA_ID_FORMAT = "%04X";
116
117 public static final byte REPLICA_ID_DELIMITER = (byte)'_';
118
119 private static final int MAX_REPLICA_ID = 0xFFFF;
120 public static final int DEFAULT_REPLICA_ID = 0;
121
122
123
124
125
126
127 private static boolean hasEncodedName(final byte[] regionName) {
128
129 if ((regionName.length >= 1)
130 && (regionName[regionName.length - 1] == ENC_SEPARATOR)) {
131
132 return true;
133 }
134 return false;
135 }
136
137
138
139
140
141 public static String encodeRegionName(final byte [] regionName) {
142 String encodedName;
143 if (hasEncodedName(regionName)) {
144
145
146 encodedName = Bytes.toString(regionName,
147 regionName.length - MD5_HEX_LENGTH - 1,
148 MD5_HEX_LENGTH);
149 } else {
150
151
152 int hashVal = Math.abs(JenkinsHash.getInstance().hash(regionName,
153 regionName.length, 0));
154 encodedName = String.valueOf(hashVal);
155 }
156 return encodedName;
157 }
158
159
160
161
162 public String getShortNameToLog() {
163 return prettyPrint(this.getEncodedName());
164 }
165
166
167
168
169
170
171
172 public static String prettyPrint(final String encodedRegionName) {
173 if (encodedRegionName.equals("1028785192")) {
174 return encodedRegionName + "/hbase:meta";
175 }
176 return encodedRegionName;
177 }
178
179 private byte [] endKey = HConstants.EMPTY_BYTE_ARRAY;
180
181
182
183 private boolean offLine = false;
184 private long regionId = -1;
185 private transient byte [] regionName = HConstants.EMPTY_BYTE_ARRAY;
186 private boolean split = false;
187 private byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
188 private int hashCode = -1;
189
190 public static final String NO_HASH = null;
191 private String encodedName = null;
192 private byte [] encodedNameAsBytes = null;
193 private int replicaId = DEFAULT_REPLICA_ID;
194
195
196 private TableName tableName = null;
197 final static String DISPLAY_KEYS_KEY = "hbase.display.keys";
198 public final static byte[] HIDDEN_END_KEY = Bytes.toBytes("hidden-end-key");
199 public final static byte[] HIDDEN_START_KEY = Bytes.toBytes("hidden-start-key");
200
201
202 public static final HRegionInfo FIRST_META_REGIONINFO =
203 new HRegionInfo(1L, TableName.META_TABLE_NAME);
204
205 private void setHashCode() {
206 int result = Arrays.hashCode(this.regionName);
207 result ^= this.regionId;
208 result ^= Arrays.hashCode(this.startKey);
209 result ^= Arrays.hashCode(this.endKey);
210 result ^= Boolean.valueOf(this.offLine).hashCode();
211 result ^= Arrays.hashCode(this.tableName.getName());
212 result ^= this.replicaId;
213 this.hashCode = result;
214 }
215
216
217
218
219
220
221 private HRegionInfo(long regionId, TableName tableName) {
222 this(regionId, tableName, DEFAULT_REPLICA_ID);
223 }
224
225 public HRegionInfo(long regionId, TableName tableName, int replicaId) {
226 super();
227 this.regionId = regionId;
228 this.tableName = tableName;
229 this.replicaId = replicaId;
230
231 this.regionName = createRegionName(tableName, null, regionId, replicaId, false);
232 setHashCode();
233 }
234
235 public HRegionInfo(final TableName tableName) {
236 this(tableName, null, null);
237 }
238
239
240
241
242
243
244
245
246
247 public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey)
248 throws IllegalArgumentException {
249 this(tableName, startKey, endKey, false);
250 }
251
252
253
254
255
256
257
258
259
260
261
262 public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
263 final boolean split)
264 throws IllegalArgumentException {
265 this(tableName, startKey, endKey, split, System.currentTimeMillis());
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279 public HRegionInfo(final TableName tableName, final byte[] startKey,
280 final byte[] endKey, final boolean split, final long regionid)
281 throws IllegalArgumentException {
282 this(tableName, startKey, endKey, split, regionid, DEFAULT_REPLICA_ID);
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296
297 public HRegionInfo(final TableName tableName, final byte[] startKey,
298 final byte[] endKey, final boolean split, final long regionid,
299 final int replicaId)
300 throws IllegalArgumentException {
301 super();
302 if (tableName == null) {
303 throw new IllegalArgumentException("TableName cannot be null");
304 }
305 this.tableName = tableName;
306 this.offLine = false;
307 this.regionId = regionid;
308 this.replicaId = replicaId;
309 if (this.replicaId > MAX_REPLICA_ID) {
310 throw new IllegalArgumentException("ReplicaId cannot be greater than" + MAX_REPLICA_ID);
311 }
312
313 this.regionName = createRegionName(this.tableName, startKey, regionId, replicaId, true);
314
315 this.split = split;
316 this.endKey = endKey == null? HConstants.EMPTY_END_ROW: endKey.clone();
317 this.startKey = startKey == null?
318 HConstants.EMPTY_START_ROW: startKey.clone();
319 this.tableName = tableName;
320 setHashCode();
321 }
322
323
324
325
326
327
328 public HRegionInfo(HRegionInfo other) {
329 super();
330 this.endKey = other.getEndKey();
331 this.offLine = other.isOffline();
332 this.regionId = other.getRegionId();
333 this.regionName = other.getRegionName();
334 this.split = other.isSplit();
335 this.startKey = other.getStartKey();
336 this.hashCode = other.hashCode();
337 this.encodedName = other.getEncodedName();
338 this.tableName = other.tableName;
339 this.replicaId = other.replicaId;
340 }
341
342 public HRegionInfo(HRegionInfo other, int replicaId) {
343 this(other);
344 this.replicaId = replicaId;
345 this.setHashCode();
346 }
347
348
349
350
351
352
353
354
355
356
357 public static byte [] createRegionName(final TableName tableName,
358 final byte [] startKey, final long regionid, boolean newFormat) {
359 return createRegionName(tableName, startKey, Long.toString(regionid), newFormat);
360 }
361
362
363
364
365
366
367
368
369
370
371 public static byte [] createRegionName(final TableName tableName,
372 final byte [] startKey, final String id, boolean newFormat) {
373 return createRegionName(tableName, startKey, Bytes.toBytes(id), newFormat);
374 }
375
376
377
378
379
380
381
382
383
384
385
386 public static byte [] createRegionName(final TableName tableName,
387 final byte [] startKey, final long regionid, int replicaId, boolean newFormat) {
388 return createRegionName(tableName, startKey, Bytes.toBytes(Long.toString(regionid)),
389 replicaId, newFormat);
390 }
391
392
393
394
395
396
397
398
399
400
401 public static byte [] createRegionName(final TableName tableName,
402 final byte [] startKey, final byte [] id, boolean newFormat) {
403 return createRegionName(tableName, startKey, id, DEFAULT_REPLICA_ID, newFormat);
404 }
405
406
407
408
409
410
411
412
413
414 public static byte [] createRegionName(final TableName tableName,
415 final byte [] startKey, final byte [] id, final int replicaId, boolean newFormat) {
416 int len = tableName.getName().length + 2 + id.length +
417 (startKey == null? 0: startKey.length);
418 if (newFormat) {
419 len += MD5_HEX_LENGTH + 2;
420 }
421 byte[] replicaIdBytes = null;
422
423
424
425 if (replicaId > 0) {
426
427 replicaIdBytes = Bytes.toBytes(String.format(REPLICA_ID_FORMAT, replicaId));
428 len += 1 + replicaIdBytes.length;
429 }
430
431 byte [] b = new byte [len];
432
433 int offset = tableName.getName().length;
434 System.arraycopy(tableName.getName(), 0, b, 0, offset);
435 b[offset++] = HConstants.DELIMITER;
436 if (startKey != null && startKey.length > 0) {
437 System.arraycopy(startKey, 0, b, offset, startKey.length);
438 offset += startKey.length;
439 }
440 b[offset++] = HConstants.DELIMITER;
441 System.arraycopy(id, 0, b, offset, id.length);
442 offset += id.length;
443
444 if (replicaIdBytes != null) {
445 b[offset++] = REPLICA_ID_DELIMITER;
446 System.arraycopy(replicaIdBytes, 0, b, offset, replicaIdBytes.length);
447 offset += replicaIdBytes.length;
448 }
449
450 if (newFormat) {
451
452
453
454
455
456
457
458 String md5Hash = MD5Hash.getMD5AsHex(b, 0, offset);
459 byte [] md5HashBytes = Bytes.toBytes(md5Hash);
460
461 if (md5HashBytes.length != MD5_HEX_LENGTH) {
462 LOG.error("MD5-hash length mismatch: Expected=" + MD5_HEX_LENGTH +
463 "; Got=" + md5HashBytes.length);
464 }
465
466
467 b[offset++] = ENC_SEPARATOR;
468 System.arraycopy(md5HashBytes, 0, b, offset, MD5_HEX_LENGTH);
469 offset += MD5_HEX_LENGTH;
470 b[offset++] = ENC_SEPARATOR;
471 }
472
473 return b;
474 }
475
476
477
478
479
480
481 public static TableName getTable(final byte [] regionName) {
482 int offset = -1;
483 for (int i = 0; i < regionName.length; i++) {
484 if (regionName[i] == HConstants.DELIMITER) {
485 offset = i;
486 break;
487 }
488 }
489 byte[] buff = new byte[offset];
490 System.arraycopy(regionName, 0, buff, 0, offset);
491 return TableName.valueOf(buff);
492 }
493
494
495
496
497
498
499 public static byte[] getStartKey(final byte[] regionName) throws IOException {
500 return parseRegionName(regionName)[1];
501 }
502
503
504
505
506
507
508
509 public static byte [][] parseRegionName(final byte [] regionName)
510 throws IOException {
511
512
513
514
515
516 int offset = -1;
517 for (int i = 0; i < regionName.length; i++) {
518 if (regionName[i] == HConstants.DELIMITER) {
519 offset = i;
520 break;
521 }
522 }
523 if (offset == -1) {
524 throw new IOException("Invalid regionName format: " + Bytes.toStringBinary(regionName));
525 }
526 byte[] tableName = new byte[offset];
527 System.arraycopy(regionName, 0, tableName, 0, offset);
528 offset = -1;
529
530 int endOffset = regionName.length;
531
532 if (regionName.length > MD5_HEX_LENGTH + 2
533 && regionName[regionName.length-1] == ENC_SEPARATOR
534 && regionName[regionName.length-MD5_HEX_LENGTH-2] == ENC_SEPARATOR) {
535 endOffset = endOffset - MD5_HEX_LENGTH - 2;
536 }
537
538
539 byte[] replicaId = null;
540 int idEndOffset = endOffset;
541 for (int i = endOffset - 1; i > 0; i--) {
542 if (regionName[i] == REPLICA_ID_DELIMITER) {
543 replicaId = new byte[endOffset - i - 1];
544 System.arraycopy(regionName, i + 1, replicaId, 0,
545 endOffset - i - 1);
546 idEndOffset = i;
547
548 }
549 if (regionName[i] == HConstants.DELIMITER) {
550 offset = i;
551 break;
552 }
553 }
554 if (offset == -1) {
555 throw new IOException("Invalid regionName format: " + Bytes.toStringBinary(regionName));
556 }
557 byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
558 if(offset != tableName.length + 1) {
559 startKey = new byte[offset - tableName.length - 1];
560 System.arraycopy(regionName, tableName.length + 1, startKey, 0,
561 offset - tableName.length - 1);
562 }
563 byte [] id = new byte[idEndOffset - offset - 1];
564 System.arraycopy(regionName, offset + 1, id, 0,
565 idEndOffset - offset - 1);
566 byte [][] elements = new byte[replicaId == null ? 3 : 4][];
567 elements[0] = tableName;
568 elements[1] = startKey;
569 elements[2] = id;
570 if (replicaId != null) {
571 elements[3] = replicaId;
572 }
573
574 return elements;
575 }
576
577
578 public long getRegionId(){
579 return regionId;
580 }
581
582
583
584
585
586 public byte [] getRegionName(){
587 return regionName;
588 }
589
590
591
592
593 public String getRegionNameAsString() {
594 if (hasEncodedName(this.regionName)) {
595
596 return Bytes.toStringBinary(this.regionName);
597 }
598
599
600
601
602 return Bytes.toStringBinary(this.regionName) + "." + this.getEncodedName();
603 }
604
605
606 public synchronized String getEncodedName() {
607 if (this.encodedName == null) {
608 this.encodedName = encodeRegionName(this.regionName);
609 }
610 return this.encodedName;
611 }
612
613 public synchronized byte [] getEncodedNameAsBytes() {
614 if (this.encodedNameAsBytes == null) {
615 this.encodedNameAsBytes = Bytes.toBytes(getEncodedName());
616 }
617 return this.encodedNameAsBytes;
618 }
619
620
621 public byte [] getStartKey(){
622 return startKey;
623 }
624
625
626 public byte [] getEndKey(){
627 return endKey;
628 }
629
630
631
632
633
634 public TableName getTable() {
635
636
637
638 if (tableName == null || tableName.getName().length == 0) {
639 tableName = getTable(getRegionName());
640 }
641 return this.tableName;
642 }
643
644
645
646
647
648
649
650
651 public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) {
652 if (Bytes.compareTo(rangeStartKey, rangeEndKey) > 0) {
653 throw new IllegalArgumentException(
654 "Invalid range: " + Bytes.toStringBinary(rangeStartKey) +
655 " > " + Bytes.toStringBinary(rangeEndKey));
656 }
657
658 boolean firstKeyInRange = Bytes.compareTo(rangeStartKey, startKey) >= 0;
659 boolean lastKeyInRange =
660 Bytes.compareTo(rangeEndKey, endKey) < 0 ||
661 Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY);
662 return firstKeyInRange && lastKeyInRange;
663 }
664
665
666
667
668 public boolean containsRow(byte[] row) {
669 return Bytes.compareTo(row, startKey) >= 0 &&
670 (Bytes.compareTo(row, endKey) < 0 ||
671 Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY));
672 }
673
674
675
676
677 public boolean isMetaTable() {
678 return isMetaRegion();
679 }
680
681
682 public boolean isMetaRegion() {
683 return tableName.equals(HRegionInfo.FIRST_META_REGIONINFO.getTable());
684 }
685
686
687
688
689 public boolean isSystemTable() {
690 return tableName.isSystemTable();
691 }
692
693
694
695
696 public boolean isSplit() {
697 return this.split;
698 }
699
700
701
702
703 public void setSplit(boolean split) {
704 this.split = split;
705 }
706
707
708
709
710 public boolean isOffline() {
711 return this.offLine;
712 }
713
714
715
716
717
718
719 public void setOffline(boolean offLine) {
720 this.offLine = offLine;
721 }
722
723
724
725
726 public boolean isSplitParent() {
727 if (!isSplit()) return false;
728 if (!isOffline()) {
729 LOG.warn("Region is split but NOT offline: " + getRegionNameAsString());
730 }
731 return true;
732 }
733
734
735
736
737
738 public int getReplicaId() {
739 return replicaId;
740 }
741
742
743
744
745 @Override
746 public String toString() {
747 return "{ENCODED => " + getEncodedName() + ", " +
748 HConstants.NAME + " => '" + Bytes.toStringBinary(this.regionName)
749 + "', STARTKEY => '" +
750 Bytes.toStringBinary(this.startKey) + "', ENDKEY => '" +
751 Bytes.toStringBinary(this.endKey) + "'" +
752 (isOffline()? ", OFFLINE => true": "") +
753 (isSplit()? ", SPLIT => true": "") +
754 ((replicaId > 0)? ", REPLICA_ID => " + replicaId : "") + "}";
755 }
756
757
758
759
760 @Override
761 public boolean equals(Object o) {
762 if (this == o) {
763 return true;
764 }
765 if (o == null) {
766 return false;
767 }
768 if (!(o instanceof HRegionInfo)) {
769 return false;
770 }
771 return this.compareTo((HRegionInfo)o) == 0;
772 }
773
774
775
776
777 @Override
778 public int hashCode() {
779 return this.hashCode;
780 }
781
782
783
784
785
786 @Override
787 public int compareTo(HRegionInfo o) {
788 if (o == null) {
789 return 1;
790 }
791
792
793 int result = this.tableName.compareTo(o.tableName);
794 if (result != 0) {
795 return result;
796 }
797
798
799 result = Bytes.compareTo(this.startKey, o.startKey);
800 if (result != 0) {
801 return result;
802 }
803
804
805 result = Bytes.compareTo(this.endKey, o.endKey);
806
807 if (result != 0) {
808 if (this.getStartKey().length != 0
809 && this.getEndKey().length == 0) {
810 return 1;
811 }
812 if (o.getStartKey().length != 0
813 && o.getEndKey().length == 0) {
814 return -1;
815 }
816 return result;
817 }
818
819
820
821 if (this.regionId > o.regionId) {
822 return 1;
823 } else if (this.regionId < o.regionId) {
824 return -1;
825 }
826
827 int replicaDiff = this.getReplicaId() - o.getReplicaId();
828 if (replicaDiff != 0) return replicaDiff;
829
830 if (this.offLine == o.offLine)
831 return 0;
832 if (this.offLine == true) return -1;
833
834 return 1;
835 }
836
837
838
839
840
841 @Deprecated
842 public KVComparator getComparator() {
843 return isMetaRegion()?
844 KeyValue.META_COMPARATOR: KeyValue.COMPARATOR;
845 }
846
847
848
849
850
851
852 RegionInfo convert() {
853 return convert(this);
854 }
855
856
857
858
859
860
861
862 public static RegionInfo convert(final HRegionInfo info) {
863 if (info == null) return null;
864 RegionInfo.Builder builder = RegionInfo.newBuilder();
865 builder.setTableName(ProtobufUtil.toProtoTableName(info.getTable()));
866 builder.setRegionId(info.getRegionId());
867 if (info.getStartKey() != null) {
868 builder.setStartKey(ByteStringer.wrap(info.getStartKey()));
869 }
870 if (info.getEndKey() != null) {
871 builder.setEndKey(ByteStringer.wrap(info.getEndKey()));
872 }
873 builder.setOffline(info.isOffline());
874 builder.setSplit(info.isSplit());
875 builder.setReplicaId(info.getReplicaId());
876 return builder.build();
877 }
878
879
880
881
882
883
884
885 public static HRegionInfo convert(final RegionInfo proto) {
886 if (proto == null) return null;
887 TableName tableName =
888 ProtobufUtil.toTableName(proto.getTableName());
889 if (tableName.equals(TableName.META_TABLE_NAME)) {
890 return RegionReplicaUtil.getRegionInfoForReplica(FIRST_META_REGIONINFO,
891 proto.getReplicaId());
892 }
893 long regionId = proto.getRegionId();
894 int replicaId = proto.hasReplicaId() ? proto.getReplicaId() : DEFAULT_REPLICA_ID;
895 byte[] startKey = null;
896 byte[] endKey = null;
897 if (proto.hasStartKey()) {
898 startKey = proto.getStartKey().toByteArray();
899 }
900 if (proto.hasEndKey()) {
901 endKey = proto.getEndKey().toByteArray();
902 }
903 boolean split = false;
904 if (proto.hasSplit()) {
905 split = proto.getSplit();
906 }
907 HRegionInfo hri = new HRegionInfo(
908 tableName,
909 startKey,
910 endKey, split, regionId, replicaId);
911 if (proto.hasOffline()) {
912 hri.setOffline(proto.getOffline());
913 }
914 return hri;
915 }
916
917
918
919
920
921 public byte [] toByteArray() {
922 byte [] bytes = convert().toByteArray();
923 return ProtobufUtil.prependPBMagic(bytes);
924 }
925
926
927
928
929
930
931 public static HRegionInfo parseFromOrNull(final byte [] bytes) {
932 if (bytes == null) return null;
933 return parseFromOrNull(bytes, 0, bytes.length);
934 }
935
936
937
938
939
940
941 public static HRegionInfo parseFromOrNull(final byte [] bytes, int offset, int len) {
942 if (bytes == null || len <= 0) return null;
943 try {
944 return parseFrom(bytes, offset, len);
945 } catch (DeserializationException e) {
946 return null;
947 }
948 }
949
950
951
952
953
954
955
956 public static HRegionInfo parseFrom(final byte [] bytes) throws DeserializationException {
957 if (bytes == null) return null;
958 return parseFrom(bytes, 0, bytes.length);
959 }
960
961
962
963
964
965
966
967
968
969 public static HRegionInfo parseFrom(final byte [] bytes, int offset, int len)
970 throws DeserializationException {
971 if (ProtobufUtil.isPBMagicPrefix(bytes, offset, len)) {
972 int pblen = ProtobufUtil.lengthOfPBMagic();
973 try {
974 HBaseProtos.RegionInfo.Builder builder = HBaseProtos.RegionInfo.newBuilder();
975 ProtobufUtil.mergeFrom(builder, bytes, pblen + offset, len - pblen);
976 HBaseProtos.RegionInfo ri = builder.build();
977 return convert(ri);
978 } catch (IOException e) {
979 throw new DeserializationException(e);
980 }
981 } else {
982 throw new DeserializationException("PB encoded HRegionInfo expected");
983 }
984 }
985
986
987
988
989
990
991
992
993 public byte [] toDelimitedByteArray() throws IOException {
994 return ProtobufUtil.toDelimitedByteArray(convert());
995 }
996
997
998
999
1000
1001
1002
1003
1004 public static String getDescriptiveNameFromRegionStateForDisplay(RegionState state,
1005 Configuration conf) {
1006 if (conf.getBoolean(DISPLAY_KEYS_KEY, true)) return state.toDescriptiveString();
1007 String descriptiveStringFromState = state.toDescriptiveString();
1008 int idx = descriptiveStringFromState.lastIndexOf(" state=");
1009 String regionName = getRegionNameAsStringForDisplay(state.getRegion(), conf);
1010 return regionName + descriptiveStringFromState.substring(idx);
1011 }
1012
1013
1014
1015
1016
1017
1018
1019 public static byte[] getEndKeyForDisplay(HRegionInfo hri, Configuration conf) {
1020 boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
1021 if (displayKey) return hri.getEndKey();
1022 return HIDDEN_END_KEY;
1023 }
1024
1025
1026
1027
1028
1029
1030
1031 public static byte[] getStartKeyForDisplay(HRegionInfo hri, Configuration conf) {
1032 boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
1033 if (displayKey) return hri.getStartKey();
1034 return HIDDEN_START_KEY;
1035 }
1036
1037
1038
1039
1040
1041
1042
1043 public static String getRegionNameAsStringForDisplay(HRegionInfo hri, Configuration conf) {
1044 return Bytes.toStringBinary(getRegionNameForDisplay(hri, conf));
1045 }
1046
1047
1048
1049
1050
1051
1052
1053 public static byte[] getRegionNameForDisplay(HRegionInfo hri, Configuration conf) {
1054 boolean displayKey = conf.getBoolean(DISPLAY_KEYS_KEY, true);
1055 if (displayKey || hri.getTable().equals(TableName.META_TABLE_NAME)) {
1056 return hri.getRegionName();
1057 } else {
1058
1059
1060 try {
1061 byte[][]regionNameParts = parseRegionName(hri.getRegionName());
1062 regionNameParts[1] = HIDDEN_START_KEY;
1063 int len = 0;
1064
1065 for (byte[] b : regionNameParts) {
1066 len += b.length;
1067 }
1068 byte[] encodedRegionName =
1069 Bytes.toBytes(encodeRegionName(hri.getRegionName()));
1070 len += encodedRegionName.length;
1071
1072 byte[] modifiedName = new byte[len + regionNameParts.length + 1];
1073 int lengthSoFar = 0;
1074 int loopCount = 0;
1075 for (byte[] b : regionNameParts) {
1076 System.arraycopy(b, 0, modifiedName, lengthSoFar, b.length);
1077 lengthSoFar += b.length;
1078 if (loopCount++ == 2) modifiedName[lengthSoFar++] = REPLICA_ID_DELIMITER;
1079 else modifiedName[lengthSoFar++] = HConstants.DELIMITER;
1080 }
1081
1082 modifiedName[lengthSoFar - 1] = ENC_SEPARATOR;
1083 System.arraycopy(encodedRegionName, 0, modifiedName, lengthSoFar,
1084 encodedRegionName.length);
1085 lengthSoFar += encodedRegionName.length;
1086 modifiedName[lengthSoFar] = ENC_SEPARATOR;
1087 return modifiedName;
1088 } catch (IOException e) {
1089
1090 throw new RuntimeException(e);
1091 }
1092 }
1093 }
1094
1095
1096
1097
1098
1099
1100
1101
1102 public static HRegionInfo parseFrom(final DataInputStream in) throws IOException {
1103
1104
1105 int pblen = ProtobufUtil.lengthOfPBMagic();
1106 byte [] pbuf = new byte[pblen];
1107 if (in.markSupported()) {
1108 in.mark(pblen);
1109 }
1110
1111
1112 int read = in.read(pbuf);
1113 if (read != pblen) throw new IOException("read=" + read + ", wanted=" + pblen);
1114 if (ProtobufUtil.isPBMagicPrefix(pbuf)) {
1115 return convert(HBaseProtos.RegionInfo.parseDelimitedFrom(in));
1116 } else {
1117 throw new IOException("PB encoded HRegionInfo expected");
1118 }
1119 }
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 public static byte[] toDelimitedByteArray(HRegionInfo... infos) throws IOException {
1132 byte[][] bytes = new byte[infos.length][];
1133 int size = 0;
1134 for (int i = 0; i < infos.length; i++) {
1135 bytes[i] = infos[i].toDelimitedByteArray();
1136 size += bytes[i].length;
1137 }
1138
1139 byte[] result = new byte[size];
1140 int offset = 0;
1141 for (byte[] b : bytes) {
1142 System.arraycopy(b, 0, result, offset, b.length);
1143 offset += b.length;
1144 }
1145 return result;
1146 }
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 public static List<HRegionInfo> parseDelimitedFrom(final byte[] bytes, final int offset,
1157 final int length) throws IOException {
1158 if (bytes == null) {
1159 throw new IllegalArgumentException("Can't build an object with empty bytes array");
1160 }
1161 DataInputBuffer in = new DataInputBuffer();
1162 List<HRegionInfo> hris = new ArrayList<HRegionInfo>();
1163 try {
1164 in.reset(bytes, offset, length);
1165 while (in.available() > 0) {
1166 HRegionInfo hri = parseFrom(in);
1167 hris.add(hri);
1168 }
1169 } finally {
1170 in.close();
1171 }
1172 return hris;
1173 }
1174
1175
1176
1177
1178
1179
1180
1181 public static boolean areAdjacent(HRegionInfo regionA, HRegionInfo regionB) {
1182 if (regionA == null || regionB == null) {
1183 throw new IllegalArgumentException(
1184 "Can't check whether adjacent for null region");
1185 }
1186 HRegionInfo a = regionA;
1187 HRegionInfo b = regionB;
1188 if (Bytes.compareTo(a.getStartKey(), b.getStartKey()) > 0) {
1189 a = regionB;
1190 b = regionA;
1191 }
1192 if (Bytes.compareTo(a.getEndKey(), b.getStartKey()) == 0) {
1193 return true;
1194 }
1195 return false;
1196 }
1197 }