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