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