View Javadoc

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