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