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.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.classification.InterfaceAudience;
35 import org.apache.hadoop.classification.InterfaceStability;
36 import org.apache.hadoop.hbase.KeyValue.KVComparator;
37 import org.apache.hadoop.hbase.client.Result;
38 import org.apache.hadoop.hbase.exceptions.DeserializationException;
39 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
40 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
41 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
42 import org.apache.hadoop.hbase.util.Bytes;
43 import org.apache.hadoop.hbase.util.JenkinsHash;
44 import org.apache.hadoop.hbase.util.MD5Hash;
45 import org.apache.hadoop.hbase.util.Pair;
46 import org.apache.hadoop.hbase.util.PairOfSameType;
47 import org.apache.hadoop.io.DataInputBuffer;
48
49 import com.google.protobuf.ByteString;
50 import com.google.protobuf.InvalidProtocolBufferException;
51
52
53
54
55
56 @InterfaceAudience.Public
57 @InterfaceStability.Evolving
58 public class HRegionInfo implements Comparable<HRegionInfo> {
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 @Deprecated
82 public static final byte VERSION = 1;
83 private static final Log LOG = LogFactory.getLog(HRegionInfo.class);
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
111 private static final int ENC_SEPARATOR = '.';
112 public static final int MD5_HEX_LENGTH = 32;
113
114
115 public static final String ENCODED_REGION_NAME_REGEX = "(?:[a-f0-9]+)";
116
117
118
119
120
121
122
123 private static boolean hasEncodedName(final byte[] regionName) {
124
125 if ((regionName.length >= 1)
126 && (regionName[regionName.length - 1] == ENC_SEPARATOR)) {
127
128 return true;
129 }
130 return false;
131 }
132
133
134
135
136
137 public static String encodeRegionName(final byte [] regionName) {
138 String encodedName;
139 if (hasEncodedName(regionName)) {
140
141
142 encodedName = Bytes.toString(regionName,
143 regionName.length - MD5_HEX_LENGTH - 1,
144 MD5_HEX_LENGTH);
145 } else {
146
147
148 int hashVal = Math.abs(JenkinsHash.getInstance().hash(regionName,
149 regionName.length, 0));
150 encodedName = String.valueOf(hashVal);
151 }
152 return encodedName;
153 }
154
155
156
157
158 public String getShortNameToLog() {
159 return prettyPrint(this.getEncodedName());
160 }
161
162
163
164
165
166
167
168 public static String prettyPrint(final String encodedRegionName) {
169 if (encodedRegionName.equals("1028785192")) {
170 return encodedRegionName + "/.META.";
171 }
172 return encodedRegionName;
173 }
174
175 private byte [] endKey = HConstants.EMPTY_BYTE_ARRAY;
176
177
178
179 private boolean offLine = false;
180 private long regionId = -1;
181 private transient byte [] regionName = HConstants.EMPTY_BYTE_ARRAY;
182 private String regionNameStr = "";
183 private boolean split = false;
184 private byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
185 private int hashCode = -1;
186
187 public static final String NO_HASH = null;
188 private volatile String encodedName = NO_HASH;
189 private byte [] encodedNameAsBytes = null;
190
191
192 private TableName tableName = null;
193
194
195 public static final HRegionInfo ROOT_REGIONINFO =
196 new HRegionInfo(0L, TableName.ROOT_TABLE_NAME);
197
198
199 public static final HRegionInfo FIRST_META_REGIONINFO =
200 new HRegionInfo(1L, TableName.META_TABLE_NAME);
201
202 private void setHashCode() {
203 int result = Arrays.hashCode(this.regionName);
204 result ^= this.regionId;
205 result ^= Arrays.hashCode(this.startKey);
206 result ^= Arrays.hashCode(this.endKey);
207 result ^= Boolean.valueOf(this.offLine).hashCode();
208 result ^= Arrays.hashCode(this.tableName.getName());
209 this.hashCode = result;
210 }
211
212
213
214
215
216
217 private HRegionInfo(long regionId, TableName tableName) {
218 super();
219 this.regionId = regionId;
220 this.tableName = tableName;
221
222 this.regionName = createRegionName(tableName, null,
223 regionId, false);
224 this.regionNameStr = Bytes.toStringBinary(this.regionName);
225 setHashCode();
226 }
227
228
229
230
231 @Deprecated
232 public HRegionInfo() {
233 super();
234 }
235
236 public HRegionInfo(final TableName tableName) {
237 this(tableName, null, null);
238 }
239
240
241
242
243
244
245
246
247
248 public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey)
249 throws IllegalArgumentException {
250 this(tableName, startKey, endKey, false);
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264 public HRegionInfo(final TableName tableName, final byte[] startKey, final byte[] endKey,
265 final boolean split)
266 throws IllegalArgumentException {
267 this(tableName, startKey, endKey, split, System.currentTimeMillis());
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282 public HRegionInfo(final TableName tableName, final byte[] startKey,
283 final byte[] endKey, final boolean split, final long regionid)
284 throws IllegalArgumentException {
285
286 super();
287 if (tableName == null) {
288 throw new IllegalArgumentException("TableName cannot be null");
289 }
290 this.tableName = tableName;
291 this.offLine = false;
292 this.regionId = regionid;
293
294 this.regionName = createRegionName(this.tableName, startKey, regionId, true);
295
296 this.regionNameStr = Bytes.toStringBinary(this.regionName);
297 this.split = split;
298 this.endKey = endKey == null? HConstants.EMPTY_END_ROW: endKey.clone();
299 this.startKey = startKey == null?
300 HConstants.EMPTY_START_ROW: startKey.clone();
301 this.tableName = tableName;
302 setHashCode();
303 }
304
305
306
307
308
309
310 public HRegionInfo(HRegionInfo other) {
311 super();
312 this.endKey = other.getEndKey();
313 this.offLine = other.isOffline();
314 this.regionId = other.getRegionId();
315 this.regionName = other.getRegionName();
316 this.regionNameStr = Bytes.toStringBinary(this.regionName);
317 this.split = other.isSplit();
318 this.startKey = other.getStartKey();
319 this.hashCode = other.hashCode();
320 this.encodedName = other.getEncodedName();
321 this.tableName = other.tableName;
322 }
323
324
325
326
327
328
329
330
331
332
333
334 public static byte [] createRegionName(final TableName tableName,
335 final byte [] startKey, final long regionid, boolean newFormat) {
336 return createRegionName(tableName, startKey, Long.toString(regionid), newFormat);
337 }
338
339
340
341
342
343
344
345
346
347
348 public static byte [] createRegionName(final TableName tableName,
349 final byte [] startKey, final String id, boolean newFormat) {
350 return createRegionName(tableName, startKey, Bytes.toBytes(id), newFormat);
351 }
352
353
354
355
356
357
358
359
360
361
362 public static byte [] createRegionName(final TableName tableName,
363 final byte [] startKey, final byte [] id, boolean newFormat) {
364 byte [] b = new byte [tableName.getName().length + 2 + id.length +
365 (startKey == null? 0: startKey.length) +
366 (newFormat ? (MD5_HEX_LENGTH + 2) : 0)];
367
368 int offset = tableName.getName().length;
369 System.arraycopy(tableName.getName(), 0, b, 0, offset);
370 b[offset++] = HConstants.DELIMITER;
371 if (startKey != null && startKey.length > 0) {
372 System.arraycopy(startKey, 0, b, offset, startKey.length);
373 offset += startKey.length;
374 }
375 b[offset++] = HConstants.DELIMITER;
376 System.arraycopy(id, 0, b, offset, id.length);
377 offset += id.length;
378
379 if (newFormat) {
380
381
382
383
384
385
386
387 String md5Hash = MD5Hash.getMD5AsHex(b, 0, offset);
388 byte [] md5HashBytes = Bytes.toBytes(md5Hash);
389
390 if (md5HashBytes.length != MD5_HEX_LENGTH) {
391 LOG.error("MD5-hash length mismatch: Expected=" + MD5_HEX_LENGTH +
392 "; Got=" + md5HashBytes.length);
393 }
394
395
396 b[offset++] = ENC_SEPARATOR;
397 System.arraycopy(md5HashBytes, 0, b, offset, MD5_HEX_LENGTH);
398 offset += MD5_HEX_LENGTH;
399 b[offset++] = ENC_SEPARATOR;
400 }
401
402 return b;
403 }
404
405
406
407
408
409
410 public static TableName getTableName(byte[] regionName) {
411 int offset = -1;
412 for (int i = 0; i < regionName.length; i++) {
413 if (regionName[i] == HConstants.DELIMITER) {
414 offset = i;
415 break;
416 }
417 }
418 byte[] buff = new byte[offset];
419 System.arraycopy(regionName, 0, buff, 0, offset);
420 return TableName.valueOf(buff);
421 }
422
423
424
425
426
427
428 public static byte[] getStartKey(final byte[] regionName) throws IOException {
429 return parseRegionName(regionName)[1];
430 }
431
432
433
434
435
436
437
438 public static byte [][] parseRegionName(final byte [] regionName)
439 throws IOException {
440 int offset = -1;
441 for (int i = 0; i < regionName.length; i++) {
442 if (regionName[i] == HConstants.DELIMITER) {
443 offset = i;
444 break;
445 }
446 }
447 if(offset == -1) throw new IOException("Invalid regionName format");
448 byte[] tableName = new byte[offset];
449 System.arraycopy(regionName, 0, tableName, 0, offset);
450 offset = -1;
451 for (int i = regionName.length - 1; i > 0; i--) {
452 if(regionName[i] == HConstants.DELIMITER) {
453 offset = i;
454 break;
455 }
456 }
457 if(offset == -1) throw new IOException("Invalid regionName format");
458 byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
459 if(offset != tableName.length + 1) {
460 startKey = new byte[offset - tableName.length - 1];
461 System.arraycopy(regionName, tableName.length + 1, startKey, 0,
462 offset - tableName.length - 1);
463 }
464 byte [] id = new byte[regionName.length - offset - 1];
465 System.arraycopy(regionName, offset + 1, id, 0,
466 regionName.length - offset - 1);
467 byte [][] elements = new byte[3][];
468 elements[0] = tableName;
469 elements[1] = startKey;
470 elements[2] = id;
471 return elements;
472 }
473
474
475 public long getRegionId(){
476 return regionId;
477 }
478
479
480
481
482
483 public byte [] getRegionName(){
484 return regionName;
485 }
486
487
488
489
490 public String getRegionNameAsString() {
491 if (hasEncodedName(this.regionName)) {
492
493 return this.regionNameStr;
494 }
495
496
497
498
499 return this.regionNameStr + "." + this.getEncodedName();
500 }
501
502
503 public synchronized String getEncodedName() {
504 if (this.encodedName == NO_HASH) {
505 this.encodedName = encodeRegionName(this.regionName);
506 }
507 return this.encodedName;
508 }
509
510 public synchronized byte [] getEncodedNameAsBytes() {
511 if (this.encodedNameAsBytes == null) {
512 this.encodedNameAsBytes = Bytes.toBytes(getEncodedName());
513 }
514 return this.encodedNameAsBytes;
515 }
516
517
518 public byte [] getStartKey(){
519 return startKey;
520 }
521
522
523 public byte [] getEndKey(){
524 return endKey;
525 }
526
527
528
529
530
531 public TableName getTableName() {
532 if (tableName == null || tableName.getName().length == 0) {
533 tableName = getTableName(getRegionName());
534 }
535 return 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 tableName.equals(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 "{ENCODED => " + getEncodedName() + ", " +
628 HConstants.NAME + " => '" + this.regionNameStr
629 + "', STARTKEY => '" +
630 Bytes.toStringBinary(this.startKey) + "', ENDKEY => '" +
631 Bytes.toStringBinary(this.endKey) + "'" +
632 (isOffline()? ", OFFLINE => true": "") +
633 (isSplit()? ", SPLIT => true": "") + "}";
634 }
635
636
637
638
639 @Override
640 public boolean equals(Object o) {
641 if (this == o) {
642 return true;
643 }
644 if (o == null) {
645 return false;
646 }
647 if (!(o instanceof HRegionInfo)) {
648 return false;
649 }
650 return this.compareTo((HRegionInfo)o) == 0;
651 }
652
653
654
655
656 @Override
657 public int hashCode() {
658 return this.hashCode;
659 }
660
661
662
663 @Deprecated
664 public byte getVersion() {
665 return VERSION;
666 }
667
668
669
670
671
672 @Deprecated
673 public void write(DataOutput out) throws IOException {
674 out.writeByte(getVersion());
675 Bytes.writeByteArray(out, endKey);
676 out.writeBoolean(offLine);
677 out.writeLong(regionId);
678 Bytes.writeByteArray(out, regionName);
679 out.writeBoolean(split);
680 Bytes.writeByteArray(out, startKey);
681 Bytes.writeByteArray(out, tableName.getName());
682 out.writeInt(hashCode);
683 }
684
685
686
687
688
689 @Deprecated
690 public void readFields(DataInput in) throws IOException {
691
692
693
694 byte version = in.readByte();
695 if (version == 0) {
696
697
698 this.endKey = Bytes.readByteArray(in);
699 this.offLine = in.readBoolean();
700 this.regionId = in.readLong();
701 this.regionName = Bytes.readByteArray(in);
702 this.regionNameStr = Bytes.toStringBinary(this.regionName);
703 this.split = in.readBoolean();
704 this.startKey = Bytes.readByteArray(in);
705 try {
706 HTableDescriptor htd = new HTableDescriptor();
707 htd.readFields(in);
708 this.tableName = htd.getTableName();
709 } catch(EOFException eofe) {
710 throw new IOException("HTD not found in input buffer", eofe);
711 }
712 this.hashCode = in.readInt();
713 } else if (getVersion() == version) {
714 this.endKey = Bytes.readByteArray(in);
715 this.offLine = in.readBoolean();
716 this.regionId = in.readLong();
717 this.regionName = Bytes.readByteArray(in);
718 this.regionNameStr = Bytes.toStringBinary(this.regionName);
719 this.split = in.readBoolean();
720 this.startKey = Bytes.readByteArray(in);
721 this.tableName = TableName.valueOf(Bytes.readByteArray(in));
722 this.hashCode = in.readInt();
723 } else {
724 throw new IOException("Non-migratable/unknown version=" + getVersion());
725 }
726 }
727
728 @Deprecated
729 private void readFields(byte[] bytes) throws IOException {
730 if (bytes == null || bytes.length <= 0) {
731 throw new IllegalArgumentException("Can't build a writable with empty " +
732 "bytes array");
733 }
734 DataInputBuffer in = new DataInputBuffer();
735 try {
736 in.reset(bytes, 0, bytes.length);
737 this.readFields(in);
738 } finally {
739 in.close();
740 }
741 }
742
743
744
745
746
747 public int compareTo(HRegionInfo o) {
748 if (o == null) {
749 return 1;
750 }
751
752
753 int result = this.tableName.compareTo(o.tableName);
754 if (result != 0) {
755 return result;
756 }
757
758
759 result = Bytes.compareTo(this.startKey, o.startKey);
760 if (result != 0) {
761 return result;
762 }
763
764
765 result = Bytes.compareTo(this.endKey, o.endKey);
766
767 if (result != 0) {
768 if (this.getStartKey().length != 0
769 && this.getEndKey().length == 0) {
770 return 1;
771 }
772 if (o.getStartKey().length != 0
773 && o.getEndKey().length == 0) {
774 return -1;
775 }
776 return result;
777 }
778
779
780
781 if (this.regionId > o.regionId) {
782 return 1;
783 } else if (this.regionId < o.regionId) {
784 return -1;
785 }
786
787 if (this.offLine == o.offLine)
788 return 0;
789 if (this.offLine == true) return -1;
790
791 return 1;
792 }
793
794
795
796
797 public KVComparator getComparator() {
798 return isMetaRegion()?
799 KeyValue.META_COMPARATOR: KeyValue.COMPARATOR;
800 }
801
802
803
804
805
806
807 RegionInfo convert() {
808 return convert(this);
809 }
810
811
812
813
814
815
816
817 public static RegionInfo convert(final HRegionInfo info) {
818 if (info == null) return null;
819 RegionInfo.Builder builder = RegionInfo.newBuilder();
820 builder.setTableName(ProtobufUtil.toProtoTableName(info.getTableName()));
821 builder.setRegionId(info.getRegionId());
822 if (info.getStartKey() != null) {
823 builder.setStartKey(ByteString.copyFrom(info.getStartKey()));
824 }
825 if (info.getEndKey() != null) {
826 builder.setEndKey(ByteString.copyFrom(info.getEndKey()));
827 }
828 builder.setOffline(info.isOffline());
829 builder.setSplit(info.isSplit());
830 return builder.build();
831 }
832
833
834
835
836
837
838
839 public static HRegionInfo convert(final RegionInfo proto) {
840 if (proto == null) return null;
841 TableName tableName =
842 ProtobufUtil.toTableName(proto.getTableName());
843 if (tableName.equals(TableName.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(
860 tableName,
861 startKey,
862 endKey, split, regionId);
863 if (proto.hasOffline()) {
864 hri.setOffline(proto.getOffline());
865 }
866 return hri;
867 }
868
869
870
871
872
873 public byte [] toByteArray() {
874 byte [] bytes = convert().toByteArray();
875 return ProtobufUtil.prependPBMagic(bytes);
876 }
877
878
879
880
881
882
883 public static HRegionInfo parseFromOrNull(final byte [] bytes) {
884 if (bytes == null || bytes.length <= 0) return null;
885 try {
886 return parseFrom(bytes);
887 } catch (DeserializationException e) {
888 return null;
889 }
890 }
891
892
893
894
895
896
897
898 public static HRegionInfo parseFrom(final byte [] bytes) throws DeserializationException {
899 if (ProtobufUtil.isPBMagicPrefix(bytes)) {
900 int pblen = ProtobufUtil.lengthOfPBMagic();
901 try {
902 HBaseProtos.RegionInfo ri =
903 HBaseProtos.RegionInfo.newBuilder().mergeFrom(bytes, pblen, bytes.length - pblen).build();
904 return convert(ri);
905 } catch (InvalidProtocolBufferException e) {
906 throw new DeserializationException(e);
907 }
908 } else {
909 try {
910 HRegionInfo hri = new HRegionInfo();
911 hri.readFields(bytes);
912 return hri;
913 } catch (IOException e) {
914 throw new DeserializationException(e);
915 }
916 }
917 }
918
919
920
921
922
923
924
925
926 public byte [] toDelimitedByteArray() throws IOException {
927 return ProtobufUtil.toDelimitedByteArray(convert());
928 }
929
930
931
932
933
934
935
936
937 public static Pair<HRegionInfo, ServerName> getHRegionInfoAndServerName(final Result r) {
938 HRegionInfo info =
939 getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER);
940 ServerName sn = getServerName(r);
941 return new Pair<HRegionInfo, ServerName>(info, sn);
942 }
943
944
945
946
947
948
949
950
951 public static HRegionInfo getHRegionInfo(Result data) {
952 byte [] bytes =
953 data.getValue(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
954 if (bytes == null) return null;
955 HRegionInfo info = parseFromOrNull(bytes);
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 }