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