View Javadoc

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