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