View Javadoc

1   /**
2    * Copyright 2009 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase;
21  
22  import java.io.DataInput;
23  import java.io.DataOutput;
24  import java.io.IOException;
25  import java.nio.ByteBuffer;
26  import java.util.Comparator;
27  import java.util.HashMap;
28  import java.util.Map;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.hadoop.hbase.io.HeapSize;
33  import org.apache.hadoop.hbase.io.hfile.HFile;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.apache.hadoop.hbase.util.ClassSize;
36  import org.apache.hadoop.io.RawComparator;
37  import org.apache.hadoop.io.Writable;
38  
39  import com.google.common.primitives.Longs;
40  
41  /**
42   * An HBase Key/Value.  This is the fundamental HBase Type.
43   *
44   * <p>If being used client-side, the primary methods to access individual fields
45   * are {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()},
46   * {@link #getTimestamp()}, and {@link #getValue()}.  These methods allocate new
47   * byte arrays and return copies. Avoid their use server-side.
48   *
49   * <p>Instances of this class are immutable.  They do not implement Comparable
50   * but Comparators are provided.  Comparators change with context,
51   * whether user table or a catalog table comparison.  Its critical you use the
52   * appropriate comparator.  There are Comparators for KeyValue instances and
53   * then for just the Key portion of a KeyValue used mostly by {@link HFile}.
54   *
55   * <p>KeyValue wraps a byte array and takes offsets and lengths into passed
56   * array at where to start interpreting the content as KeyValue.  The KeyValue
57   * format inside a byte array is:
58   * <code>&lt;keylength> &lt;valuelength> &lt;key> &lt;value></code>
59   * Key is further decomposed as:
60   * <code>&lt;rowlength> &lt;row> &lt;columnfamilylength> &lt;columnfamily> &lt;columnqualifier> &lt;timestamp> &lt;keytype></code>
61   * The <code>rowlength</code> maximum is <code>Short.MAX_SIZE</code>,
62   * column family length maximum is
63   * <code>Byte.MAX_SIZE</code>, and column qualifier + key length must
64   * be < <code>Integer.MAX_SIZE</code>.
65   * The column does not contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}
66   */
67  public class KeyValue implements Writable, HeapSize {
68    static final Log LOG = LogFactory.getLog(KeyValue.class);
69    // TODO: Group Key-only comparators and operations into a Key class, just
70    // for neatness sake, if can figure what to call it.
71  
72    /**
73     * Colon character in UTF-8
74     */
75    public static final char COLUMN_FAMILY_DELIMITER = ':';
76  
77    public static final byte[] COLUMN_FAMILY_DELIM_ARRAY =
78      new byte[]{COLUMN_FAMILY_DELIMITER};
79  
80    /**
81     * Comparator for plain key/values; i.e. non-catalog table key/values.
82     */
83    public static KVComparator COMPARATOR = new KVComparator();
84  
85    /**
86     * Comparator for plain key; i.e. non-catalog table key.  Works on Key portion
87     * of KeyValue only.
88     */
89    public static KeyComparator KEY_COMPARATOR = new KeyComparator();
90  
91    /**
92     * A {@link KVComparator} for <code>.META.</code> catalog table
93     * {@link KeyValue}s.
94     */
95    public static KVComparator META_COMPARATOR = new MetaComparator();
96  
97    /**
98     * A {@link KVComparator} for <code>.META.</code> catalog table
99     * {@link KeyValue} keys.
100    */
101   public static KeyComparator META_KEY_COMPARATOR = new MetaKeyComparator();
102 
103   /**
104    * A {@link KVComparator} for <code>-ROOT-</code> catalog table
105    * {@link KeyValue}s.
106    */
107   public static KVComparator ROOT_COMPARATOR = new RootComparator();
108 
109   /**
110    * A {@link KVComparator} for <code>-ROOT-</code> catalog table
111    * {@link KeyValue} keys.
112    */
113   public static KeyComparator ROOT_KEY_COMPARATOR = new RootKeyComparator();
114 
115   /**
116    * Get the appropriate row comparator for the specified table.
117    *
118    * Hopefully we can get rid of this, I added this here because it's replacing
119    * something in HSK.  We should move completely off of that.
120    *
121    * @param tableName  The table name.
122    * @return The comparator.
123    */
124   public static KeyComparator getRowComparator(byte [] tableName) {
125     if(Bytes.equals(HTableDescriptor.ROOT_TABLEDESC.getName(),tableName)) {
126       return ROOT_COMPARATOR.getRawComparator();
127     }
128     if(Bytes.equals(HTableDescriptor.META_TABLEDESC.getName(), tableName)) {
129       return META_COMPARATOR.getRawComparator();
130     }
131     return COMPARATOR.getRawComparator();
132   }
133 
134   /** Size of the key length field in bytes*/
135   public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT;
136 
137   /** Size of the key type field in bytes */
138   public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE;
139 
140   /** Size of the row length field in bytes */
141   public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
142 
143   /** Size of the family length field in bytes */
144   public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
145 
146   /** Size of the timestamp field in bytes */
147   public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG;
148 
149   // Size of the timestamp and type byte on end of a key -- a long + a byte.
150   public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE;
151 
152   // Size of the length shorts and bytes in key.
153   public static final int KEY_INFRASTRUCTURE_SIZE = ROW_LENGTH_SIZE
154       + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE;
155 
156   // How far into the key the row starts at. First thing to read is the short
157   // that says how long the row is.
158   public static final int ROW_OFFSET =
159     Bytes.SIZEOF_INT /*keylength*/ +
160     Bytes.SIZEOF_INT /*valuelength*/;
161 
162   // Size of the length ints in a KeyValue datastructure.
163   public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET;
164 
165   /**
166    * Key type.
167    * Has space for other key types to be added later.  Cannot rely on
168    * enum ordinals . They change if item is removed or moved.  Do our own codes.
169    */
170   public static enum Type {
171     Minimum((byte)0),
172     Put((byte)4),
173 
174     Delete((byte)8),
175     DeleteColumn((byte)12),
176     DeleteFamily((byte)14),
177 
178     // Maximum is used when searching; you look from maximum on down.
179     Maximum((byte)255);
180 
181     private final byte code;
182 
183     Type(final byte c) {
184       this.code = c;
185     }
186 
187     public byte getCode() {
188       return this.code;
189     }
190 
191     /**
192      * Cannot rely on enum ordinals . They change if item is removed or moved.
193      * Do our own codes.
194      * @param b
195      * @return Type associated with passed code.
196      */
197     public static Type codeToType(final byte b) {
198       for (Type t : Type.values()) {
199         if (t.getCode() == b) {
200           return t;
201         }
202       }
203       throw new RuntimeException("Unknown code " + b);
204     }
205   }
206 
207   /**
208    * Lowest possible key.
209    * Makes a Key with highest possible Timestamp, empty row and column.  No
210    * key can be equal or lower than this one in memstore or in store file.
211    */
212   public static final KeyValue LOWESTKEY =
213     new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP);
214 
215   private byte [] bytes = null;
216   private int offset = 0;
217   private int length = 0;
218 
219   /**
220    * @return True if a delete type, a {@link KeyValue.Type#Delete} or
221    * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
222    * KeyValue type.
223    */
224   public static boolean isDelete(byte t) {
225     return Type.Delete.getCode() <= t && t <= Type.DeleteFamily.getCode();
226   }
227 
228   /** Here be dragons **/
229 
230   // used to achieve atomic operations in the memstore.
231   public long getMemstoreTS() {
232     return memstoreTS;
233   }
234 
235   public void setMemstoreTS(long memstoreTS) {
236     this.memstoreTS = memstoreTS;
237   }
238 
239   // default value is 0, aka DNC
240   private long memstoreTS = 0;
241 
242   /** Dragon time over, return to normal business */
243 
244 
245   /** Writable Constructor -- DO NOT USE */
246   public KeyValue() {}
247 
248   /**
249    * Creates a KeyValue from the start of the specified byte array.
250    * Presumes <code>bytes</code> content is formatted as a KeyValue blob.
251    * @param bytes byte array
252    */
253   public KeyValue(final byte [] bytes) {
254     this(bytes, 0);
255   }
256 
257   /**
258    * Creates a KeyValue from the specified byte array and offset.
259    * Presumes <code>bytes</code> content starting at <code>offset</code> is
260    * formatted as a KeyValue blob.
261    * @param bytes byte array
262    * @param offset offset to start of KeyValue
263    */
264   public KeyValue(final byte [] bytes, final int offset) {
265     this(bytes, offset, getLength(bytes, offset));
266   }
267 
268   /**
269    * Creates a KeyValue from the specified byte array, starting at offset, and
270    * for length <code>length</code>.
271    * @param bytes byte array
272    * @param offset offset to start of the KeyValue
273    * @param length length of the KeyValue
274    */
275   public KeyValue(final byte [] bytes, final int offset, final int length) {
276     this.bytes = bytes;
277     this.offset = offset;
278     this.length = length;
279   }
280 
281   /**
282    * Creates a KeyValue from the specified byte array, starting at offset,
283    * for length <code>length</code>, and a known <code>keyLength</code>.
284    * @param bytes byte array
285    * @param offset offset to start of the KeyValue
286    * @param length length of the KeyValue
287    * @param keyLength length of the key portion of the KeyValue
288    */
289   public KeyValue(final byte [] bytes, final int offset, final int length, final int keyLength) {
290     this.bytes = bytes;
291     this.offset = offset;
292     this.length = length;
293     this.keyLength = keyLength;
294   }
295 
296   /** Constructors that build a new backing byte array from fields */
297 
298   /**
299    * Constructs KeyValue structure filled with null value.
300    * Sets type to {@link KeyValue.Type#Maximum}
301    * @param row - row key (arbitrary byte array)
302    * @param timestamp
303    */
304   public KeyValue(final byte [] row, final long timestamp) {
305     this(row, timestamp, Type.Maximum);
306   }
307 
308   /**
309    * Constructs KeyValue structure filled with null value.
310    * @param row - row key (arbitrary byte array)
311    * @param timestamp
312    */
313   public KeyValue(final byte [] row, final long timestamp, Type type) {
314     this(row, null, null, timestamp, type, null);
315   }
316 
317   /**
318    * Constructs KeyValue structure filled with null value.
319    * Sets type to {@link KeyValue.Type#Maximum}
320    * @param row - row key (arbitrary byte array)
321    * @param family family name
322    * @param qualifier column qualifier
323    */
324   public KeyValue(final byte [] row, final byte [] family,
325       final byte [] qualifier) {
326     this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
327   }
328 
329   /**
330    * Constructs KeyValue structure filled with null value.
331    * @param row - row key (arbitrary byte array)
332    * @param family family name
333    * @param qualifier column qualifier
334    */
335   public KeyValue(final byte [] row, final byte [] family,
336       final byte [] qualifier, final byte [] value) {
337     this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value);
338   }
339 
340   /**
341    * Constructs KeyValue structure filled with specified values.
342    * @param row row key
343    * @param family family name
344    * @param qualifier column qualifier
345    * @param timestamp version timestamp
346    * @param type key type
347    * @throws IllegalArgumentException
348    */
349   public KeyValue(final byte[] row, final byte[] family,
350       final byte[] qualifier, final long timestamp, Type type) {
351     this(row, family, qualifier, timestamp, type, null);
352   }
353 
354   /**
355    * Constructs KeyValue structure filled with specified values.
356    * @param row row key
357    * @param family family name
358    * @param qualifier column qualifier
359    * @param timestamp version timestamp
360    * @param value column value
361    * @throws IllegalArgumentException
362    */
363   public KeyValue(final byte[] row, final byte[] family,
364       final byte[] qualifier, final long timestamp, final byte[] value) {
365     this(row, family, qualifier, timestamp, Type.Put, value);
366   }
367 
368   /**
369    * Constructs KeyValue structure filled with specified values.
370    * @param row row key
371    * @param family family name
372    * @param qualifier column qualifier
373    * @param timestamp version timestamp
374    * @param type key type
375    * @param value column value
376    * @throws IllegalArgumentException
377    */
378   public KeyValue(final byte[] row, final byte[] family,
379       final byte[] qualifier, final long timestamp, Type type,
380       final byte[] value) {
381     this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length,
382         timestamp, type, value, 0, value==null ? 0 : value.length);
383   }
384 
385   /**
386    * Constructs KeyValue structure filled with specified values.
387    * @param row row key
388    * @param family family name
389    * @param qualifier column qualifier
390    * @param qoffset qualifier offset
391    * @param qlength qualifier length
392    * @param timestamp version timestamp
393    * @param type key type
394    * @param value column value
395    * @param voffset value offset
396    * @param vlength value length
397    * @throws IllegalArgumentException
398    */
399   public KeyValue(byte [] row, byte [] family,
400       byte [] qualifier, int qoffset, int qlength, long timestamp, Type type,
401       byte [] value, int voffset, int vlength) {
402     this(row, 0, row==null ? 0 : row.length,
403         family, 0, family==null ? 0 : family.length,
404         qualifier, qoffset, qlength, timestamp, type,
405         value, voffset, vlength);
406   }
407 
408   /**
409    * Constructs KeyValue structure filled with specified values.
410    * <p>
411    * Column is split into two fields, family and qualifier.
412    * @param row row key
413    * @param roffset row offset
414    * @param rlength row length
415    * @param family family name
416    * @param foffset family offset
417    * @param flength family length
418    * @param qualifier column qualifier
419    * @param qoffset qualifier offset
420    * @param qlength qualifier length
421    * @param timestamp version timestamp
422    * @param type key type
423    * @param value column value
424    * @param voffset value offset
425    * @param vlength value length
426    * @throws IllegalArgumentException
427    */
428   public KeyValue(final byte [] row, final int roffset, final int rlength,
429       final byte [] family, final int foffset, final int flength,
430       final byte [] qualifier, final int qoffset, final int qlength,
431       final long timestamp, final Type type,
432       final byte [] value, final int voffset, final int vlength) {
433     this.bytes = createByteArray(row, roffset, rlength,
434         family, foffset, flength, qualifier, qoffset, qlength,
435         timestamp, type, value, voffset, vlength);
436     this.length = bytes.length;
437     this.offset = 0;
438   }
439 
440   /**
441    * Constructs an empty KeyValue structure, with specified sizes.
442    * This can be used to partially fill up KeyValues.
443    * <p>
444    * Column is split into two fields, family and qualifier.
445    * @param rlength row length
446    * @param flength family length
447    * @param qlength qualifier length
448    * @param timestamp version timestamp
449    * @param type key type
450    * @param vlength value length
451    * @throws IllegalArgumentException
452    */
453   public KeyValue(final int rlength,
454       final int flength,
455       final int qlength,
456       final long timestamp, final Type type,
457       final int vlength) {
458     this.bytes = createEmptyByteArray(rlength,
459         flength, qlength,
460         timestamp, type, vlength);
461     this.length = bytes.length;
462     this.offset = 0;
463   }
464 
465   /**
466    * Create an empty byte[] representing a KeyValue
467    * All lengths are preset and can be filled in later.
468    * @param rlength
469    * @param flength
470    * @param qlength
471    * @param timestamp
472    * @param type
473    * @param vlength
474    * @return The newly created byte array.
475    */
476   static byte[] createEmptyByteArray(final int rlength, int flength,
477       int qlength, final long timestamp, final Type type, int vlength) {
478     if (rlength > Short.MAX_VALUE) {
479       throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
480     }
481     if (flength > Byte.MAX_VALUE) {
482       throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
483     }
484     // Qualifier length
485     if (qlength > Integer.MAX_VALUE - rlength - flength) {
486       throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
487     }
488     // Key length
489     long longkeylength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
490     if (longkeylength > Integer.MAX_VALUE) {
491       throw new IllegalArgumentException("keylength " + longkeylength + " > " +
492         Integer.MAX_VALUE);
493     }
494     int keylength = (int)longkeylength;
495     // Value length
496     if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
497       throw new IllegalArgumentException("Valuer > " +
498           HConstants.MAXIMUM_VALUE_LENGTH);
499     }
500 
501     // Allocate right-sized byte array.
502     byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength];
503     // Write the correct size markers
504     int pos = 0;
505     pos = Bytes.putInt(bytes, pos, keylength);
506     pos = Bytes.putInt(bytes, pos, vlength);
507     pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
508     pos += rlength;
509     pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
510     pos += flength + qlength;
511     pos = Bytes.putLong(bytes, pos, timestamp);
512     pos = Bytes.putByte(bytes, pos, type.getCode());
513     return bytes;
514   }
515 
516   /**
517    * Write KeyValue format into a byte array.
518    *
519    * @param row row key
520    * @param roffset row offset
521    * @param rlength row length
522    * @param family family name
523    * @param foffset family offset
524    * @param flength family length
525    * @param qualifier column qualifier
526    * @param qoffset qualifier offset
527    * @param qlength qualifier length
528    * @param timestamp version timestamp
529    * @param type key type
530    * @param value column value
531    * @param voffset value offset
532    * @param vlength value length
533    * @return The newly created byte array.
534    */
535   static byte [] createByteArray(final byte [] row, final int roffset,
536       final int rlength, final byte [] family, final int foffset, int flength,
537       final byte [] qualifier, final int qoffset, int qlength,
538       final long timestamp, final Type type,
539       final byte [] value, final int voffset, int vlength) {
540     if (rlength > Short.MAX_VALUE) {
541       throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
542     }
543     if (row == null) {
544       throw new IllegalArgumentException("Row is null");
545     }
546     // Family length
547     flength = family == null ? 0 : flength;
548     if (flength > Byte.MAX_VALUE) {
549       throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
550     }
551     // Qualifier length
552     qlength = qualifier == null ? 0 : qlength;
553     if (qlength > Integer.MAX_VALUE - rlength - flength) {
554       throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
555     }
556     // Key length
557     long longkeylength = KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
558     if (longkeylength > Integer.MAX_VALUE) {
559       throw new IllegalArgumentException("keylength " + longkeylength + " > " +
560         Integer.MAX_VALUE);
561     }
562     int keylength = (int)longkeylength;
563     // Value length
564     vlength = value == null? 0 : vlength;
565     if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
566       throw new IllegalArgumentException("Valuer > " +
567           HConstants.MAXIMUM_VALUE_LENGTH);
568     }
569 
570     // Allocate right-sized byte array.
571     byte [] bytes = new byte[KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength];
572     // Write key, value and key row length.
573     int pos = 0;
574     pos = Bytes.putInt(bytes, pos, keylength);
575     pos = Bytes.putInt(bytes, pos, vlength);
576     pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
577     pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
578     pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
579     if(flength != 0) {
580       pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
581     }
582     if(qlength != 0) {
583       pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength);
584     }
585     pos = Bytes.putLong(bytes, pos, timestamp);
586     pos = Bytes.putByte(bytes, pos, type.getCode());
587     if (value != null && value.length > 0) {
588       pos = Bytes.putBytes(bytes, pos, value, voffset, vlength);
589     }
590     return bytes;
591   }
592 
593   /**
594    * Write KeyValue format into a byte array.
595    * <p>
596    * Takes column in the form <code>family:qualifier</code>
597    * @param row - row key (arbitrary byte array)
598    * @param roffset
599    * @param rlength
600    * @param column
601    * @param coffset
602    * @param clength
603    * @param timestamp
604    * @param type
605    * @param value
606    * @param voffset
607    * @param vlength
608    * @return The newly created byte array.
609    */
610   static byte [] createByteArray(final byte [] row, final int roffset,
611         final int rlength,
612       final byte [] column, final int coffset, int clength,
613       final long timestamp, final Type type,
614       final byte [] value, final int voffset, int vlength) {
615     // If column is non-null, figure where the delimiter is at.
616     int delimiteroffset = 0;
617     if (column != null && column.length > 0) {
618       delimiteroffset = getFamilyDelimiterIndex(column, coffset, clength);
619       if (delimiteroffset > Byte.MAX_VALUE) {
620         throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
621       }
622     } else {
623       return createByteArray(row,roffset,rlength,null,0,0,null,0,0,timestamp,
624           type,value,voffset,vlength);
625     }
626     int flength = delimiteroffset-coffset;
627     int qlength = clength - flength - 1;
628     return createByteArray(row, roffset, rlength, column, coffset,
629         flength, column, delimiteroffset+1, qlength, timestamp, type,
630         value, voffset, vlength);
631   }
632 
633   // Needed doing 'contains' on List.  Only compares the key portion, not the
634   // value.
635   public boolean equals(Object other) {
636     if (!(other instanceof KeyValue)) {
637       return false;
638     }
639     KeyValue kv = (KeyValue)other;
640     // Comparing bytes should be fine doing equals test.  Shouldn't have to
641     // worry about special .META. comparators doing straight equals.
642     return Bytes.equals(getBuffer(), getKeyOffset(), getKeyLength(),
643       kv.getBuffer(), kv.getKeyOffset(), kv.getKeyLength());
644   }
645 
646   public int hashCode() {
647     byte[] b = getBuffer();
648     int start = getOffset(), end = getOffset() + getLength();
649     int h = b[start++];
650     for (int i = start; i < end; i++) {
651       h = (h * 13) ^ b[i];
652     }
653     return h;
654   }
655 
656   //---------------------------------------------------------------------------
657   //
658   //  KeyValue cloning
659   //
660   //---------------------------------------------------------------------------
661 
662   /**
663    * Clones a KeyValue.  This creates a copy, re-allocating the buffer.
664    * @return Fully copied clone of this KeyValue
665    */
666   public KeyValue clone() {
667     byte [] b = new byte[this.length];
668     System.arraycopy(this.bytes, this.offset, b, 0, this.length);
669     KeyValue ret = new KeyValue(b, 0, b.length);
670     // Important to clone the memstoreTS as well - otherwise memstore's
671     // update-in-place methods (eg increment) will end up creating
672     // new entries
673     ret.setMemstoreTS(memstoreTS);
674     return ret;
675   }
676 
677   /**
678    * Creates a deep copy of this KeyValue, re-allocating the buffer.
679    * Same function as {@link #clone()}.  Added for clarity vs shallowCopy()
680    * @return Deep copy of this KeyValue
681    */
682   public KeyValue deepCopy() {
683     return clone();
684   }
685 
686   /**
687    * Creates a shallow copy of this KeyValue, reusing the data byte buffer.
688    * http://en.wikipedia.org/wiki/Object_copy
689    * @return Shallow copy of this KeyValue
690    */
691   public KeyValue shallowCopy() {
692     KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length);
693     shallowCopy.setMemstoreTS(this.memstoreTS);
694     return shallowCopy;
695   }
696 
697   //---------------------------------------------------------------------------
698   //
699   //  String representation
700   //
701   //---------------------------------------------------------------------------
702 
703   public String toString() {
704     if (this.bytes == null || this.bytes.length == 0) {
705       return "empty";
706     }
707     return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) +
708       "/vlen=" + getValueLength() + "/ts=" + memstoreTS;
709   }
710 
711   /**
712    * @param k Key portion of a KeyValue.
713    * @return Key as a String.
714    */
715   public static String keyToString(final byte [] k) {
716     if (k == null) {
717       return "";
718     }
719     return keyToString(k, 0, k.length);
720   }
721 
722   /**
723    * Use for logging.
724    * @param b Key portion of a KeyValue.
725    * @param o Offset to start of key
726    * @param l Length of key.
727    * @return Key as a String.
728    */
729   /**
730    * Produces a string map for this key/value pair. Useful for programmatic use
731    * and manipulation of the data stored in an HLogKey, for example, printing
732    * as JSON. Values are left out due to their tendency to be large. If needed,
733    * they can be added manually.
734    *
735    * @return the Map<String,?> containing data from this key
736    */
737   public Map<String, Object> toStringMap() {
738     Map<String, Object> stringMap = new HashMap<String, Object>();
739     stringMap.put("row", Bytes.toStringBinary(getRow()));
740     stringMap.put("family", Bytes.toStringBinary(getFamily()));
741     stringMap.put("qualifier", Bytes.toStringBinary(getQualifier()));
742     stringMap.put("timestamp", getTimestamp());
743     stringMap.put("vlen", getValueLength());
744     return stringMap;
745   }
746 
747   public static String keyToString(final byte [] b, final int o, final int l) {
748     if (b == null) return "";
749     int rowlength = Bytes.toShort(b, o);
750     String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
751     int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
752     int familylength = b[columnoffset - 1];
753     int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
754     String family = familylength == 0? "":
755       Bytes.toStringBinary(b, columnoffset, familylength);
756     String qualifier = columnlength == 0? "":
757       Bytes.toStringBinary(b, columnoffset + familylength,
758       columnlength - familylength);
759     long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
760     String timestampStr = humanReadableTimestamp(timestamp);
761     byte type = b[o + l - 1];
762     return row + "/" + family +
763       (family != null && family.length() > 0? ":" :"") +
764       qualifier + "/" + timestampStr + "/" + Type.codeToType(type);
765   }
766 
767   public static String humanReadableTimestamp(final long timestamp) {
768     if (timestamp == HConstants.LATEST_TIMESTAMP) {
769       return "LATEST_TIMESTAMP";
770     }
771     if (timestamp == HConstants.OLDEST_TIMESTAMP) {
772       return "OLDEST_TIMESTAMP";
773     }
774     return String.valueOf(timestamp);
775   }
776 
777   //---------------------------------------------------------------------------
778   //
779   //  Public Member Accessors
780   //
781   //---------------------------------------------------------------------------
782 
783   /**
784    * @return The byte array backing this KeyValue.
785    */
786   public byte [] getBuffer() {
787     return this.bytes;
788   }
789 
790   /**
791    * @return Offset into {@link #getBuffer()} at which this KeyValue starts.
792    */
793   public int getOffset() {
794     return this.offset;
795   }
796 
797   /**
798    * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}.
799    */
800   public int getLength() {
801     return length;
802   }
803 
804   //---------------------------------------------------------------------------
805   //
806   //  Length and Offset Calculators
807   //
808   //---------------------------------------------------------------------------
809 
810   /**
811    * Determines the total length of the KeyValue stored in the specified
812    * byte array and offset.  Includes all headers.
813    * @param bytes byte array
814    * @param offset offset to start of the KeyValue
815    * @return length of entire KeyValue, in bytes
816    */
817   private static int getLength(byte [] bytes, int offset) {
818     return ROW_OFFSET +
819         Bytes.toInt(bytes, offset) +
820         Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
821   }
822 
823   /**
824    * @return Key offset in backing buffer..
825    */
826   public int getKeyOffset() {
827     return this.offset + ROW_OFFSET;
828   }
829 
830   public String getKeyString() {
831     return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
832   }
833 
834   /**
835    * @return Length of key portion.
836    */
837   private int keyLength = 0;
838 
839   public int getKeyLength() {
840     if (keyLength == 0) {
841       keyLength = Bytes.toInt(this.bytes, this.offset);
842     }
843     return keyLength;
844   }
845 
846   /**
847    * @return Value offset
848    */
849   public int getValueOffset() {
850     return getKeyOffset() + getKeyLength();
851   }
852 
853   /**
854    * @return Value length
855    */
856   public int getValueLength() {
857     return Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
858   }
859 
860   /**
861    * @return Row offset
862    */
863   public int getRowOffset() {
864     return getKeyOffset() + Bytes.SIZEOF_SHORT;
865   }
866 
867   /**
868    * @return Row length
869    */
870   public short getRowLength() {
871     return Bytes.toShort(this.bytes, getKeyOffset());
872   }
873 
874   /**
875    * @return Family offset
876    */
877   public int getFamilyOffset() {
878     return getFamilyOffset(getRowLength());
879   }
880 
881   /**
882    * @return Family offset
883    */
884   public int getFamilyOffset(int rlength) {
885     return this.offset + ROW_OFFSET + Bytes.SIZEOF_SHORT + rlength + Bytes.SIZEOF_BYTE;
886   }
887 
888   /**
889    * @return Family length
890    */
891   public byte getFamilyLength() {
892     return getFamilyLength(getFamilyOffset());
893   }
894 
895   /**
896    * @return Family length
897    */
898   public byte getFamilyLength(int foffset) {
899     return this.bytes[foffset-1];
900   }
901 
902   /**
903    * @return Qualifier offset
904    */
905   public int getQualifierOffset() {
906     return getQualifierOffset(getFamilyOffset());
907   }
908 
909   /**
910    * @return Qualifier offset
911    */
912   public int getQualifierOffset(int foffset) {
913     return foffset + getFamilyLength(foffset);
914   }
915 
916   /**
917    * @return Qualifier length
918    */
919   public int getQualifierLength() {
920     return getQualifierLength(getRowLength(),getFamilyLength());
921   }
922 
923   /**
924    * @return Qualifier length
925    */
926   public int getQualifierLength(int rlength, int flength) {
927     return getKeyLength() -
928       (KEY_INFRASTRUCTURE_SIZE + rlength + flength);
929   }
930 
931   /**
932    * @return Column (family + qualifier) length
933    */
934   public int getTotalColumnLength() {
935     int rlength = getRowLength();
936     int foffset = getFamilyOffset(rlength);
937     return getTotalColumnLength(rlength,foffset);
938   }
939 
940   /**
941    * @return Column (family + qualifier) length
942    */
943   public int getTotalColumnLength(int rlength, int foffset) {
944     int flength = getFamilyLength(foffset);
945     int qlength = getQualifierLength(rlength,flength);
946     return flength + qlength;
947   }
948 
949   /**
950    * @return Timestamp offset
951    */
952   public int getTimestampOffset() {
953     return getTimestampOffset(getKeyLength());
954   }
955 
956   /**
957    * @param keylength Pass if you have it to save on a int creation.
958    * @return Timestamp offset
959    */
960   public int getTimestampOffset(final int keylength) {
961     return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
962   }
963 
964   /**
965    * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp.
966    */
967   public boolean isLatestTimestamp() {
968     return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
969       HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
970   }
971 
972   /**
973    * @return True if this is a "fake" KV created for internal seeking purposes,
974    * which should not be seen by user code
975    */
976   public boolean isInternal() {
977     byte type = getType();
978     return type == Type.Minimum.code || type == Type.Maximum.code;
979   }
980   /**
981    * @param now Time to set into <code>this</code> IFF timestamp ==
982    * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
983    * @return True is we modified this.
984    */
985   public boolean updateLatestStamp(final byte [] now) {
986     if (this.isLatestTimestamp()) {
987       int tsOffset = getTimestampOffset();
988       System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
989       // clear cache or else getTimestamp() possibly returns an old value
990       return true;
991     }
992     return false;
993   }
994 
995   //---------------------------------------------------------------------------
996   //
997   //  Methods that return copies of fields
998   //
999   //---------------------------------------------------------------------------
1000 
1001   /**
1002    * Do not use unless you have to.  Used internally for compacting and testing.
1003    *
1004    * Use {@link #getRow()}, {@link #getFamily()}, {@link #getQualifier()}, and
1005    * {@link #getValue()} if accessing a KeyValue client-side.
1006    * @return Copy of the key portion only.
1007    */
1008   public byte [] getKey() {
1009     int keylength = getKeyLength();
1010     byte [] key = new byte[keylength];
1011     System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
1012     return key;
1013   }
1014 
1015   /**
1016    * Returns value in a new byte array.
1017    * Primarily for use client-side. If server-side, use
1018    * {@link #getBuffer()} with appropriate offsets and lengths instead to
1019    * save on allocations.
1020    * @return Value in a new byte array.
1021    */
1022   public byte [] getValue() {
1023     int o = getValueOffset();
1024     int l = getValueLength();
1025     byte [] result = new byte[l];
1026     System.arraycopy(getBuffer(), o, result, 0, l);
1027     return result;
1028   }
1029 
1030   /**
1031    * Primarily for use client-side.  Returns the row of this KeyValue in a new
1032    * byte array.<p>
1033    *
1034    * If server-side, use {@link #getBuffer()} with appropriate offsets and
1035    * lengths instead.
1036    * @return Row in a new byte array.
1037    */
1038   public byte [] getRow() {
1039     int o = getRowOffset();
1040     short l = getRowLength();
1041     byte result[] = new byte[l];
1042     System.arraycopy(getBuffer(), o, result, 0, l);
1043     return result;
1044   }
1045 
1046   /**
1047    *
1048    * @return Timestamp
1049    */
1050   public long getTimestamp() {
1051     return getTimestamp(getKeyLength());
1052   }
1053 
1054   /**
1055    * @param keylength Pass if you have it to save on a int creation.
1056    * @return Timestamp
1057    */
1058   long getTimestamp(final int keylength) {
1059     int tsOffset = getTimestampOffset(keylength);
1060     return Bytes.toLong(this.bytes, tsOffset);
1061   }
1062 
1063   /**
1064    * @return Type of this KeyValue.
1065    */
1066   public byte getType() {
1067     return getType(getKeyLength());
1068   }
1069 
1070   /**
1071    * @param keylength Pass if you have it to save on a int creation.
1072    * @return Type of this KeyValue.
1073    */
1074   byte getType(final int keylength) {
1075     return this.bytes[this.offset + keylength - 1 + ROW_OFFSET];
1076   }
1077 
1078   /**
1079    * @return True if a delete type, a {@link KeyValue.Type#Delete} or
1080    * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
1081    * KeyValue type.
1082    */
1083   public boolean isDelete() {
1084     return KeyValue.isDelete(getType());
1085   }
1086 
1087   /**
1088    * @return True if this KV is a {@link KeyValue.Type#Delete} type.
1089    */
1090   public boolean isDeleteType() {
1091     // TODO: Fix this method name vis-a-vis isDelete!
1092     return getType() == Type.Delete.getCode();
1093   }
1094 
1095   /**
1096    * @return True if this KV is a delete family type.
1097    */
1098   public boolean isDeleteFamily() {
1099     return getType() == Type.DeleteFamily.getCode();
1100   }
1101 
1102   /**
1103    *
1104    * @return True if this KV is a delete family or column type.
1105    */
1106   public boolean isDeleteColumnOrFamily() {
1107     int t = getType();
1108     return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
1109   }
1110 
1111   /**
1112    * Primarily for use client-side.  Returns the family of this KeyValue in a
1113    * new byte array.<p>
1114    *
1115    * If server-side, use {@link #getBuffer()} with appropriate offsets and
1116    * lengths instead.
1117    * @return Returns family. Makes a copy.
1118    */
1119   public byte [] getFamily() {
1120     int o = getFamilyOffset();
1121     int l = getFamilyLength(o);
1122     byte [] result = new byte[l];
1123     System.arraycopy(this.bytes, o, result, 0, l);
1124     return result;
1125   }
1126 
1127   /**
1128    * Primarily for use client-side.  Returns the column qualifier of this
1129    * KeyValue in a new byte array.<p>
1130    *
1131    * If server-side, use {@link #getBuffer()} with appropriate offsets and
1132    * lengths instead.
1133    * Use {@link #getBuffer()} with appropriate offsets and lengths instead.
1134    * @return Returns qualifier. Makes a copy.
1135    */
1136   public byte [] getQualifier() {
1137     int o = getQualifierOffset();
1138     int l = getQualifierLength();
1139     byte [] result = new byte[l];
1140     System.arraycopy(this.bytes, o, result, 0, l);
1141     return result;
1142   }
1143 
1144   //---------------------------------------------------------------------------
1145   //
1146   //  KeyValue splitter
1147   //
1148   //---------------------------------------------------------------------------
1149 
1150   /**
1151    * Utility class that splits a KeyValue buffer into separate byte arrays.
1152    * <p>
1153    * Should get rid of this if we can, but is very useful for debugging.
1154    */
1155   public static class SplitKeyValue {
1156     private byte [][] split;
1157     SplitKeyValue() {
1158       this.split = new byte[6][];
1159     }
1160     public void setRow(byte [] value) { this.split[0] = value; }
1161     public void setFamily(byte [] value) { this.split[1] = value; }
1162     public void setQualifier(byte [] value) { this.split[2] = value; }
1163     public void setTimestamp(byte [] value) { this.split[3] = value; }
1164     public void setType(byte [] value) { this.split[4] = value; }
1165     public void setValue(byte [] value) { this.split[5] = value; }
1166     public byte [] getRow() { return this.split[0]; }
1167     public byte [] getFamily() { return this.split[1]; }
1168     public byte [] getQualifier() { return this.split[2]; }
1169     public byte [] getTimestamp() { return this.split[3]; }
1170     public byte [] getType() { return this.split[4]; }
1171     public byte [] getValue() { return this.split[5]; }
1172   }
1173 
1174   public SplitKeyValue split() {
1175     SplitKeyValue split = new SplitKeyValue();
1176     int splitOffset = this.offset;
1177     int keyLen = Bytes.toInt(bytes, splitOffset);
1178     splitOffset += Bytes.SIZEOF_INT;
1179     int valLen = Bytes.toInt(bytes, splitOffset);
1180     splitOffset += Bytes.SIZEOF_INT;
1181     short rowLen = Bytes.toShort(bytes, splitOffset);
1182     splitOffset += Bytes.SIZEOF_SHORT;
1183     byte [] row = new byte[rowLen];
1184     System.arraycopy(bytes, splitOffset, row, 0, rowLen);
1185     splitOffset += rowLen;
1186     split.setRow(row);
1187     byte famLen = bytes[splitOffset];
1188     splitOffset += Bytes.SIZEOF_BYTE;
1189     byte [] family = new byte[famLen];
1190     System.arraycopy(bytes, splitOffset, family, 0, famLen);
1191     splitOffset += famLen;
1192     split.setFamily(family);
1193     int colLen = keyLen -
1194       (rowLen + famLen + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE +
1195       Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE);
1196     byte [] qualifier = new byte[colLen];
1197     System.arraycopy(bytes, splitOffset, qualifier, 0, colLen);
1198     splitOffset += colLen;
1199     split.setQualifier(qualifier);
1200     byte [] timestamp = new byte[Bytes.SIZEOF_LONG];
1201     System.arraycopy(bytes, splitOffset, timestamp, 0, Bytes.SIZEOF_LONG);
1202     splitOffset += Bytes.SIZEOF_LONG;
1203     split.setTimestamp(timestamp);
1204     byte [] type = new byte[1];
1205     type[0] = bytes[splitOffset];
1206     splitOffset += Bytes.SIZEOF_BYTE;
1207     split.setType(type);
1208     byte [] value = new byte[valLen];
1209     System.arraycopy(bytes, splitOffset, value, 0, valLen);
1210     split.setValue(value);
1211     return split;
1212   }
1213 
1214   //---------------------------------------------------------------------------
1215   //
1216   //  Compare specified fields against those contained in this KeyValue
1217   //
1218   //---------------------------------------------------------------------------
1219 
1220   /**
1221    * @param family
1222    * @return True if matching families.
1223    */
1224   public boolean matchingFamily(final byte [] family) {
1225     return matchingFamily(family, 0, family.length);
1226   }
1227 
1228   public boolean matchingFamily(final byte[] family, int offset, int length) {
1229     if (this.length == 0 || this.bytes.length == 0) {
1230       return false;
1231     }
1232     return Bytes.equals(family, offset, length,
1233         this.bytes, getFamilyOffset(), getFamilyLength());
1234   }
1235 
1236   public boolean matchingFamily(final KeyValue other) {
1237     return matchingFamily(other.getBuffer(), other.getFamilyOffset(),
1238         other.getFamilyLength());
1239   }
1240 
1241   /**
1242    * @param qualifier
1243    * @return True if matching qualifiers.
1244    */
1245   public boolean matchingQualifier(final byte [] qualifier) {
1246     return matchingQualifier(qualifier, 0, qualifier.length);
1247   }
1248 
1249   public boolean matchingQualifier(final byte [] qualifier, int offset, int length) {
1250     return Bytes.equals(qualifier, offset, length,
1251         this.bytes, getQualifierOffset(), getQualifierLength());
1252   }
1253 
1254   public boolean matchingQualifier(final KeyValue other) {
1255     return matchingQualifier(other.getBuffer(), other.getQualifierOffset(),
1256         other.getQualifierLength());
1257   }
1258 
1259   public boolean matchingRow(final byte [] row) {
1260     return matchingRow(row, 0, row.length);
1261   }
1262 
1263   public boolean matchingRow(final byte[] row, int offset, int length) {
1264     return Bytes.equals(row, offset, length,
1265         this.bytes, getRowOffset(), getRowLength());
1266   }
1267 
1268   public boolean matchingRow(KeyValue other) {
1269     return matchingRow(other.getBuffer(), other.getRowOffset(),
1270         other.getRowLength());
1271   }
1272 
1273   /**
1274    * @param column Column minus its delimiter
1275    * @return True if column matches.
1276    */
1277   public boolean matchingColumnNoDelimiter(final byte [] column) {
1278     int rl = getRowLength();
1279     int o = getFamilyOffset(rl);
1280     int fl = getFamilyLength(o);
1281     int l = fl + getQualifierLength(rl,fl);
1282     return Bytes.equals(column, 0, column.length, this.bytes, o, l);
1283   }
1284 
1285   /**
1286    *
1287    * @param family column family
1288    * @param qualifier column qualifier
1289    * @return True if column matches
1290    */
1291   public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
1292     int rl = getRowLength();
1293     int o = getFamilyOffset(rl);
1294     int fl = getFamilyLength(o);
1295     int ql = getQualifierLength(rl,fl);
1296     if (!Bytes.equals(family, 0, family.length, this.bytes, o, fl)) {
1297       return false;
1298     }
1299     if (qualifier == null || qualifier.length == 0) {
1300       if (ql == 0) {
1301         return true;
1302       }
1303       return false;
1304     }
1305     return Bytes.equals(qualifier, 0, qualifier.length,
1306         this.bytes, o + fl, ql);
1307   }
1308 
1309   /**
1310    * @param left
1311    * @param loffset
1312    * @param llength
1313    * @param lfamilylength Offset of family delimiter in left column.
1314    * @param right
1315    * @param roffset
1316    * @param rlength
1317    * @param rfamilylength Offset of family delimiter in right column.
1318    * @return The result of the comparison.
1319    */
1320   static int compareColumns(final byte [] left, final int loffset,
1321       final int llength, final int lfamilylength,
1322       final byte [] right, final int roffset, final int rlength,
1323       final int rfamilylength) {
1324     // Compare family portion first.
1325     int diff = Bytes.compareTo(left, loffset, lfamilylength,
1326       right, roffset, rfamilylength);
1327     if (diff != 0) {
1328       return diff;
1329     }
1330     // Compare qualifier portion
1331     return Bytes.compareTo(left, loffset + lfamilylength,
1332       llength - lfamilylength,
1333       right, roffset + rfamilylength, rlength - rfamilylength);
1334   }
1335 
1336   /**
1337    * @return True if non-null row and column.
1338    */
1339   public boolean nonNullRowAndColumn() {
1340     return getRowLength() > 0 && !isEmptyColumn();
1341   }
1342 
1343   /**
1344    * @return True if column is empty.
1345    */
1346   public boolean isEmptyColumn() {
1347     return getQualifierLength() == 0;
1348   }
1349 
1350   /**
1351    * Creates a new KeyValue that only contains the key portion (the value is
1352    * set to be null).
1353    * @param lenAsVal replace value with the actual value length (false=empty)
1354    */
1355   public KeyValue createKeyOnly(boolean lenAsVal) {
1356     // KV format:  <keylen:4><valuelen:4><key:keylen><value:valuelen>
1357     // Rebuild as: <keylen:4><0:4><key:keylen>
1358     int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0;
1359     byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1360     System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1361         Math.min(newBuffer.length,this.length));
1362     Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1363     if (lenAsVal) {
1364       Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1365     }
1366     return new KeyValue(newBuffer);
1367   }
1368 
1369   /**
1370    * Splits a column in family:qualifier form into separate byte arrays.
1371    * <p>
1372    * Not recommend to be used as this is old-style API.
1373    * @param c  The column.
1374    * @return The parsed column.
1375    */
1376   public static byte [][] parseColumn(byte [] c) {
1377     final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER);
1378     if (index == -1) {
1379       // If no delimiter, return array of size 1
1380       return new byte [][] { c };
1381     } else if(index == c.length - 1) {
1382       // Only a family, return array size 1
1383       byte [] family = new byte[c.length-1];
1384       System.arraycopy(c, 0, family, 0, family.length);
1385       return new byte [][] { family };
1386     }
1387     // Family and column, return array size 2
1388     final byte [][] result = new byte [2][];
1389     result[0] = new byte [index];
1390     System.arraycopy(c, 0, result[0], 0, index);
1391     final int len = c.length - (index + 1);
1392     result[1] = new byte[len];
1393     System.arraycopy(c, index + 1 /*Skip delimiter*/, result[1], 0,
1394       len);
1395     return result;
1396   }
1397 
1398   /**
1399    * Makes a column in family:qualifier form from separate byte arrays.
1400    * <p>
1401    * Not recommended for usage as this is old-style API.
1402    * @param family
1403    * @param qualifier
1404    * @return family:qualifier
1405    */
1406   public static byte [] makeColumn(byte [] family, byte [] qualifier) {
1407     return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier);
1408   }
1409 
1410   /**
1411    * @param b
1412    * @return Index of the family-qualifier colon delimiter character in passed
1413    * buffer.
1414    */
1415   public static int getFamilyDelimiterIndex(final byte [] b, final int offset,
1416       final int length) {
1417     return getRequiredDelimiter(b, offset, length, COLUMN_FAMILY_DELIMITER);
1418   }
1419 
1420   private static int getRequiredDelimiter(final byte [] b,
1421       final int offset, final int length, final int delimiter) {
1422     int index = getDelimiter(b, offset, length, delimiter);
1423     if (index < 0) {
1424       throw new IllegalArgumentException("No " + (char)delimiter + " in <" +
1425         Bytes.toString(b) + ">" + ", length=" + length + ", offset=" + offset);
1426     }
1427     return index;
1428   }
1429 
1430   /**
1431    * This function is only used in Meta key comparisons so its error message
1432    * is specific for meta key errors.
1433    */
1434   static int getRequiredDelimiterInReverse(final byte [] b,
1435       final int offset, final int length, final int delimiter) {
1436     int index = getDelimiterInReverse(b, offset, length, delimiter);
1437     if (index < 0) {
1438       throw new IllegalArgumentException(".META. key must have two '" + (char)delimiter + "' "
1439         + "delimiters and have the following format: '<table>,<key>,<etc>'");
1440     }
1441     return index;
1442   }
1443 
1444   /**
1445    * @param b
1446    * @param delimiter
1447    * @return Index of delimiter having started from start of <code>b</code>
1448    * moving rightward.
1449    */
1450   public static int getDelimiter(final byte [] b, int offset, final int length,
1451       final int delimiter) {
1452     if (b == null) {
1453       throw new IllegalArgumentException("Passed buffer is null");
1454     }
1455     int result = -1;
1456     for (int i = offset; i < length + offset; i++) {
1457       if (b[i] == delimiter) {
1458         result = i;
1459         break;
1460       }
1461     }
1462     return result;
1463   }
1464 
1465   /**
1466    * Find index of passed delimiter walking from end of buffer backwards.
1467    * @param b
1468    * @param delimiter
1469    * @return Index of delimiter
1470    */
1471   public static int getDelimiterInReverse(final byte [] b, final int offset,
1472       final int length, final int delimiter) {
1473     if (b == null) {
1474       throw new IllegalArgumentException("Passed buffer is null");
1475     }
1476     int result = -1;
1477     for (int i = (offset + length) - 1; i >= offset; i--) {
1478       if (b[i] == delimiter) {
1479         result = i;
1480         break;
1481       }
1482     }
1483     return result;
1484   }
1485 
1486   /**
1487    * A {@link KVComparator} for <code>-ROOT-</code> catalog table
1488    * {@link KeyValue}s.
1489    */
1490   public static class RootComparator extends MetaComparator {
1491     private final KeyComparator rawcomparator = new RootKeyComparator();
1492 
1493     public KeyComparator getRawComparator() {
1494       return this.rawcomparator;
1495     }
1496 
1497     @Override
1498     protected Object clone() throws CloneNotSupportedException {
1499       return new RootComparator();
1500     }
1501   }
1502 
1503   /**
1504    * A {@link KVComparator} for <code>.META.</code> catalog table
1505    * {@link KeyValue}s.
1506    */
1507   public static class MetaComparator extends KVComparator {
1508     private final KeyComparator rawcomparator = new MetaKeyComparator();
1509 
1510     public KeyComparator getRawComparator() {
1511       return this.rawcomparator;
1512     }
1513 
1514     @Override
1515     protected Object clone() throws CloneNotSupportedException {
1516       return new MetaComparator();
1517     }
1518   }
1519 
1520   /**
1521    * Compare KeyValues.  When we compare KeyValues, we only compare the Key
1522    * portion.  This means two KeyValues with same Key but different Values are
1523    * considered the same as far as this Comparator is concerned.
1524    * Hosts a {@link KeyComparator}.
1525    */
1526   public static class KVComparator implements java.util.Comparator<KeyValue> {
1527     private final KeyComparator rawcomparator = new KeyComparator();
1528 
1529     /**
1530      * @return RawComparator that can compare the Key portion of a KeyValue.
1531      * Used in hfile where indices are the Key portion of a KeyValue.
1532      */
1533     public KeyComparator getRawComparator() {
1534       return this.rawcomparator;
1535     }
1536 
1537     public int compare(final KeyValue left, final KeyValue right) {
1538       int ret = getRawComparator().compare(left.getBuffer(),
1539           left.getOffset() + ROW_OFFSET, left.getKeyLength(),
1540           right.getBuffer(), right.getOffset() + ROW_OFFSET,
1541           right.getKeyLength());
1542       if (ret != 0) return ret;
1543       // Negate this comparison so later edits show up first
1544       return -Longs.compare(left.getMemstoreTS(), right.getMemstoreTS());
1545     }
1546 
1547     public int compareTimestamps(final KeyValue left, final KeyValue right) {
1548       return compareTimestamps(left, left.getKeyLength(), right,
1549         right.getKeyLength());
1550     }
1551 
1552     int compareTimestamps(final KeyValue left, final int lkeylength,
1553         final KeyValue right, final int rkeylength) {
1554       // Compare timestamps
1555       long ltimestamp = left.getTimestamp(lkeylength);
1556       long rtimestamp = right.getTimestamp(rkeylength);
1557       return getRawComparator().compareTimestamps(ltimestamp, rtimestamp);
1558     }
1559 
1560     /**
1561      * @param left
1562      * @param right
1563      * @return Result comparing rows.
1564      */
1565     public int compareRows(final KeyValue left, final KeyValue right) {
1566       return compareRows(left, left.getRowLength(), right,
1567           right.getRowLength());
1568     }
1569 
1570     /**
1571      * @param left
1572      * @param lrowlength Length of left row.
1573      * @param right
1574      * @param rrowlength Length of right row.
1575      * @return Result comparing rows.
1576      */
1577     public int compareRows(final KeyValue left, final short lrowlength,
1578         final KeyValue right, final short rrowlength) {
1579       return getRawComparator().compareRows(left.getBuffer(),
1580           left.getRowOffset(), lrowlength,
1581         right.getBuffer(), right.getRowOffset(), rrowlength);
1582     }
1583 
1584     /**
1585      * @param left
1586      * @param row - row key (arbitrary byte array)
1587      * @return RawComparator
1588      */
1589     public int compareRows(final KeyValue left, final byte [] row) {
1590       return getRawComparator().compareRows(left.getBuffer(),
1591           left.getRowOffset(), left.getRowLength(), row, 0, row.length);
1592     }
1593 
1594     public int compareRows(byte [] left, int loffset, int llength,
1595         byte [] right, int roffset, int rlength) {
1596       return getRawComparator().compareRows(left, loffset, llength,
1597         right, roffset, rlength);
1598     }
1599 
1600     public int compareColumns(final KeyValue left, final byte [] right,
1601         final int roffset, final int rlength, final int rfamilyoffset) {
1602       int offset = left.getFamilyOffset();
1603       int length = left.getFamilyLength() + left.getQualifierLength();
1604       return getRawComparator().compareColumns(left.getBuffer(), offset, length,
1605         left.getFamilyLength(offset),
1606         right, roffset, rlength, rfamilyoffset);
1607     }
1608 
1609     int compareColumns(final KeyValue left, final short lrowlength,
1610         final KeyValue right, final short rrowlength) {
1611       int lfoffset = left.getFamilyOffset(lrowlength);
1612       int rfoffset = right.getFamilyOffset(rrowlength);
1613       int lclength = left.getTotalColumnLength(lrowlength,lfoffset);
1614       int rclength = right.getTotalColumnLength(rrowlength, rfoffset);
1615       int lfamilylength = left.getFamilyLength(lfoffset);
1616       int rfamilylength = right.getFamilyLength(rfoffset);
1617       return getRawComparator().compareColumns(left.getBuffer(), lfoffset,
1618           lclength, lfamilylength,
1619         right.getBuffer(), rfoffset, rclength, rfamilylength);
1620     }
1621 
1622     /**
1623      * Compares the row and column of two keyvalues for equality
1624      * @param left
1625      * @param right
1626      * @return True if same row and column.
1627      */
1628     public boolean matchingRowColumn(final KeyValue left,
1629         final KeyValue right) {
1630       short lrowlength = left.getRowLength();
1631       short rrowlength = right.getRowLength();
1632       // TsOffset = end of column data. just comparing Row+CF length of each
1633       return ((left.getTimestampOffset() - left.getOffset()) ==
1634               (right.getTimestampOffset() - right.getOffset())) &&
1635         matchingRows(left, lrowlength, right, rrowlength) &&
1636         compareColumns(left, lrowlength, right, rrowlength) == 0;
1637     }
1638 
1639     /**
1640      * @param left
1641      * @param right
1642      * @return True if rows match.
1643      */
1644     public boolean matchingRows(final KeyValue left, final byte [] right) {
1645       return Bytes.equals(left.getBuffer(), left.getRowOffset(), left.getRowLength(),
1646           right, 0, right.length);
1647     }
1648 
1649     /**
1650      * Compares the row of two keyvalues for equality
1651      * @param left
1652      * @param right
1653      * @return True if rows match.
1654      */
1655     public boolean matchingRows(final KeyValue left, final KeyValue right) {
1656       short lrowlength = left.getRowLength();
1657       short rrowlength = right.getRowLength();
1658       return matchingRows(left, lrowlength, right, rrowlength);
1659     }
1660 
1661     /**
1662      * @param left
1663      * @param lrowlength
1664      * @param right
1665      * @param rrowlength
1666      * @return True if rows match.
1667      */
1668     public boolean matchingRows(final KeyValue left, final short lrowlength,
1669         final KeyValue right, final short rrowlength) {
1670       return lrowlength == rrowlength &&
1671           Bytes.equals(left.getBuffer(), left.getRowOffset(), lrowlength,
1672               right.getBuffer(), right.getRowOffset(), rrowlength);
1673     }
1674 
1675     public boolean matchingRows(final byte [] left, final int loffset,
1676         final int llength,
1677         final byte [] right, final int roffset, final int rlength) {
1678       return Bytes.equals(left, loffset, llength,
1679           right, roffset, rlength);
1680     }
1681 
1682     /**
1683      * Compares the row and timestamp of two keys
1684      * Was called matchesWithoutColumn in HStoreKey.
1685      * @param right Key to compare against.
1686      * @return True if same row and timestamp is greater than the timestamp in
1687      * <code>right</code>
1688      */
1689     public boolean matchingRowsGreaterTimestamp(final KeyValue left,
1690         final KeyValue right) {
1691       short lrowlength = left.getRowLength();
1692       short rrowlength = right.getRowLength();
1693       if (!matchingRows(left, lrowlength, right, rrowlength)) {
1694         return false;
1695       }
1696       return left.getTimestamp() >= right.getTimestamp();
1697     }
1698 
1699     @Override
1700     protected Object clone() throws CloneNotSupportedException {
1701       return new KVComparator();
1702     }
1703 
1704     /**
1705      * @return Comparator that ignores timestamps; useful counting versions.
1706      */
1707     public KVComparator getComparatorIgnoringTimestamps() {
1708       KVComparator c = null;
1709       try {
1710         c = (KVComparator)this.clone();
1711         c.getRawComparator().ignoreTimestamp = true;
1712       } catch (CloneNotSupportedException e) {
1713         LOG.error("Not supported", e);
1714       }
1715       return c;
1716     }
1717 
1718     /**
1719      * @return Comparator that ignores key type; useful checking deletes
1720      */
1721     public KVComparator getComparatorIgnoringType() {
1722       KVComparator c = null;
1723       try {
1724         c = (KVComparator)this.clone();
1725         c.getRawComparator().ignoreType = true;
1726       } catch (CloneNotSupportedException e) {
1727         LOG.error("Not supported", e);
1728       }
1729       return c;
1730     }
1731   }
1732 
1733   /**
1734    * Creates a KeyValue that is last on the specified row id. That is,
1735    * every other possible KeyValue for the given row would compareTo()
1736    * less than the result of this call.
1737    * @param row row key
1738    * @return Last possible KeyValue on passed <code>row</code>
1739    */
1740   public static KeyValue createLastOnRow(final byte[] row) {
1741     return new KeyValue(row, null, null, HConstants.LATEST_TIMESTAMP, Type.Minimum);
1742   }
1743 
1744   /**
1745    * Create a KeyValue that is smaller than all other possible KeyValues
1746    * for the given row. That is any (valid) KeyValue on 'row' would sort
1747    * _after_ the result.
1748    *
1749    * @param row - row key (arbitrary byte array)
1750    * @return First possible KeyValue on passed <code>row</code>
1751    */
1752   public static KeyValue createFirstOnRow(final byte [] row) {
1753     return createFirstOnRow(row, HConstants.LATEST_TIMESTAMP);
1754   }
1755 
1756   /**
1757    * Create a KeyValue that is smaller than all other possible KeyValues
1758    * for the given row. That is any (valid) KeyValue on 'row' would sort
1759    * _after_ the result.
1760    *
1761    * @param row - row key (arbitrary byte array)
1762    * @return First possible KeyValue on passed <code>row</code>
1763    */
1764   public static KeyValue createFirstOnRow(final byte [] row, int roffset, short rlength) {
1765     return new KeyValue(row, roffset, rlength,
1766         null, 0, 0, null, 0, 0, HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1767   }
1768 
1769   /**
1770    * Creates a KeyValue that is smaller than all other KeyValues that
1771    * are older than the passed timestamp.
1772    * @param row - row key (arbitrary byte array)
1773    * @param ts - timestamp
1774    * @return First possible key on passed <code>row</code> and timestamp.
1775    */
1776   public static KeyValue createFirstOnRow(final byte [] row,
1777       final long ts) {
1778     return new KeyValue(row, null, null, ts, Type.Maximum);
1779   }
1780 
1781   /**
1782    * Create a KeyValue for the specified row, family and qualifier that would be
1783    * smaller than all other possible KeyValues that have the same row,family,qualifier.
1784    * Used for seeking.
1785    * @param row - row key (arbitrary byte array)
1786    * @param family - family name
1787    * @param qualifier - column qualifier
1788    * @return First possible key on passed <code>row</code>, and column.
1789    */
1790   public static KeyValue createFirstOnRow(final byte [] row, final byte [] family,
1791       final byte [] qualifier) {
1792     return new KeyValue(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
1793   }
1794 
1795   /**
1796    * Create a Delete Family KeyValue for the specified row and family that would
1797    * be smaller than all other possible Delete Family KeyValues that have the
1798    * same row and family.
1799    * Used for seeking.
1800    * @param row - row key (arbitrary byte array)
1801    * @param family - family name
1802    * @return First Delete Family possible key on passed <code>row</code>.
1803    */
1804   public static KeyValue createFirstDeleteFamilyOnRow(final byte [] row,
1805       final byte [] family) {
1806     return new KeyValue(row, family, null, HConstants.LATEST_TIMESTAMP,
1807         Type.DeleteFamily);
1808   }
1809 
1810   /**
1811    * @param row - row key (arbitrary byte array)
1812    * @param f - family name
1813    * @param q - column qualifier
1814    * @param ts - timestamp
1815    * @return First possible key on passed <code>row</code>, column and timestamp
1816    */
1817   public static KeyValue createFirstOnRow(final byte [] row, final byte [] f,
1818       final byte [] q, final long ts) {
1819     return new KeyValue(row, f, q, ts, Type.Maximum);
1820   }
1821 
1822   /**
1823    * Create a KeyValue for the specified row, family and qualifier that would be
1824    * smaller than all other possible KeyValues that have the same row,
1825    * family, qualifier.
1826    * Used for seeking.
1827    * @param row row key
1828    * @param roffset row offset
1829    * @param rlength row length
1830    * @param family family name
1831    * @param foffset family offset
1832    * @param flength family length
1833    * @param qualifier column qualifier
1834    * @param qoffset qualifier offset
1835    * @param qlength qualifier length
1836    * @return First possible key on passed Row, Family, Qualifier.
1837    */
1838   public static KeyValue createFirstOnRow(final byte [] row,
1839       final int roffset, final int rlength, final byte [] family,
1840       final int foffset, final int flength, final byte [] qualifier,
1841       final int qoffset, final int qlength) {
1842     return new KeyValue(row, roffset, rlength, family,
1843         foffset, flength, qualifier, qoffset, qlength,
1844         HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1845   }
1846 
1847   /**
1848    * Create a KeyValue for the specified row, family and qualifier that would be
1849    * larger than or equal to all other possible KeyValues that have the same
1850    * row, family, qualifier.
1851    * Used for reseeking.
1852    * @param row row key
1853    * @param roffset row offset
1854    * @param rlength row length
1855    * @param family family name
1856    * @param foffset family offset
1857    * @param flength family length
1858    * @param qualifier column qualifier
1859    * @param qoffset qualifier offset
1860    * @param qlength qualifier length
1861    * @return Last possible key on passed row, family, qualifier.
1862    */
1863   public static KeyValue createLastOnRow(final byte [] row,
1864       final int roffset, final int rlength, final byte [] family,
1865       final int foffset, final int flength, final byte [] qualifier,
1866       final int qoffset, final int qlength) {
1867     return new KeyValue(row, roffset, rlength, family,
1868         foffset, flength, qualifier, qoffset, qlength,
1869         HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
1870   }
1871 
1872   /**
1873    * Similar to {@link #createLastOnRow(byte[], int, int, byte[], int, int,
1874    * byte[], int, int)} but creates the last key on the row/column of this KV
1875    * (the value part of the returned KV is always empty). Used in creating
1876    * "fake keys" for the multi-column Bloom filter optimization to skip the
1877    * row/column we already know is not in the file.
1878    * @return the last key on the row/column of the given key-value pair
1879    */
1880   public KeyValue createLastOnRowCol() {
1881     return new KeyValue(
1882         bytes, getRowOffset(), getRowLength(),
1883         bytes, getFamilyOffset(), getFamilyLength(),
1884         bytes, getQualifierOffset(), getQualifierLength(),
1885         HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
1886   }
1887 
1888   /**
1889    * Creates the first KV with the row/family/qualifier of this KV and the
1890    * given timestamp. Uses the "maximum" KV type that guarantees that the new
1891    * KV is the lowest possible for this combination of row, family, qualifier,
1892    * and timestamp. This KV's own timestamp is ignored. While this function
1893    * copies the value from this KV, it is normally used on key-only KVs.
1894    */
1895   public KeyValue createFirstOnRowColTS(long ts) {
1896     return new KeyValue(
1897         bytes, getRowOffset(), getRowLength(),
1898         bytes, getFamilyOffset(), getFamilyLength(),
1899         bytes, getQualifierOffset(), getQualifierLength(),
1900         ts, Type.Maximum, bytes, getValueOffset(), getValueLength());
1901   }
1902 
1903   /**
1904    * @param b
1905    * @return A KeyValue made of a byte array that holds the key-only part.
1906    * Needed to convert hfile index members to KeyValues.
1907    */
1908   public static KeyValue createKeyValueFromKey(final byte [] b) {
1909     return createKeyValueFromKey(b, 0, b.length);
1910   }
1911 
1912   /**
1913    * @param bb
1914    * @return A KeyValue made of a byte buffer that holds the key-only part.
1915    * Needed to convert hfile index members to KeyValues.
1916    */
1917   public static KeyValue createKeyValueFromKey(final ByteBuffer bb) {
1918     return createKeyValueFromKey(bb.array(), bb.arrayOffset(), bb.limit());
1919   }
1920 
1921   /**
1922    * @param b
1923    * @param o
1924    * @param l
1925    * @return A KeyValue made of a byte array that holds the key-only part.
1926    * Needed to convert hfile index members to KeyValues.
1927    */
1928   public static KeyValue createKeyValueFromKey(final byte [] b, final int o,
1929       final int l) {
1930     byte [] newb = new byte[l + ROW_OFFSET];
1931     System.arraycopy(b, o, newb, ROW_OFFSET, l);
1932     Bytes.putInt(newb, 0, l);
1933     Bytes.putInt(newb, Bytes.SIZEOF_INT, 0);
1934     return new KeyValue(newb);
1935   }
1936 
1937   /**
1938    * Compare key portion of a {@link KeyValue} for keys in <code>-ROOT-<code>
1939    * table.
1940    */
1941   public static class RootKeyComparator extends MetaKeyComparator {
1942     public int compareRows(byte [] left, int loffset, int llength,
1943         byte [] right, int roffset, int rlength) {
1944       // Rows look like this: .META.,ROW_FROM_META,RID
1945       //        LOG.info("ROOT " + Bytes.toString(left, loffset, llength) +
1946       //          "---" + Bytes.toString(right, roffset, rlength));
1947       final int metalength = 7; // '.META.' length
1948       int lmetaOffsetPlusDelimiter = loffset + metalength;
1949       int leftFarDelimiter = getDelimiterInReverse(left,
1950           lmetaOffsetPlusDelimiter,
1951           llength - metalength, HRegionInfo.DELIMITER);
1952       int rmetaOffsetPlusDelimiter = roffset + metalength;
1953       int rightFarDelimiter = getDelimiterInReverse(right,
1954           rmetaOffsetPlusDelimiter, rlength - metalength,
1955           HRegionInfo.DELIMITER);
1956       if (leftFarDelimiter < 0 && rightFarDelimiter >= 0) {
1957         // Nothing between .META. and regionid.  Its first key.
1958         return -1;
1959       } else if (rightFarDelimiter < 0 && leftFarDelimiter >= 0) {
1960         return 1;
1961       } else if (leftFarDelimiter < 0 && rightFarDelimiter < 0) {
1962         return 0;
1963       }
1964       int result = super.compareRows(left, lmetaOffsetPlusDelimiter,
1965           leftFarDelimiter - lmetaOffsetPlusDelimiter,
1966           right, rmetaOffsetPlusDelimiter,
1967           rightFarDelimiter - rmetaOffsetPlusDelimiter);
1968       if (result != 0) {
1969         return result;
1970       }
1971       // Compare last part of row, the rowid.
1972       leftFarDelimiter++;
1973       rightFarDelimiter++;
1974       result = compareRowid(left, leftFarDelimiter,
1975           llength - (leftFarDelimiter - loffset),
1976           right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
1977       return result;
1978     }
1979   }
1980 
1981   /**
1982    * Comparator that compares row component only of a KeyValue.
1983    */
1984   public static class RowComparator implements Comparator<KeyValue> {
1985     final KVComparator comparator;
1986 
1987     public RowComparator(final KVComparator c) {
1988       this.comparator = c;
1989     }
1990 
1991     public int compare(KeyValue left, KeyValue right) {
1992       return comparator.compareRows(left, right);
1993     }
1994   }
1995 
1996   /**
1997    * Compare key portion of a {@link KeyValue} for keys in <code>.META.</code>
1998    * table.
1999    */
2000   public static class MetaKeyComparator extends KeyComparator {
2001     public int compareRows(byte [] left, int loffset, int llength,
2002         byte [] right, int roffset, int rlength) {
2003       //        LOG.info("META " + Bytes.toString(left, loffset, llength) +
2004       //          "---" + Bytes.toString(right, roffset, rlength));
2005       int leftDelimiter = getDelimiter(left, loffset, llength,
2006           HRegionInfo.DELIMITER);
2007       int rightDelimiter = getDelimiter(right, roffset, rlength,
2008           HRegionInfo.DELIMITER);
2009       if (leftDelimiter < 0 && rightDelimiter >= 0) {
2010         // Nothing between .META. and regionid.  Its first key.
2011         return -1;
2012       } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
2013         return 1;
2014       } else if (leftDelimiter < 0 && rightDelimiter < 0) {
2015         return 0;
2016       }
2017       // Compare up to the delimiter
2018       int result = Bytes.compareTo(left, loffset, leftDelimiter - loffset,
2019           right, roffset, rightDelimiter - roffset);
2020       if (result != 0) {
2021         return result;
2022       }
2023       // Compare middle bit of the row.
2024       // Move past delimiter
2025       leftDelimiter++;
2026       rightDelimiter++;
2027       int leftFarDelimiter = getRequiredDelimiterInReverse(left, leftDelimiter,
2028           llength - (leftDelimiter - loffset), HRegionInfo.DELIMITER);
2029       int rightFarDelimiter = getRequiredDelimiterInReverse(right,
2030           rightDelimiter, rlength - (rightDelimiter - roffset),
2031           HRegionInfo.DELIMITER);
2032       // Now compare middlesection of row.
2033       result = super.compareRows(left, leftDelimiter,
2034           leftFarDelimiter - leftDelimiter, right, rightDelimiter,
2035           rightFarDelimiter - rightDelimiter);
2036       if (result != 0) {
2037         return result;
2038       }
2039       // Compare last part of row, the rowid.
2040       leftFarDelimiter++;
2041       rightFarDelimiter++;
2042       result = compareRowid(left, leftFarDelimiter,
2043           llength - (leftFarDelimiter - loffset),
2044           right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
2045       return result;
2046     }
2047 
2048     protected int compareRowid(byte[] left, int loffset, int llength,
2049         byte[] right, int roffset, int rlength) {
2050       return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2051     }
2052   }
2053 
2054   /**
2055    * Avoids redundant comparisons for better performance.
2056    */
2057   public static interface SamePrefixComparator<T> {
2058     /**
2059      * Compare two keys assuming that the first n bytes are the same.
2060      * @param commonPrefix How many bytes are the same.
2061      */
2062     public int compareIgnoringPrefix(int commonPrefix,
2063         T left, int loffset, int llength,
2064         T right, int roffset, int rlength);
2065   }
2066 
2067   /**
2068    * Compare key portion of a {@link KeyValue}.
2069    */
2070   public static class KeyComparator
2071       implements RawComparator<byte []>, SamePrefixComparator<byte[]> {
2072     volatile boolean ignoreTimestamp = false;
2073     volatile boolean ignoreType = false;
2074 
2075     public int compare(byte[] left, int loffset, int llength, byte[] right,
2076         int roffset, int rlength) {
2077       // Compare row
2078       short lrowlength = Bytes.toShort(left, loffset);
2079       short rrowlength = Bytes.toShort(right, roffset);
2080       int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT,
2081           lrowlength, right, roffset + Bytes.SIZEOF_SHORT, rrowlength);
2082       if (compare != 0) {
2083         return compare;
2084       }
2085 
2086       // Compare the rest of the two KVs without making any assumptions about
2087       // the common prefix. This function will not compare rows anyway, so we
2088       // don't need to tell it that the common prefix includes the row.
2089       return compareWithoutRow(0, left, loffset, llength, right, roffset,
2090           rlength, rrowlength);
2091     }
2092 
2093     /**
2094      * Compare the two key-values, ignoring the prefix of the given length
2095      * that is known to be the same between the two.
2096      * @param commonPrefix the prefix length to ignore
2097      */
2098     @Override
2099     public int compareIgnoringPrefix(int commonPrefix, byte[] left,
2100         int loffset, int llength, byte[] right, int roffset, int rlength) {
2101       // Compare row
2102       short lrowlength = Bytes.toShort(left, loffset);
2103       short rrowlength;
2104 
2105       int comparisonResult = 0;
2106       if (commonPrefix < ROW_LENGTH_SIZE) {
2107         // almost nothing in common
2108         rrowlength = Bytes.toShort(right, roffset);
2109         comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE,
2110             lrowlength, right, roffset + ROW_LENGTH_SIZE, rrowlength);
2111       } else { // the row length is the same
2112         rrowlength = lrowlength;
2113         if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
2114           // The rows are not the same. Exclude the common prefix and compare
2115           // the rest of the two rows.
2116           int common = commonPrefix - ROW_LENGTH_SIZE;
2117           comparisonResult = compareRows(
2118               left, loffset + common + ROW_LENGTH_SIZE, lrowlength - common,
2119               right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
2120         }
2121       }
2122       if (comparisonResult != 0) {
2123         return comparisonResult;
2124       }
2125 
2126       assert lrowlength == rrowlength;
2127 
2128       return compareWithoutRow(commonPrefix, left, loffset, llength, right,
2129           roffset, rlength, lrowlength);
2130     }
2131 
2132     /**
2133      * Compare columnFamily, qualifier, timestamp, and key type (everything
2134      * except the row). This method is used both in the normal comparator and
2135      * the "same-prefix" comparator. Note that we are assuming that row portions
2136      * of both KVs have already been parsed and found identical, and we don't
2137      * validate that assumption here.
2138      * @param commonPrefix
2139      *          the length of the common prefix of the two key-values being
2140      *          compared, including row length and row
2141      */
2142     private int compareWithoutRow(int commonPrefix, byte[] left, int loffset,
2143         int llength, byte[] right, int roffset, int rlength, short rowlength) {
2144       /***
2145        * KeyValue Format and commonLength:
2146        * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
2147        * ------------------|-------commonLength--------|--------------
2148        */
2149       int commonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rowlength;
2150 
2151       // commonLength + TIMESTAMP_TYPE_SIZE
2152       int commonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + commonLength;
2153       // ColumnFamily + Qualifier length.
2154       int lcolumnlength = llength - commonLengthWithTSAndType;
2155       int rcolumnlength = rlength - commonLengthWithTSAndType;
2156 
2157       byte ltype = left[loffset + (llength - 1)];
2158       byte rtype = right[roffset + (rlength - 1)];
2159 
2160       // If the column is not specified, the "minimum" key type appears the
2161       // latest in the sorted order, regardless of the timestamp. This is used
2162       // for specifying the last key/value in a given row, because there is no
2163       // "lexicographically last column" (it would be infinitely long). The
2164       // "maximum" key type does not need this behavior.
2165       if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
2166         // left is "bigger", i.e. it appears later in the sorted order
2167         return 1;
2168       }
2169       if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
2170         return -1;
2171       }
2172 
2173       int lfamilyoffset = commonLength + loffset;
2174       int rfamilyoffset = commonLength + roffset;
2175 
2176       // Column family length.
2177       int lfamilylength = left[lfamilyoffset - 1];
2178       int rfamilylength = right[rfamilyoffset - 1];
2179       // If left family size is not equal to right family size, we need not
2180       // compare the qualifiers. 
2181       boolean sameFamilySize = (lfamilylength == rfamilylength);
2182       int common = 0;
2183       if (commonPrefix > 0) {
2184         common = Math.max(0, commonPrefix - commonLength);
2185         if (!sameFamilySize) {
2186           // Common should not be larger than Math.min(lfamilylength,
2187           // rfamilylength).
2188           common = Math.min(common, Math.min(lfamilylength, rfamilylength));
2189         } else {
2190           common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
2191         }
2192       }
2193       if (!sameFamilySize) {
2194         // comparing column family is enough.
2195         return Bytes.compareTo(left, lfamilyoffset + common, lfamilylength
2196             - common, right, rfamilyoffset + common, rfamilylength - common);
2197       }
2198       // Compare family & qualifier together.
2199       final int comparison = Bytes.compareTo(left, lfamilyoffset + common,
2200           lcolumnlength - common, right, rfamilyoffset + common,
2201           rcolumnlength - common);
2202       if (comparison != 0) {
2203         return comparison;
2204       }
2205       return compareTimestampAndType(left, loffset, llength, right, roffset,
2206           rlength, ltype, rtype);
2207     }
2208 
2209     private int compareTimestampAndType(byte[] left, int loffset, int llength,
2210         byte[] right, int roffset, int rlength, byte ltype, byte rtype) {
2211       int compare;
2212       if (!this.ignoreTimestamp) {
2213         // Get timestamps.
2214         long ltimestamp = Bytes.toLong(left,
2215             loffset + (llength - TIMESTAMP_TYPE_SIZE));
2216         long rtimestamp = Bytes.toLong(right,
2217             roffset + (rlength - TIMESTAMP_TYPE_SIZE));
2218         compare = compareTimestamps(ltimestamp, rtimestamp);
2219         if (compare != 0) {
2220           return compare;
2221         }
2222       }
2223 
2224       if (!this.ignoreType) {
2225         // Compare types. Let the delete types sort ahead of puts; i.e. types
2226         // of higher numbers sort before those of lesser numbers. Maximum (255)
2227         // appears ahead of everything, and minimum (0) appears after
2228         // everything.
2229         return (0xff & rtype) - (0xff & ltype);
2230       }
2231       return 0;
2232     }
2233 
2234     public int compare(byte[] left, byte[] right) {
2235       return compare(left, 0, left.length, right, 0, right.length);
2236     }
2237 
2238     public int compareRows(byte [] left, int loffset, int llength,
2239         byte [] right, int roffset, int rlength) {
2240       return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2241     }
2242 
2243     protected int compareColumns(
2244         byte [] left, int loffset, int llength, final int lfamilylength,
2245         byte [] right, int roffset, int rlength, final int rfamilylength) {
2246       return KeyValue.compareColumns(left, loffset, llength, lfamilylength,
2247         right, roffset, rlength, rfamilylength);
2248     }
2249 
2250     int compareTimestamps(final long ltimestamp, final long rtimestamp) {
2251       // The below older timestamps sorting ahead of newer timestamps looks
2252       // wrong but it is intentional. This way, newer timestamps are first
2253       // found when we iterate over a memstore and newer versions are the
2254       // first we trip over when reading from a store file.
2255       if (ltimestamp < rtimestamp) {
2256         return 1;
2257       } else if (ltimestamp > rtimestamp) {
2258         return -1;
2259       }
2260       return 0;
2261     }
2262   }
2263 
2264   // HeapSize
2265   public long heapSize() {
2266     return ClassSize.align(ClassSize.OBJECT + ClassSize.REFERENCE
2267         + ClassSize.align(ClassSize.ARRAY) + ClassSize.align(length)
2268         + (3 * Bytes.SIZEOF_INT) + Bytes.SIZEOF_LONG);
2269   }
2270 
2271   // this overload assumes that the length bytes have already been read,
2272   // and it expects the length of the KeyValue to be explicitly passed
2273   // to it.
2274   public void readFields(int length, final DataInput in) throws IOException {
2275     this.length = length;
2276     this.offset = 0;
2277     this.keyLength = 0;
2278     this.bytes = new byte[this.length];
2279     in.readFully(this.bytes, 0, this.length);
2280   }
2281 
2282   // Writable
2283   public void readFields(final DataInput in) throws IOException {
2284     int length = in.readInt();
2285     readFields(length, in);
2286   }
2287 
2288   public void write(final DataOutput out) throws IOException {
2289     out.writeInt(this.length);
2290     out.write(this.bytes, this.offset, this.length);
2291   }
2292 }