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