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