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