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