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