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