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