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 = (int) (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
1004 public static RegionInfo convert(final HRegionInfo info) {
1005 if (info == null) return null;
1006 RegionInfo.Builder builder = RegionInfo.newBuilder();
1007 builder.setTableName(ProtobufUtil.toProtoTableName(info.getTable()));
1008 builder.setRegionId(info.getRegionId());
1009 if (info.getStartKey() != null) {
1010 builder.setStartKey(ByteStringer.wrap(info.getStartKey()));
1011 }
1012 if (info.getEndKey() != null) {
1013 builder.setEndKey(ByteStringer.wrap(info.getEndKey()));
1014 }
1015 builder.setOffline(info.isOffline());
1016 builder.setSplit(info.isSplit());
1017 builder.setReplicaId(info.getReplicaId());
1018 return builder.build();
1019 }
1020
1021
1022
1023
1024
1025
1026
1027 public static HRegionInfo convert(final RegionInfo proto) {
1028 if (proto == null) return null;
1029 TableName tableName =
1030 ProtobufUtil.toTableName(proto.getTableName());
1031 if (tableName.equals(TableName.META_TABLE_NAME)) {
1032 return RegionReplicaUtil.getRegionInfoForReplica(FIRST_META_REGIONINFO,
1033 proto.getReplicaId());
1034 }
1035 long regionId = proto.getRegionId();
1036 int replicaId = proto.hasReplicaId() ? proto.getReplicaId() : DEFAULT_REPLICA_ID;
1037 byte[] startKey = null;
1038 byte[] endKey = null;
1039 if (proto.hasStartKey()) {
1040 startKey = proto.getStartKey().toByteArray();
1041 }
1042 if (proto.hasEndKey()) {
1043 endKey = proto.getEndKey().toByteArray();
1044 }
1045 boolean split = false;
1046 if (proto.hasSplit()) {
1047 split = proto.getSplit();
1048 }
1049 HRegionInfo hri = new HRegionInfo(
1050 tableName,
1051 startKey,
1052 endKey, split, regionId, replicaId);
1053 if (proto.hasOffline()) {
1054 hri.setOffline(proto.getOffline());
1055 }
1056 return hri;
1057 }
1058
1059
1060
1061
1062
1063 public byte [] toByteArray() {
1064 byte [] bytes = convert(this).toByteArray();
1065 return ProtobufUtil.prependPBMagic(bytes);
1066 }
1067
1068
1069
1070
1071
1072
1073 public static HRegionInfo parseFromOrNull(final byte [] bytes) {
1074 if (bytes == null) return null;
1075 return parseFromOrNull(bytes, 0, bytes.length);
1076 }
1077
1078
1079
1080
1081
1082
1083 public static HRegionInfo parseFromOrNull(final byte [] bytes, int offset, int len) {
1084 if (bytes == null || len <= 0) return null;
1085 try {
1086 return parseFrom(bytes, offset, len);
1087 } catch (DeserializationException e) {
1088 return null;
1089 }
1090 }
1091
1092
1093
1094
1095
1096
1097
1098 public static HRegionInfo parseFrom(final byte [] bytes) throws DeserializationException {
1099 if (bytes == null) return null;
1100 return parseFrom(bytes, 0, bytes.length);
1101 }
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 public static HRegionInfo parseFrom(final byte [] bytes, int offset, int len)
1112 throws DeserializationException {
1113 if (ProtobufUtil.isPBMagicPrefix(bytes, offset, len)) {
1114 int pblen = ProtobufUtil.lengthOfPBMagic();
1115 try {
1116 HBaseProtos.RegionInfo.Builder builder = HBaseProtos.RegionInfo.newBuilder();
1117 ProtobufUtil.mergeFrom(builder, bytes, pblen + offset, len - pblen);
1118 HBaseProtos.RegionInfo ri = builder.build();
1119 return convert(ri);
1120 } catch (IOException e) {
1121 throw new DeserializationException(e);
1122 }
1123 } else {
1124 try {
1125 HRegionInfo hri = new HRegionInfo();
1126 hri.readFields(bytes, offset, len);
1127 return hri;
1128 } catch (IOException e) {
1129 throw new DeserializationException(e);
1130 }
1131 }
1132 }
1133
1134
1135
1136
1137
1138
1139
1140
1141 public byte [] toDelimitedByteArray() throws IOException {
1142 return ProtobufUtil.toDelimitedByteArray(convert(this));
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 }