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