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