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