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