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