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