001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import static org.apache.hadoop.hbase.util.Bytes.len;
021
022import java.io.DataInput;
023import java.io.DataOutput;
024import java.io.IOException;
025import java.io.OutputStream;
026import java.nio.ByteBuffer;
027import java.util.ArrayList;
028import java.util.Arrays;
029import java.util.HashMap;
030import java.util.Iterator;
031import java.util.List;
032import java.util.Map;
033import org.apache.hadoop.hbase.util.ByteBufferUtils;
034import org.apache.hadoop.hbase.util.Bytes;
035import org.apache.hadoop.hbase.util.ClassSize;
036import org.apache.hadoop.io.RawComparator;
037import org.apache.yetus.audience.InterfaceAudience;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041/**
042 * An HBase Key/Value. This is the fundamental HBase Type.
043 * <p>
044 * HBase applications and users should use the Cell interface and avoid directly using KeyValue and
045 * member functions not defined in Cell.
046 * <p>
047 * If being used client-side, the primary methods to access individual fields are
048 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()},
049 * {@link #getTimestamp()}, and {@link #getValueArray()}. These methods allocate new byte arrays and
050 * return copies. Avoid their use server-side.
051 * <p>
052 * Instances of this class are immutable. They do not implement Comparable but Comparators are
053 * provided. Comparators change with context, whether user table or a catalog table comparison. Its
054 * critical you use the appropriate comparator. There are Comparators for normal HFiles, Meta's
055 * Hfiles, and bloom filter keys.
056 * <p>
057 * KeyValue wraps a byte array and takes offsets and lengths into passed array at where to start
058 * interpreting the content as KeyValue. The KeyValue format inside a byte array is:
059 * <code>&lt;keylength&gt; &lt;valuelength&gt; &lt;key&gt; &lt;value&gt;</code> Key is further
060 * decomposed as: <code>&lt;rowlength&gt; &lt;row&gt; &lt;columnfamilylength&gt;
061 * &lt;columnfamily&gt; &lt;columnqualifier&gt;
062 * &lt;timestamp&gt; &lt;keytype&gt;</code> The <code>rowlength</code> maximum is
063 * <code>Short.MAX_SIZE</code>, column family length maximum is <code>Byte.MAX_SIZE</code>, and
064 * column qualifier + key length must be &lt; <code>Integer.MAX_SIZE</code>. The column does not
065 * contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}<br>
066 * KeyValue can optionally contain Tags. When it contains tags, it is added in the byte array after
067 * the value part. The format for this part is: <code>&lt;tagslength&gt;&lt;tagsbytes&gt;</code>.
068 * <code>tagslength</code> maximum is <code>Short.MAX_SIZE</code>. The <code>tagsbytes</code>
069 * contain one or more tags where as each tag is of the form
070 * <code>&lt;taglength&gt;&lt;tagtype&gt;&lt;tagbytes&gt;</code>. <code>tagtype</code> is one byte
071 * and <code>taglength</code> maximum is <code>Short.MAX_SIZE</code> and it includes 1 byte type
072 * length and actual tag bytes length.
073 */
074@InterfaceAudience.Private
075public class KeyValue implements ExtendedCell, Cloneable {
076  private static final Logger LOG = LoggerFactory.getLogger(KeyValue.class);
077
078  public static final int FIXED_OVERHEAD = ClassSize.OBJECT + // the KeyValue object itself
079    ClassSize.REFERENCE + // pointer to "bytes"
080    2 * Bytes.SIZEOF_INT + // offset, length
081    Bytes.SIZEOF_LONG;// memstoreTS
082
083  /**
084   * Colon character in UTF-8
085   */
086  public static final char COLUMN_FAMILY_DELIMITER = ':';
087
088  public static final byte[] COLUMN_FAMILY_DELIM_ARRAY = new byte[] { COLUMN_FAMILY_DELIMITER };
089
090  /**
091   * Comparator for plain key/values; i.e. non-catalog table key/values. Works on Key portion of
092   * KeyValue only.
093   * @deprecated Use {@link CellComparator#getInstance()} instead. Deprecated for hbase 2.0, remove
094   *             for hbase 3.0.
095   */
096  @Deprecated
097  public static final KVComparator COMPARATOR = new KVComparator();
098  /**
099   * A {@link KVComparator} for <code>hbase:meta</code> catalog table {@link KeyValue}s.
100   * @deprecated Use {@link MetaCellComparator#META_COMPARATOR} instead. Deprecated for hbase 2.0,
101   *             remove for hbase 3.0.
102   */
103  @Deprecated
104  public static final KVComparator META_COMPARATOR = new MetaComparator();
105
106  /** Size of the key length field in bytes */
107  public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT;
108
109  /** Size of the key type field in bytes */
110  public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE;
111
112  /** Size of the row length field in bytes */
113  public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
114
115  /** Size of the family length field in bytes */
116  public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
117
118  /** Size of the timestamp field in bytes */
119  public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG;
120
121  // Size of the timestamp and type byte on end of a key -- a long + a byte.
122  public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE;
123
124  // Size of the length shorts and bytes in key.
125  public static final int KEY_INFRASTRUCTURE_SIZE =
126    ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE;
127
128  // How far into the key the row starts at. First thing to read is the short
129  // that says how long the row is.
130  public static final int ROW_OFFSET =
131    Bytes.SIZEOF_INT /* keylength */ + Bytes.SIZEOF_INT /* valuelength */;
132
133  public static final int ROW_KEY_OFFSET = ROW_OFFSET + ROW_LENGTH_SIZE;
134
135  // Size of the length ints in a KeyValue datastructure.
136  public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET;
137
138  /** Size of the tags length field in bytes */
139  public static final int TAGS_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
140
141  public static final int KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE = ROW_OFFSET + TAGS_LENGTH_SIZE;
142
143  /**
144   * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
145   * characteristics would take up for its underlying data structure.
146   * @param rlength row length
147   * @param flength family length
148   * @param qlength qualifier length
149   * @param vlength value length
150   * @return the <code>KeyValue</code> data structure length
151   */
152  public static long getKeyValueDataStructureSize(int rlength, int flength, int qlength,
153    int vlength) {
154    return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE
155      + getKeyDataStructureSize(rlength, flength, qlength) + vlength;
156  }
157
158  /**
159   * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
160   * characteristics would take up for its underlying data structure.
161   * @param rlength    row length
162   * @param flength    family length
163   * @param qlength    qualifier length
164   * @param vlength    value length
165   * @param tagsLength total length of the tags
166   * @return the <code>KeyValue</code> data structure length
167   */
168  public static long getKeyValueDataStructureSize(int rlength, int flength, int qlength,
169    int vlength, int tagsLength) {
170    if (tagsLength == 0) {
171      return getKeyValueDataStructureSize(rlength, flength, qlength, vlength);
172    }
173    return KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE
174      + getKeyDataStructureSize(rlength, flength, qlength) + vlength + tagsLength;
175  }
176
177  /**
178   * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
179   * characteristics would take up for its underlying data structure.
180   * @param klength    key length
181   * @param vlength    value length
182   * @param tagsLength total length of the tags
183   * @return the <code>KeyValue</code> data structure length
184   */
185  public static long getKeyValueDataStructureSize(int klength, int vlength, int tagsLength) {
186    if (tagsLength == 0) {
187      return (long) KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + klength + vlength;
188    }
189    return (long) KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE + klength + vlength + tagsLength;
190  }
191
192  /**
193   * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
194   * characteristics would take up in its underlying data structure for the key.
195   * @param rlength row length
196   * @param flength family length
197   * @param qlength qualifier length
198   * @return the key data structure length
199   */
200  public static long getKeyDataStructureSize(int rlength, int flength, int qlength) {
201    return (long) KeyValue.KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
202  }
203
204  /**
205   * Key type. Has space for other key types to be added later. Cannot rely on enum ordinals . They
206   * change if item is removed or moved. Do our own codes.
207   */
208  public static enum Type {
209    Minimum((byte) 0),
210    Put((byte) 4),
211
212    Delete((byte) 8),
213    DeleteFamilyVersion((byte) 10),
214    DeleteColumn((byte) 12),
215    DeleteFamily((byte) 14),
216
217    // Maximum is used when searching; you look from maximum on down.
218    Maximum((byte) 255);
219
220    private final byte code;
221
222    Type(final byte c) {
223      this.code = c;
224    }
225
226    public byte getCode() {
227      return this.code;
228    }
229
230    private static Type[] codeArray = new Type[256];
231
232    static {
233      for (Type t : Type.values()) {
234        codeArray[t.code & 0xff] = t;
235      }
236    }
237
238    /**
239     * True to indicate that the byte b is a valid type.
240     * @param b byte to check
241     * @return true or false
242     */
243    static boolean isValidType(byte b) {
244      return codeArray[b & 0xff] != null;
245    }
246
247    /**
248     * Cannot rely on enum ordinals . They change if item is removed or moved. Do our own codes.
249     * @param b the kv serialized byte[] to process
250     * @return Type associated with passed code.
251     */
252    public static Type codeToType(final byte b) {
253      Type t = codeArray[b & 0xff];
254      if (t != null) {
255        return t;
256      }
257      throw new RuntimeException("Unknown code " + b);
258    }
259  }
260
261  /**
262   * Lowest possible key. Makes a Key with highest possible Timestamp, empty row and column. No key
263   * can be equal or lower than this one in memstore or in store file.
264   */
265  public static final KeyValue LOWESTKEY =
266    new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP);
267
268  ////
269  // KeyValue core instance fields.
270  protected byte[] bytes = null; // an immutable byte array that contains the KV
271  protected int offset = 0; // offset into bytes buffer KV starts at
272  protected int length = 0; // length of the KV starting from offset.
273
274  /** Here be dragons **/
275
276  /**
277   * used to achieve atomic operations in the memstore.
278   */
279  @Override
280  public long getSequenceId() {
281    return seqId;
282  }
283
284  @Override
285  public void setSequenceId(long seqId) {
286    this.seqId = seqId;
287  }
288
289  // multi-version concurrency control version. default value is 0, aka do not care.
290  private long seqId = 0;
291
292  /** Dragon time over, return to normal business */
293
294  /** Writable Constructor -- DO NOT USE */
295  public KeyValue() {
296  }
297
298  /**
299   * Creates a KeyValue from the start of the specified byte array. Presumes <code>bytes</code>
300   * content is formatted as a KeyValue blob.
301   * @param bytes byte array
302   */
303  public KeyValue(final byte[] bytes) {
304    this(bytes, 0);
305  }
306
307  /**
308   * Creates a KeyValue from the specified byte array and offset. Presumes <code>bytes</code>
309   * content starting at <code>offset</code> is formatted as a KeyValue blob.
310   * @param bytes  byte array
311   * @param offset offset to start of KeyValue
312   */
313  public KeyValue(final byte[] bytes, final int offset) {
314    this(bytes, offset, getLength(bytes, offset));
315  }
316
317  /**
318   * Creates a KeyValue from the specified byte array, starting at offset, and for length
319   * <code>length</code>.
320   * @param bytes  byte array
321   * @param offset offset to start of the KeyValue
322   * @param length length of the KeyValue
323   */
324  public KeyValue(final byte[] bytes, final int offset, final int length) {
325    KeyValueUtil.checkKeyValueBytes(bytes, offset, length, true);
326    this.bytes = bytes;
327    this.offset = offset;
328    this.length = length;
329  }
330
331  /**
332   * Creates a KeyValue from the specified byte array, starting at offset, and for length
333   * <code>length</code>.
334   * @param bytes  byte array
335   * @param offset offset to start of the KeyValue
336   * @param length length of the KeyValue
337   * @param ts     timestamp
338   */
339  public KeyValue(final byte[] bytes, final int offset, final int length, long ts) {
340    this(bytes, offset, length, null, 0, 0, null, 0, 0, ts, Type.Maximum, null, 0, 0, null);
341  }
342
343  /** Constructors that build a new backing byte array from fields */
344
345  /**
346   * Constructs KeyValue structure filled with null value. Sets type to
347   * {@link KeyValue.Type#Maximum}
348   * @param row       - row key (arbitrary byte array)
349   * @param timestamp version timestamp
350   */
351  public KeyValue(final byte[] row, final long timestamp) {
352    this(row, null, null, timestamp, Type.Maximum, null);
353  }
354
355  /**
356   * Constructs KeyValue structure filled with null value.
357   * @param row       - row key (arbitrary byte array)
358   * @param timestamp version timestamp
359   */
360  public KeyValue(final byte[] row, final long timestamp, Type type) {
361    this(row, null, null, timestamp, type, null);
362  }
363
364  /**
365   * Constructs KeyValue structure filled with null value. Sets type to
366   * {@link KeyValue.Type#Maximum}
367   * @param row       - row key (arbitrary byte array)
368   * @param family    family name
369   * @param qualifier column qualifier
370   */
371  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier) {
372    this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
373  }
374
375  /**
376   * Constructs KeyValue structure as a put filled with specified values and LATEST_TIMESTAMP.
377   * @param row       - row key (arbitrary byte array)
378   * @param family    family name
379   * @param qualifier column qualifier
380   */
381  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
382    final byte[] value) {
383    this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value);
384  }
385
386  /**
387   * Constructs KeyValue structure filled with specified values.
388   * @param row       row key
389   * @param family    family name
390   * @param qualifier column qualifier
391   * @param timestamp version timestamp
392   * @param type      key type
393   * @throws IllegalArgumentException an illegal value was passed
394   */
395  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
396    final long timestamp, Type type) {
397    this(row, family, qualifier, timestamp, type, null);
398  }
399
400  /**
401   * Constructs KeyValue structure filled with specified values.
402   * @param row       row key
403   * @param family    family name
404   * @param qualifier column qualifier
405   * @param timestamp version timestamp
406   * @param value     column value
407   * @throws IllegalArgumentException an illegal value was passed
408   */
409  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
410    final long timestamp, final byte[] value) {
411    this(row, family, qualifier, timestamp, Type.Put, value);
412  }
413
414  /**
415   * Constructs KeyValue structure filled with specified values.
416   * @param row       row key
417   * @param family    family name
418   * @param qualifier column qualifier
419   * @param timestamp version timestamp
420   * @param value     column value
421   * @param tags      tags
422   * @throws IllegalArgumentException an illegal value was passed
423   */
424  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
425    final long timestamp, final byte[] value, final Tag[] tags) {
426    this(row, family, qualifier, timestamp, value, tags != null ? Arrays.asList(tags) : null);
427  }
428
429  /**
430   * Constructs KeyValue structure filled with specified values.
431   * @param row       row key
432   * @param family    family name
433   * @param qualifier column qualifier
434   * @param timestamp version timestamp
435   * @param value     column value
436   * @param tags      tags non-empty list of tags or null
437   * @throws IllegalArgumentException an illegal value was passed
438   */
439  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
440    final long timestamp, final byte[] value, final List<Tag> tags) {
441    this(row, 0, row == null ? 0 : row.length, family, 0, family == null ? 0 : family.length,
442      qualifier, 0, qualifier == null ? 0 : qualifier.length, timestamp, Type.Put, value, 0,
443      value == null ? 0 : value.length, tags);
444  }
445
446  /**
447   * Constructs KeyValue structure filled with specified values.
448   * @param row       row key
449   * @param family    family name
450   * @param qualifier column qualifier
451   * @param timestamp version timestamp
452   * @param type      key type
453   * @param value     column value
454   * @throws IllegalArgumentException an illegal value was passed
455   */
456  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
457    final long timestamp, Type type, final byte[] value) {
458    this(row, 0, len(row), family, 0, len(family), qualifier, 0, len(qualifier), timestamp, type,
459      value, 0, len(value));
460  }
461
462  /**
463   * Constructs KeyValue structure filled with specified values.
464   * <p>
465   * Column is split into two fields, family and qualifier.
466   * @param row       row key
467   * @param family    family name
468   * @param qualifier column qualifier
469   * @param timestamp version timestamp
470   * @param type      key type
471   * @param value     column value
472   * @throws IllegalArgumentException an illegal value was passed
473   */
474  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
475    final long timestamp, Type type, final byte[] value, final List<Tag> tags) {
476    this(row, family, qualifier, 0, qualifier == null ? 0 : qualifier.length, timestamp, type,
477      value, 0, value == null ? 0 : value.length, tags);
478  }
479
480  /**
481   * Constructs KeyValue structure filled with specified values.
482   * @param row       row key
483   * @param family    family name
484   * @param qualifier column qualifier
485   * @param timestamp version timestamp
486   * @param type      key type
487   * @param value     column value
488   * @throws IllegalArgumentException an illegal value was passed
489   */
490  public KeyValue(final byte[] row, final byte[] family, final byte[] qualifier,
491    final long timestamp, Type type, final byte[] value, final byte[] tags) {
492    this(row, family, qualifier, 0, qualifier == null ? 0 : qualifier.length, timestamp, type,
493      value, 0, value == null ? 0 : value.length, tags);
494  }
495
496  /**
497   * Constructs KeyValue structure filled with specified values.
498   * @param row       row key
499   * @param family    family name
500   * @param qualifier column qualifier
501   * @param qoffset   qualifier offset
502   * @param qlength   qualifier length
503   * @param timestamp version timestamp
504   * @param type      key type
505   * @param value     column value
506   * @param voffset   value offset
507   * @param vlength   value length
508   * @throws IllegalArgumentException an illegal value was passed
509   */
510  public KeyValue(byte[] row, byte[] family, byte[] qualifier, int qoffset, int qlength,
511    long timestamp, Type type, byte[] value, int voffset, int vlength, List<Tag> tags) {
512    this(row, 0, row == null ? 0 : row.length, family, 0, family == null ? 0 : family.length,
513      qualifier, qoffset, qlength, timestamp, type, value, voffset, vlength, tags);
514  }
515
516  /**
517   * @param row       row key
518   * @param family    family name
519   * @param qualifier qualifier name
520   * @param qoffset   qualifier offset
521   * @param qlength   qualifier length
522   * @param timestamp version timestamp
523   * @param type      key type
524   * @param value     column value
525   * @param voffset   value offset
526   * @param vlength   value length
527   * @param tags      tags
528   */
529  public KeyValue(byte[] row, byte[] family, byte[] qualifier, int qoffset, int qlength,
530    long timestamp, Type type, byte[] value, int voffset, int vlength, byte[] tags) {
531    this(row, 0, row == null ? 0 : row.length, family, 0, family == null ? 0 : family.length,
532      qualifier, qoffset, qlength, timestamp, type, value, voffset, vlength, tags, 0,
533      tags == null ? 0 : tags.length);
534  }
535
536  /**
537   * Constructs KeyValue structure filled with specified values.
538   * <p>
539   * Column is split into two fields, family and qualifier.
540   * @param row row key
541   * @throws IllegalArgumentException an illegal value was passed
542   */
543  public KeyValue(final byte[] row, final int roffset, final int rlength, final byte[] family,
544    final int foffset, final int flength, final byte[] qualifier, final int qoffset,
545    final int qlength, final long timestamp, final Type type, final byte[] value, final int voffset,
546    final int vlength) {
547    this(row, roffset, rlength, family, foffset, flength, qualifier, qoffset, qlength, timestamp,
548      type, value, voffset, vlength, null);
549  }
550
551  /**
552   * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the
553   * data buffer.
554   * <p>
555   * Column is split into two fields, family and qualifier.
556   * @param buffer    the bytes buffer to use
557   * @param boffset   buffer offset
558   * @param row       row key
559   * @param roffset   row offset
560   * @param rlength   row length
561   * @param family    family name
562   * @param foffset   family offset
563   * @param flength   family length
564   * @param qualifier column qualifier
565   * @param qoffset   qualifier offset
566   * @param qlength   qualifier length
567   * @param timestamp version timestamp
568   * @param type      key type
569   * @param value     column value
570   * @param voffset   value offset
571   * @param vlength   value length
572   * @param tags      non-empty list of tags or null
573   * @throws IllegalArgumentException an illegal value was passed or there is insufficient space
574   *                                  remaining in the buffer
575   */
576  public KeyValue(byte[] buffer, final int boffset, final byte[] row, final int roffset,
577    final int rlength, final byte[] family, final int foffset, final int flength,
578    final byte[] qualifier, final int qoffset, final int qlength, final long timestamp,
579    final Type type, final byte[] value, final int voffset, final int vlength, final Tag[] tags) {
580    this.bytes = buffer;
581    this.length = writeByteArray(buffer, boffset, row, roffset, rlength, family, foffset, flength,
582      qualifier, qoffset, qlength, timestamp, type, value, voffset, vlength, tags);
583    this.offset = boffset;
584  }
585
586  /**
587   * Constructs KeyValue structure filled with specified values.
588   * <p>
589   * Column is split into two fields, family and qualifier.
590   * @param row       row key
591   * @param roffset   row offset
592   * @param rlength   row length
593   * @param family    family name
594   * @param foffset   family offset
595   * @param flength   family length
596   * @param qualifier column qualifier
597   * @param qoffset   qualifier offset
598   * @param qlength   qualifier length
599   * @param timestamp version timestamp
600   * @param type      key type
601   * @param value     column value
602   * @param voffset   value offset
603   * @param vlength   value length
604   * @param tags      tags
605   * @throws IllegalArgumentException an illegal value was passed
606   */
607  public KeyValue(final byte[] row, final int roffset, final int rlength, final byte[] family,
608    final int foffset, final int flength, final byte[] qualifier, final int qoffset,
609    final int qlength, final long timestamp, final Type type, final byte[] value, final int voffset,
610    final int vlength, final List<Tag> tags) {
611    this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, qualifier,
612      qoffset, qlength, timestamp, type, value, voffset, vlength, tags);
613    this.length = bytes.length;
614    this.offset = 0;
615  }
616
617  /**
618   * @param row       row key
619   * @param roffset   row offset
620   * @param rlength   row length
621   * @param family    family name
622   * @param foffset   fammily offset
623   * @param flength   family length
624   * @param qualifier column qualifier
625   * @param qoffset   qualifier offset
626   * @param qlength   qualifier length
627   * @param timestamp version timestamp
628   * @param type      key type
629   * @param value     column value
630   * @param voffset   value offset
631   * @param vlength   value length
632   * @param tags      input tags
633   */
634  public KeyValue(final byte[] row, final int roffset, final int rlength, final byte[] family,
635    final int foffset, final int flength, final byte[] qualifier, final int qoffset,
636    final int qlength, final long timestamp, final Type type, final byte[] value, final int voffset,
637    final int vlength, final byte[] tags, final int tagsOffset, final int tagsLength) {
638    this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, qualifier,
639      qoffset, qlength, timestamp, type, value, voffset, vlength, tags, tagsOffset, tagsLength);
640    this.length = bytes.length;
641    this.offset = 0;
642  }
643
644  /**
645   * Constructs an empty KeyValue structure, with specified sizes. This can be used to partially
646   * fill up KeyValues.
647   * <p>
648   * Column is split into two fields, family and qualifier.
649   * @param rlength   row length
650   * @param flength   family length
651   * @param qlength   qualifier length
652   * @param timestamp version timestamp
653   * @param type      key type
654   * @param vlength   value length
655   * @throws IllegalArgumentException an illegal value was passed
656   */
657  public KeyValue(final int rlength, final int flength, final int qlength, final long timestamp,
658    final Type type, final int vlength) {
659    this(rlength, flength, qlength, timestamp, type, vlength, 0);
660  }
661
662  /**
663   * Constructs an empty KeyValue structure, with specified sizes. This can be used to partially
664   * fill up KeyValues.
665   * <p>
666   * Column is split into two fields, family and qualifier.
667   * @param rlength    row length
668   * @param flength    family length
669   * @param qlength    qualifier length
670   * @param timestamp  version timestamp
671   * @param type       key type
672   * @param vlength    value length
673   * @param tagsLength length of the tags
674   * @throws IllegalArgumentException an illegal value was passed
675   */
676  public KeyValue(final int rlength, final int flength, final int qlength, final long timestamp,
677    final Type type, final int vlength, final int tagsLength) {
678    this.bytes =
679      createEmptyByteArray(rlength, flength, qlength, timestamp, type, vlength, tagsLength);
680    this.length = bytes.length;
681    this.offset = 0;
682  }
683
684  public KeyValue(byte[] row, int roffset, int rlength, byte[] family, int foffset, int flength,
685    ByteBuffer qualifier, long ts, Type type, ByteBuffer value, List<Tag> tags) {
686    this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength, qualifier, 0,
687      qualifier == null ? 0 : qualifier.remaining(), ts, type, value, 0,
688      value == null ? 0 : value.remaining(), tags);
689    this.length = bytes.length;
690    this.offset = 0;
691  }
692
693  public KeyValue(Cell c) {
694    this(c.getRowArray(), c.getRowOffset(), c.getRowLength(), c.getFamilyArray(),
695      c.getFamilyOffset(), c.getFamilyLength(), c.getQualifierArray(), c.getQualifierOffset(),
696      c.getQualifierLength(), c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(),
697      c.getValueOffset(), c.getValueLength(), c.getTagsArray(), c.getTagsOffset(),
698      c.getTagsLength());
699    this.seqId = c.getSequenceId();
700  }
701
702  /**
703   * Create an empty byte[] representing a KeyValue All lengths are preset and can be filled in
704   * later.
705   * @param rlength   row length
706   * @param flength   family length
707   * @param qlength   qualifier length
708   * @param timestamp version timestamp
709   * @param type      key type
710   * @param vlength   value length
711   * @return The newly created byte array.
712   */
713  private static byte[] createEmptyByteArray(final int rlength, int flength, int qlength,
714    final long timestamp, final Type type, int vlength, int tagsLength) {
715    if (rlength > Short.MAX_VALUE) {
716      throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
717    }
718    if (flength > Byte.MAX_VALUE) {
719      throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
720    }
721    // Qualifier length
722    if (qlength > Integer.MAX_VALUE - rlength - flength) {
723      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
724    }
725    RawCell.checkForTagsLength(tagsLength);
726    // Key length
727    long longkeylength = getKeyDataStructureSize(rlength, flength, qlength);
728    if (longkeylength > Integer.MAX_VALUE) {
729      throw new IllegalArgumentException("keylength " + longkeylength + " > " + Integer.MAX_VALUE);
730    }
731    int keylength = (int) longkeylength;
732    // Value length
733    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
734      throw new IllegalArgumentException("Valuer > " + HConstants.MAXIMUM_VALUE_LENGTH);
735    }
736
737    // Allocate right-sized byte array.
738    byte[] bytes =
739      new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength)];
740    // Write the correct size markers
741    int pos = 0;
742    pos = Bytes.putInt(bytes, pos, keylength);
743    pos = Bytes.putInt(bytes, pos, vlength);
744    pos = Bytes.putShort(bytes, pos, (short) (rlength & 0x0000ffff));
745    pos += rlength;
746    pos = Bytes.putByte(bytes, pos, (byte) (flength & 0x0000ff));
747    pos += flength + qlength;
748    pos = Bytes.putLong(bytes, pos, timestamp);
749    pos = Bytes.putByte(bytes, pos, type.getCode());
750    pos += vlength;
751    if (tagsLength > 0) {
752      pos = Bytes.putAsShort(bytes, pos, tagsLength);
753    }
754    return bytes;
755  }
756
757  /**
758   * Checks the parameters passed to a constructor.
759   * @param row     row key
760   * @param rlength row length
761   * @param family  family name
762   * @param flength family length
763   * @param qlength qualifier length
764   * @param vlength value length
765   * @throws IllegalArgumentException an illegal value was passed
766   */
767  static void checkParameters(final byte[] row, final int rlength, final byte[] family, int flength,
768    int qlength, int vlength) throws IllegalArgumentException {
769    if (rlength > Short.MAX_VALUE) {
770      throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
771    }
772    if (row == null) {
773      throw new IllegalArgumentException("Row is null");
774    }
775    // Family length
776    flength = family == null ? 0 : flength;
777    if (flength > Byte.MAX_VALUE) {
778      throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
779    }
780    // Qualifier length
781    if (qlength > Integer.MAX_VALUE - rlength - flength) {
782      throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
783    }
784    // Key length
785    long longKeyLength = getKeyDataStructureSize(rlength, flength, qlength);
786    if (longKeyLength > Integer.MAX_VALUE) {
787      throw new IllegalArgumentException("keylength " + longKeyLength + " > " + Integer.MAX_VALUE);
788    }
789    // Value length
790    if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) { // FindBugs INT_VACUOUS_COMPARISON
791      throw new IllegalArgumentException(
792        "Value length " + vlength + " > " + HConstants.MAXIMUM_VALUE_LENGTH);
793    }
794  }
795
796  /**
797   * Write KeyValue format into the provided byte array.
798   * @param buffer    the bytes buffer to use
799   * @param boffset   buffer offset
800   * @param row       row key
801   * @param roffset   row offset
802   * @param rlength   row length
803   * @param family    family name
804   * @param foffset   family offset
805   * @param flength   family length
806   * @param qualifier column qualifier
807   * @param qoffset   qualifier offset
808   * @param qlength   qualifier length
809   * @param timestamp version timestamp
810   * @param type      key type
811   * @param value     column value
812   * @param voffset   value offset
813   * @param vlength   value length
814   * @return The number of useful bytes in the buffer.
815   * @throws IllegalArgumentException an illegal value was passed or there is insufficient space
816   *                                  remaining in the buffer
817   */
818  public static int writeByteArray(byte[] buffer, final int boffset, final byte[] row,
819    final int roffset, final int rlength, final byte[] family, final int foffset, int flength,
820    final byte[] qualifier, final int qoffset, int qlength, final long timestamp, final Type type,
821    final byte[] value, final int voffset, int vlength, Tag[] tags) {
822
823    checkParameters(row, rlength, family, flength, qlength, vlength);
824
825    // Calculate length of tags area
826    int tagsLength = 0;
827    if (tags != null && tags.length > 0) {
828      for (Tag t : tags) {
829        tagsLength += t.getValueLength() + Tag.INFRASTRUCTURE_SIZE;
830      }
831    }
832    RawCell.checkForTagsLength(tagsLength);
833    int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
834    int keyValueLength =
835      (int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength);
836    if (keyValueLength > buffer.length - boffset) {
837      throw new IllegalArgumentException(
838        "Buffer size " + (buffer.length - boffset) + " < " + keyValueLength);
839    }
840
841    // Write key, value and key row length.
842    int pos = boffset;
843    pos = Bytes.putInt(buffer, pos, keyLength);
844    pos = Bytes.putInt(buffer, pos, vlength);
845    pos = Bytes.putShort(buffer, pos, (short) (rlength & 0x0000ffff));
846    pos = Bytes.putBytes(buffer, pos, row, roffset, rlength);
847    pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff));
848    if (flength != 0) {
849      pos = Bytes.putBytes(buffer, pos, family, foffset, flength);
850    }
851    if (qlength != 0) {
852      pos = Bytes.putBytes(buffer, pos, qualifier, qoffset, qlength);
853    }
854    pos = Bytes.putLong(buffer, pos, timestamp);
855    pos = Bytes.putByte(buffer, pos, type.getCode());
856    if (value != null && value.length > 0) {
857      pos = Bytes.putBytes(buffer, pos, value, voffset, vlength);
858    }
859    // Write the number of tags. If it is 0 then it means there are no tags.
860    if (tagsLength > 0) {
861      pos = Bytes.putAsShort(buffer, pos, tagsLength);
862      for (Tag t : tags) {
863        int tlen = t.getValueLength();
864        pos = Bytes.putAsShort(buffer, pos, tlen + Tag.TYPE_LENGTH_SIZE);
865        pos = Bytes.putByte(buffer, pos, t.getType());
866        Tag.copyValueTo(t, buffer, pos);
867        pos += tlen;
868      }
869    }
870    return keyValueLength;
871  }
872
873  /**
874   * Write KeyValue format into a byte array.
875   * @param row       row key
876   * @param roffset   row offset
877   * @param rlength   row length
878   * @param family    family name
879   * @param foffset   family offset
880   * @param flength   family length
881   * @param qualifier column qualifier
882   * @param qoffset   qualifier offset
883   * @param qlength   qualifier length
884   * @param timestamp version timestamp
885   * @param type      key type
886   * @param value     column value
887   * @param voffset   value offset
888   * @param vlength   value length
889   * @return The newly created byte array.
890   */
891  private static byte[] createByteArray(final byte[] row, final int roffset, final int rlength,
892    final byte[] family, final int foffset, int flength, final byte[] qualifier, final int qoffset,
893    int qlength, final long timestamp, final Type type, final byte[] value, final int voffset,
894    int vlength, byte[] tags, int tagsOffset, int tagsLength) {
895
896    checkParameters(row, rlength, family, flength, qlength, vlength);
897    RawCell.checkForTagsLength(tagsLength);
898    // Allocate right-sized byte array.
899    int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
900    byte[] bytes =
901      new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength)];
902    // Write key, value and key row length.
903    int pos = 0;
904    pos = Bytes.putInt(bytes, pos, keyLength);
905    pos = Bytes.putInt(bytes, pos, vlength);
906    pos = Bytes.putShort(bytes, pos, (short) (rlength & 0x0000ffff));
907    pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
908    pos = Bytes.putByte(bytes, pos, (byte) (flength & 0x0000ff));
909    if (flength != 0) {
910      pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
911    }
912    if (qlength != 0) {
913      pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength);
914    }
915    pos = Bytes.putLong(bytes, pos, timestamp);
916    pos = Bytes.putByte(bytes, pos, type.getCode());
917    if (value != null && value.length > 0) {
918      pos = Bytes.putBytes(bytes, pos, value, voffset, vlength);
919    }
920    // Add the tags after the value part
921    if (tagsLength > 0) {
922      pos = Bytes.putAsShort(bytes, pos, tagsLength);
923      pos = Bytes.putBytes(bytes, pos, tags, tagsOffset, tagsLength);
924    }
925    return bytes;
926  }
927
928  /**
929   * @param qualifier can be a ByteBuffer or a byte[], or null.
930   * @param value     can be a ByteBuffer or a byte[], or null.
931   */
932  private static byte[] createByteArray(final byte[] row, final int roffset, final int rlength,
933    final byte[] family, final int foffset, int flength, final Object qualifier, final int qoffset,
934    int qlength, final long timestamp, final Type type, final Object value, final int voffset,
935    int vlength, List<Tag> tags) {
936
937    checkParameters(row, rlength, family, flength, qlength, vlength);
938
939    // Calculate length of tags area
940    int tagsLength = 0;
941    if (tags != null && !tags.isEmpty()) {
942      for (Tag t : tags) {
943        tagsLength += t.getValueLength() + Tag.INFRASTRUCTURE_SIZE;
944      }
945    }
946    RawCell.checkForTagsLength(tagsLength);
947    // Allocate right-sized byte array.
948    int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
949    byte[] bytes =
950      new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength, tagsLength)];
951
952    // Write key, value and key row length.
953    int pos = 0;
954    pos = Bytes.putInt(bytes, pos, keyLength);
955
956    pos = Bytes.putInt(bytes, pos, vlength);
957    pos = Bytes.putShort(bytes, pos, (short) (rlength & 0x0000ffff));
958    pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
959    pos = Bytes.putByte(bytes, pos, (byte) (flength & 0x0000ff));
960    if (flength != 0) {
961      pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
962    }
963    if (qlength > 0) {
964      if (qualifier instanceof ByteBuffer) {
965        pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) qualifier);
966      } else {
967        pos = Bytes.putBytes(bytes, pos, (byte[]) qualifier, qoffset, qlength);
968      }
969    }
970    pos = Bytes.putLong(bytes, pos, timestamp);
971    pos = Bytes.putByte(bytes, pos, type.getCode());
972    if (vlength > 0) {
973      if (value instanceof ByteBuffer) {
974        pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) value);
975      } else {
976        pos = Bytes.putBytes(bytes, pos, (byte[]) value, voffset, vlength);
977      }
978    }
979    // Add the tags after the value part
980    if (tagsLength > 0) {
981      pos = Bytes.putAsShort(bytes, pos, tagsLength);
982      for (Tag t : tags) {
983        int tlen = t.getValueLength();
984        pos = Bytes.putAsShort(bytes, pos, tlen + Tag.TYPE_LENGTH_SIZE);
985        pos = Bytes.putByte(bytes, pos, t.getType());
986        Tag.copyValueTo(t, bytes, pos);
987        pos += tlen;
988      }
989    }
990    return bytes;
991  }
992
993  /**
994   * Needed doing 'contains' on List. Only compares the key portion, not the value.
995   */
996  @Override
997  public boolean equals(Object other) {
998    if (!(other instanceof Cell)) {
999      return false;
1000    }
1001    return CellUtil.equals(this, (Cell) other);
1002  }
1003
1004  /**
1005   * In line with {@link #equals(Object)}, only uses the key portion, not the value.
1006   */
1007  @Override
1008  public int hashCode() {
1009    return calculateHashForKey(this);
1010  }
1011
1012  private int calculateHashForKey(Cell cell) {
1013    // pre-calculate the 3 hashes made of byte ranges
1014    int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
1015    int familyHash =
1016      Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
1017    int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(),
1018      cell.getQualifierLength());
1019
1020    // combine the 6 sub-hashes
1021    int hash = 31 * rowHash + familyHash;
1022    hash = 31 * hash + qualifierHash;
1023    hash = 31 * hash + (int) cell.getTimestamp();
1024    hash = 31 * hash + cell.getTypeByte();
1025    return hash;
1026  }
1027
1028  // ---------------------------------------------------------------------------
1029  //
1030  // KeyValue cloning
1031  //
1032  // ---------------------------------------------------------------------------
1033
1034  /**
1035   * Clones a KeyValue. This creates a copy, re-allocating the buffer.
1036   * @return Fully copied clone of this KeyValue
1037   * @throws CloneNotSupportedException if cloning of keyValue is not supported
1038   */
1039  @Override
1040  public KeyValue clone() throws CloneNotSupportedException {
1041    KeyValue ret = (KeyValue) super.clone();
1042    ret.bytes = Arrays.copyOf(this.bytes, this.bytes.length);
1043    ret.offset = 0;
1044    ret.length = ret.bytes.length;
1045    // Important to clone the memstoreTS as well - otherwise memstore's
1046    // update-in-place methods (eg increment) will end up creating
1047    // new entries
1048    ret.setSequenceId(seqId);
1049    return ret;
1050  }
1051
1052  /**
1053   * Creates a shallow copy of this KeyValue, reusing the data byte buffer.
1054   * http://en.wikipedia.org/wiki/Object_copy
1055   * @return Shallow copy of this KeyValue
1056   */
1057  public KeyValue shallowCopy() {
1058    KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length);
1059    shallowCopy.setSequenceId(this.seqId);
1060    return shallowCopy;
1061  }
1062
1063  // ---------------------------------------------------------------------------
1064  //
1065  // String representation
1066  //
1067  // ---------------------------------------------------------------------------
1068
1069  @Override
1070  public String toString() {
1071    if (this.bytes == null || this.bytes.length == 0) {
1072      return "empty";
1073    }
1074    return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) + "/vlen="
1075      + getValueLength() + "/seqid=" + seqId;
1076  }
1077
1078  /** Return key as a String, empty string if k is null. */
1079  public static String keyToString(final byte[] k) {
1080    if (k == null) {
1081      return "";
1082    }
1083    return keyToString(k, 0, k.length);
1084  }
1085
1086  /**
1087   * Produces a string map for this key/value pair. Useful for programmatic use and manipulation of
1088   * the data stored in an WALKey, for example, printing as JSON. Values are left out due to their
1089   * tendency to be large. If needed, they can be added manually.
1090   * @return the Map&lt;String,?&gt; containing data from this key
1091   */
1092  public Map<String, Object> toStringMap() {
1093    Map<String, Object> stringMap = new HashMap<>();
1094    stringMap.put("row", Bytes.toStringBinary(getRowArray(), getRowOffset(), getRowLength()));
1095    stringMap.put("family",
1096      Bytes.toStringBinary(getFamilyArray(), getFamilyOffset(), getFamilyLength()));
1097    stringMap.put("qualifier",
1098      Bytes.toStringBinary(getQualifierArray(), getQualifierOffset(), getQualifierLength()));
1099    stringMap.put("timestamp", getTimestamp());
1100    stringMap.put("vlen", getValueLength());
1101    Iterator<Tag> tags = getTags();
1102    if (tags != null) {
1103      List<String> tagsString = new ArrayList<String>();
1104      while (tags.hasNext()) {
1105        tagsString.add(tags.next().toString());
1106      }
1107      stringMap.put("tag", tagsString);
1108    }
1109    return stringMap;
1110  }
1111
1112  /**
1113   * Use for logging.
1114   * @param b Key portion of a KeyValue.
1115   * @param o Offset to start of key
1116   * @param l Length of key.
1117   * @return Key as a String.
1118   */
1119  public static String keyToString(final byte[] b, final int o, final int l) {
1120    if (b == null) {
1121      return "";
1122    }
1123    int rowlength = Bytes.toShort(b, o);
1124    String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
1125    int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
1126    int familylength = b[columnoffset - 1];
1127    int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
1128    String family = familylength == 0 ? "" : Bytes.toStringBinary(b, columnoffset, familylength);
1129    String qualifier = columnlength == 0
1130      ? ""
1131      : Bytes.toStringBinary(b, columnoffset + familylength, columnlength - familylength);
1132    long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
1133    String timestampStr = humanReadableTimestamp(timestamp);
1134    byte type = b[o + l - 1];
1135    return row + "/" + family + (family != null && family.length() > 0 ? ":" : "") + qualifier + "/"
1136      + timestampStr + "/" + Type.codeToType(type);
1137  }
1138
1139  public static String humanReadableTimestamp(final long timestamp) {
1140    if (timestamp == HConstants.LATEST_TIMESTAMP) {
1141      return "LATEST_TIMESTAMP";
1142    }
1143    if (timestamp == PrivateConstants.OLDEST_TIMESTAMP) {
1144      return "OLDEST_TIMESTAMP";
1145    }
1146    return String.valueOf(timestamp);
1147  }
1148
1149  // ---------------------------------------------------------------------------
1150  //
1151  // Public Member Accessors
1152  //
1153  // ---------------------------------------------------------------------------
1154
1155  /**
1156   * To be used only in tests where the Cells are clearly assumed to be of type KeyValue and that we
1157   * need access to the backing array to do some test case related assertions.
1158   * @return The byte array backing this KeyValue.
1159   */
1160  public byte[] getBuffer() {
1161    return this.bytes;
1162  }
1163
1164  /** Returns Offset into {@link #getBuffer()} at which this KeyValue starts. */
1165  public int getOffset() {
1166    return this.offset;
1167  }
1168
1169  /** Returns Length of bytes this KeyValue occupies in {@link #getBuffer()}. */
1170  public int getLength() {
1171    return length;
1172  }
1173
1174  // ---------------------------------------------------------------------------
1175  //
1176  // Length and Offset Calculators
1177  //
1178  // ---------------------------------------------------------------------------
1179
1180  /**
1181   * Determines the total length of the KeyValue stored in the specified byte array and offset.
1182   * Includes all headers.
1183   * @param bytes  byte array
1184   * @param offset offset to start of the KeyValue
1185   * @return length of entire KeyValue, in bytes
1186   */
1187  private static int getLength(byte[] bytes, int offset) {
1188    int klength = ROW_OFFSET + Bytes.toInt(bytes, offset);
1189    int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
1190    return klength + vlength;
1191  }
1192
1193  /** Returns Key offset in backing buffer.. */
1194  public int getKeyOffset() {
1195    return this.offset + ROW_OFFSET;
1196  }
1197
1198  public String getKeyString() {
1199    return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
1200  }
1201
1202  /** Returns Length of key portion. */
1203  public int getKeyLength() {
1204    return Bytes.toInt(this.bytes, this.offset);
1205  }
1206
1207  /**
1208   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1209   */
1210  @Override
1211  public byte[] getValueArray() {
1212    return bytes;
1213  }
1214
1215  /** Returns the value offset */
1216  @Override
1217  public int getValueOffset() {
1218    int voffset = getKeyOffset() + getKeyLength();
1219    return voffset;
1220  }
1221
1222  /** Returns Value length */
1223  @Override
1224  public int getValueLength() {
1225    int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
1226    return vlength;
1227  }
1228
1229  /**
1230   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1231   */
1232  @Override
1233  public byte[] getRowArray() {
1234    return bytes;
1235  }
1236
1237  /** Returns Row offset */
1238  @Override
1239  public int getRowOffset() {
1240    return this.offset + ROW_KEY_OFFSET;
1241  }
1242
1243  /** Returns Row length */
1244  @Override
1245  public short getRowLength() {
1246    return Bytes.toShort(this.bytes, getKeyOffset());
1247  }
1248
1249  /**
1250   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1251   */
1252  @Override
1253  public byte[] getFamilyArray() {
1254    return bytes;
1255  }
1256
1257  /** Returns Family offset */
1258  @Override
1259  public int getFamilyOffset() {
1260    return getFamilyOffset(getFamilyLengthPosition(getRowLength()));
1261  }
1262
1263  /** Returns Family offset */
1264  int getFamilyOffset(int familyLenPosition) {
1265    return familyLenPosition + Bytes.SIZEOF_BYTE;
1266  }
1267
1268  /** Returns Family length */
1269  @Override
1270  public byte getFamilyLength() {
1271    return getFamilyLength(getFamilyLengthPosition(getRowLength()));
1272  }
1273
1274  /** Returns Family length */
1275  public byte getFamilyLength(int famLenPos) {
1276    return this.bytes[famLenPos];
1277  }
1278
1279  int getFamilyLengthPosition(int rowLength) {
1280    return this.offset + KeyValue.ROW_KEY_OFFSET + rowLength;
1281  }
1282
1283  /**
1284   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1285   */
1286  @Override
1287  public byte[] getQualifierArray() {
1288    return bytes;
1289  }
1290
1291  /** Returns Qualifier offset */
1292  @Override
1293  public int getQualifierOffset() {
1294    return getQualifierOffset(getFamilyOffset());
1295  }
1296
1297  /** Returns Qualifier offset */
1298  private int getQualifierOffset(int foffset) {
1299    return getQualifierOffset(foffset, getFamilyLength());
1300  }
1301
1302  /** Returns Qualifier offset */
1303  int getQualifierOffset(int foffset, int flength) {
1304    return foffset + flength;
1305  }
1306
1307  /** Returns Qualifier length */
1308  @Override
1309  public int getQualifierLength() {
1310    return getQualifierLength(getRowLength(), getFamilyLength());
1311  }
1312
1313  /** Returns Qualifier length */
1314  private int getQualifierLength(int rlength, int flength) {
1315    return getQualifierLength(getKeyLength(), rlength, flength);
1316  }
1317
1318  /** Returns Qualifier length */
1319  int getQualifierLength(int keyLength, int rlength, int flength) {
1320    return keyLength - (int) getKeyDataStructureSize(rlength, flength, 0);
1321  }
1322
1323  /** Returns Timestamp offset */
1324  public int getTimestampOffset() {
1325    return getTimestampOffset(getKeyLength());
1326  }
1327
1328  /** Return the timestamp offset */
1329  private int getTimestampOffset(final int keylength) {
1330    return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
1331  }
1332
1333  /** Returns True if this KeyValue has a LATEST_TIMESTAMP timestamp. */
1334  public boolean isLatestTimestamp() {
1335    return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
1336      HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
1337  }
1338
1339  /**
1340   * Update the timestamp.
1341   * @param now Time to set into <code>this</code> IFF timestamp ==
1342   *            {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
1343   * @return True is we modified this.
1344   */
1345  public boolean updateLatestStamp(final byte[] now) {
1346    if (this.isLatestTimestamp()) {
1347      int tsOffset = getTimestampOffset();
1348      System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
1349      // clear cache or else getTimestamp() possibly returns an old value
1350      return true;
1351    }
1352    return false;
1353  }
1354
1355  @Override
1356  public void setTimestamp(long ts) {
1357    Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG);
1358  }
1359
1360  @Override
1361  public void setTimestamp(byte[] ts) {
1362    Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, 0, Bytes.SIZEOF_LONG);
1363  }
1364
1365  // ---------------------------------------------------------------------------
1366  //
1367  // Methods that return copies of fields
1368  //
1369  // ---------------------------------------------------------------------------
1370
1371  /**
1372   * Do not use unless you have to. Used internally for compacting and testing. Use
1373   * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and
1374   * {@link #getValueArray()} if accessing a KeyValue client-side.
1375   * @return Copy of the key portion only.
1376   */
1377  public byte[] getKey() {
1378    int keylength = getKeyLength();
1379    byte[] key = new byte[keylength];
1380    System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
1381    return key;
1382  }
1383
1384  /** Return the timestamp. */
1385  @Override
1386  public long getTimestamp() {
1387    return getTimestamp(getKeyLength());
1388  }
1389
1390  /** Return the timestamp. */
1391  long getTimestamp(final int keylength) {
1392    int tsOffset = getTimestampOffset(keylength);
1393    return Bytes.toLong(this.bytes, tsOffset);
1394  }
1395
1396  /** Returns KeyValue.TYPE byte representation */
1397  @Override
1398  public byte getTypeByte() {
1399    return getTypeByte(getKeyLength());
1400  }
1401
1402  /** Return the KeyValue.TYPE byte representation */
1403  byte getTypeByte(int keyLength) {
1404    return this.bytes[this.offset + keyLength - 1 + ROW_OFFSET];
1405  }
1406
1407  /** Return the offset where the tag data starts. */
1408  @Override
1409  public int getTagsOffset() {
1410    int tagsLen = getTagsLength();
1411    if (tagsLen == 0) {
1412      return this.offset + this.length;
1413    }
1414    return this.offset + this.length - tagsLen;
1415  }
1416
1417  /** Return the total length of the tag bytes */
1418  @Override
1419  public int getTagsLength() {
1420    int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE);
1421    if (tagsLen > 0) {
1422      // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags
1423      // length
1424      tagsLen -= TAGS_LENGTH_SIZE;
1425    }
1426    return tagsLen;
1427  }
1428
1429  /**
1430   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1431   */
1432  @Override
1433  public byte[] getTagsArray() {
1434    return bytes;
1435  }
1436
1437  /**
1438   * Creates a new KeyValue that only contains the key portion (the value is set to be null). TODO
1439   * only used by KeyOnlyFilter -- move there.
1440   * @param lenAsVal replace value with the actual value length (false=empty)
1441   */
1442  public KeyValue createKeyOnly(boolean lenAsVal) {
1443    // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen>
1444    // Rebuild as: <keylen:4><0:4><key:keylen>
1445    int dataLen = lenAsVal ? Bytes.SIZEOF_INT : 0;
1446    byte[] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1447    System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1448      Math.min(newBuffer.length, this.length));
1449    Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1450    if (lenAsVal) {
1451      Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1452    }
1453    return new KeyValue(newBuffer);
1454  }
1455
1456  /**
1457   * Find index of passed delimiter walking from start of buffer forwards.
1458   * @param b         the kv serialized byte[] to process
1459   * @param delimiter input delimeter to fetch index from start
1460   * @return Index of delimiter having started from start of <code>b</code> moving rightward.
1461   */
1462  public static int getDelimiter(final byte[] b, int offset, final int length,
1463    final int delimiter) {
1464    if (b == null) {
1465      throw new IllegalArgumentException("Passed buffer is null");
1466    }
1467    int result = -1;
1468    for (int i = offset; i < length + offset; i++) {
1469      if (b[i] == delimiter) {
1470        result = i;
1471        break;
1472      }
1473    }
1474    return result;
1475  }
1476
1477  /**
1478   * Find index of passed delimiter walking from end of buffer backwards.
1479   * @param b         the kv serialized byte[] to process
1480   * @param offset    the offset in the byte[]
1481   * @param length    the length in the byte[]
1482   * @param delimiter input delimeter to fetch index from end
1483   * @return Index of delimiter
1484   */
1485  public static int getDelimiterInReverse(final byte[] b, final int offset, final int length,
1486    final int delimiter) {
1487    if (b == null) {
1488      throw new IllegalArgumentException("Passed buffer is null");
1489    }
1490    int result = -1;
1491    for (int i = (offset + length) - 1; i >= offset; i--) {
1492      if (b[i] == delimiter) {
1493        result = i;
1494        break;
1495      }
1496    }
1497    return result;
1498  }
1499
1500  /**
1501   * A {@link KVComparator} for <code>hbase:meta</code> catalog table {@link KeyValue}s.
1502   * @deprecated : {@link MetaCellComparator#META_COMPARATOR} to be used. Deprecated for hbase 2.0,
1503   *             remove for hbase 3.0.
1504   */
1505  @Deprecated
1506  public static class MetaComparator extends KVComparator {
1507    /**
1508     * Compare key portion of a {@link KeyValue} for keys in <code>hbase:meta</code> table.
1509     */
1510    @Override
1511    public int compare(final Cell left, final Cell right) {
1512      return PrivateCellUtil.compareKeyIgnoresMvcc(MetaCellComparator.META_COMPARATOR, left, right);
1513    }
1514
1515    @Override
1516    public int compareOnlyKeyPortion(Cell left, Cell right) {
1517      return compare(left, right);
1518    }
1519
1520    @Override
1521    public int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
1522      int rlength) {
1523      int leftDelimiter = getDelimiter(left, loffset, llength, HConstants.DELIMITER);
1524      int rightDelimiter = getDelimiter(right, roffset, rlength, HConstants.DELIMITER);
1525      // Compare up to the delimiter
1526      int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset);
1527      int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset);
1528      int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart);
1529      if (result != 0) {
1530        return result;
1531      } else {
1532        if (leftDelimiter < 0 && rightDelimiter >= 0) {
1533          return -1;
1534        } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1535          return 1;
1536        } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1537          return 0;
1538        }
1539      }
1540      // Compare middle bit of the row.
1541      // Move past delimiter
1542      leftDelimiter++;
1543      rightDelimiter++;
1544      int leftFarDelimiter = getDelimiterInReverse(left, leftDelimiter,
1545        llength - (leftDelimiter - loffset), HConstants.DELIMITER);
1546      int rightFarDelimiter = getDelimiterInReverse(right, rightDelimiter,
1547        rlength - (rightDelimiter - roffset), HConstants.DELIMITER);
1548      // Now compare middlesection of row.
1549      lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter;
1550      rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter;
1551      result = super.compareRows(left, leftDelimiter, lpart, right, rightDelimiter, rpart);
1552      if (result != 0) {
1553        return result;
1554      } else {
1555        if (leftDelimiter < 0 && rightDelimiter >= 0) {
1556          return -1;
1557        } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1558          return 1;
1559        } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1560          return 0;
1561        }
1562      }
1563      // Compare last part of row, the rowid.
1564      leftFarDelimiter++;
1565      rightFarDelimiter++;
1566      result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset),
1567        right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
1568      return result;
1569    }
1570
1571    /**
1572     * Don't do any fancy Block Index splitting tricks.
1573     */
1574    @Override
1575    public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
1576      return Arrays.copyOf(rightKey, rightKey.length);
1577    }
1578
1579    /**
1580     * The HFileV2 file format's trailer contains this class name. We reinterpret this and
1581     * instantiate the appropriate comparator. TODO: With V3 consider removing this.
1582     * @return legacy class name for FileFileTrailer#comparatorClassName
1583     */
1584    @Override
1585    public String getLegacyKeyComparatorName() {
1586      return "org.apache.hadoop.hbase.KeyValue$MetaKeyComparator";
1587    }
1588
1589    @Override
1590    protected MetaComparator clone() throws CloneNotSupportedException {
1591      return (MetaComparator) super.clone();
1592    }
1593
1594    /**
1595     * Override the row key comparison to parse and compare the meta row key parts.
1596     */
1597    @Override
1598    protected int compareRowKey(final Cell l, final Cell r) {
1599      byte[] left = l.getRowArray();
1600      int loffset = l.getRowOffset();
1601      int llength = l.getRowLength();
1602      byte[] right = r.getRowArray();
1603      int roffset = r.getRowOffset();
1604      int rlength = r.getRowLength();
1605      return compareRows(left, loffset, llength, right, roffset, rlength);
1606    }
1607  }
1608
1609  /**
1610   * Compare KeyValues. When we compare KeyValues, we only compare the Key portion. This means two
1611   * KeyValues with same Key but different Values are considered the same as far as this Comparator
1612   * is concerned.
1613   * @deprecated : Use {@link CellComparatorImpl}. Deprecated for hbase 2.0, remove for hbase 3.0.
1614   */
1615  @Deprecated
1616  public static class KVComparator implements RawComparator<Cell>, SamePrefixComparator<byte[]> {
1617
1618    /**
1619     * The HFileV2 file format's trailer contains this class name. We reinterpret this and
1620     * instantiate the appropriate comparator. TODO: With V3 consider removing this.
1621     * @return legacy class name for FileFileTrailer#comparatorClassName
1622     */
1623    public String getLegacyKeyComparatorName() {
1624      return "org.apache.hadoop.hbase.KeyValue$KeyComparator";
1625    }
1626
1627    @Override // RawComparator
1628    public int compare(byte[] l, int loff, int llen, byte[] r, int roff, int rlen) {
1629      return compareFlatKey(l, loff, llen, r, roff, rlen);
1630    }
1631
1632    /**
1633     * Compares the only the user specified portion of a Key. This is overridden by MetaComparator.
1634     * @param left  left cell to compare row key
1635     * @param right right cell to compare row key
1636     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1637     */
1638    protected int compareRowKey(final Cell left, final Cell right) {
1639      return CellComparatorImpl.COMPARATOR.compareRows(left, right);
1640    }
1641
1642    /**
1643     * Compares left to right assuming that left,loffset,llength and right,roffset,rlength are full
1644     * KVs laid out in a flat byte[]s.
1645     * @param left    the left kv serialized byte[] to be compared with
1646     * @param loffset the offset in the left byte[]
1647     * @param llength the length in the left byte[]
1648     * @param right   the right kv serialized byte[] to be compared with
1649     * @param roffset the offset in the right byte[]
1650     * @param rlength the length in the right byte[]
1651     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1652     */
1653    public int compareFlatKey(byte[] left, int loffset, int llength, byte[] right, int roffset,
1654      int rlength) {
1655      // Compare row
1656      short lrowlength = Bytes.toShort(left, loffset);
1657      short rrowlength = Bytes.toShort(right, roffset);
1658      int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT, lrowlength, right,
1659        roffset + Bytes.SIZEOF_SHORT, rrowlength);
1660      if (compare != 0) {
1661        return compare;
1662      }
1663
1664      // Compare the rest of the two KVs without making any assumptions about
1665      // the common prefix. This function will not compare rows anyway, so we
1666      // don't need to tell it that the common prefix includes the row.
1667      return compareWithoutRow(0, left, loffset, llength, right, roffset, rlength, rrowlength);
1668    }
1669
1670    public int compareFlatKey(byte[] left, byte[] right) {
1671      return compareFlatKey(left, 0, left.length, right, 0, right.length);
1672    }
1673
1674    // compare a key against row/fam/qual/ts/type
1675    public int compareKey(Cell cell, byte[] row, int roff, int rlen, byte[] fam, int foff, int flen,
1676      byte[] col, int coff, int clen, long ts, byte type) {
1677
1678      int compare =
1679        compareRows(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), row, roff, rlen);
1680      if (compare != 0) {
1681        return compare;
1682      }
1683      // If the column is not specified, the "minimum" key type appears the
1684      // latest in the sorted order, regardless of the timestamp. This is used
1685      // for specifying the last key/value in a given row, because there is no
1686      // "lexicographically last column" (it would be infinitely long). The
1687      // "maximum" key type does not need this behavior.
1688      if (
1689        cell.getFamilyLength() + cell.getQualifierLength() == 0
1690          && cell.getTypeByte() == Type.Minimum.getCode()
1691      ) {
1692        // left is "bigger", i.e. it appears later in the sorted order
1693        return 1;
1694      }
1695      if (flen + clen == 0 && type == Type.Minimum.getCode()) {
1696        return -1;
1697      }
1698
1699      compare = compareFamilies(cell.getFamilyArray(), cell.getFamilyOffset(),
1700        cell.getFamilyLength(), fam, foff, flen);
1701      if (compare != 0) {
1702        return compare;
1703      }
1704      compare = compareColumns(cell.getQualifierArray(), cell.getQualifierOffset(),
1705        cell.getQualifierLength(), col, coff, clen);
1706      if (compare != 0) {
1707        return compare;
1708      }
1709      // Next compare timestamps.
1710      compare = compareTimestamps(cell.getTimestamp(), ts);
1711      if (compare != 0) {
1712        return compare;
1713      }
1714
1715      // Compare types. Let the delete types sort ahead of puts; i.e. types
1716      // of higher numbers sort before those of lesser numbers. Maximum (255)
1717      // appears ahead of everything, and minimum (0) appears after
1718      // everything.
1719      return (0xff & type) - (0xff & cell.getTypeByte());
1720    }
1721
1722    public int compareOnlyKeyPortion(Cell left, Cell right) {
1723      return PrivateCellUtil.compareKeyIgnoresMvcc(CellComparatorImpl.COMPARATOR, left, right);
1724    }
1725
1726    /**
1727     * Compares the Key of a cell -- with fields being more significant in this order: rowkey,
1728     * colfam/qual, timestamp, type, mvcc
1729     */
1730    @Override
1731    public int compare(final Cell left, final Cell right) {
1732      int compare = CellComparatorImpl.COMPARATOR.compare(left, right);
1733      return compare;
1734    }
1735
1736    public int compareTimestamps(final Cell left, final Cell right) {
1737      return CellComparatorImpl.COMPARATOR.compareTimestamps(left, right);
1738    }
1739
1740    /**
1741     * Compares the rows of a cell
1742     * @param left  left cell to compare rows for
1743     * @param right right cell to compare rows for
1744     * @return Result comparing rows.
1745     */
1746    public int compareRows(final Cell left, final Cell right) {
1747      return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
1748        right.getRowArray(), right.getRowOffset(), right.getRowLength());
1749    }
1750
1751    /**
1752     * Get the b[],o,l for left and right rowkey portions and compare.
1753     * @param left    the left kv serialized byte[] to be compared with
1754     * @param loffset the offset in the left byte[]
1755     * @param llength the length in the left byte[]
1756     * @param right   the right kv serialized byte[] to be compared with
1757     * @param roffset the offset in the right byte[]
1758     * @param rlength the length in the right byte[]
1759     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1760     */
1761    public int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
1762      int rlength) {
1763      return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
1764    }
1765
1766    int compareColumns(final Cell left, final short lrowlength, final Cell right,
1767      final short rrowlength) {
1768      return CellComparatorImpl.COMPARATOR.compareColumns(left, right);
1769    }
1770
1771    protected int compareColumns(byte[] left, int loffset, int llength, final int lfamilylength,
1772      byte[] right, int roffset, int rlength, final int rfamilylength) {
1773      // Compare family portion first.
1774      int diff = Bytes.compareTo(left, loffset, lfamilylength, right, roffset, rfamilylength);
1775      if (diff != 0) {
1776        return diff;
1777      }
1778      // Compare qualifier portion
1779      return Bytes.compareTo(left, loffset + lfamilylength, llength - lfamilylength, right,
1780        roffset + rfamilylength, rlength - rfamilylength);
1781    }
1782
1783    static int compareTimestamps(final long ltimestamp, final long rtimestamp) {
1784      // The below older timestamps sorting ahead of newer timestamps looks
1785      // wrong but it is intentional. This way, newer timestamps are first
1786      // found when we iterate over a memstore and newer versions are the
1787      // first we trip over when reading from a store file.
1788      if (ltimestamp < rtimestamp) {
1789        return 1;
1790      } else if (ltimestamp > rtimestamp) {
1791        return -1;
1792      }
1793      return 0;
1794    }
1795
1796    /**
1797     * Overridden
1798     * @param commonPrefix location of expected common prefix
1799     * @param left         the left kv serialized byte[] to be compared with
1800     * @param loffset      the offset in the left byte[]
1801     * @param llength      the length in the left byte[]
1802     * @param right        the right kv serialized byte[] to be compared with
1803     * @param roffset      the offset in the byte[]
1804     * @param rlength      the length in the right byte[]
1805     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1806     */
1807    @Override // SamePrefixComparator
1808    public int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength,
1809      byte[] right, int roffset, int rlength) {
1810      // Compare row
1811      short lrowlength = Bytes.toShort(left, loffset);
1812      short rrowlength;
1813
1814      int comparisonResult = 0;
1815      if (commonPrefix < ROW_LENGTH_SIZE) {
1816        // almost nothing in common
1817        rrowlength = Bytes.toShort(right, roffset);
1818        comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE, lrowlength, right,
1819          roffset + ROW_LENGTH_SIZE, rrowlength);
1820      } else { // the row length is the same
1821        rrowlength = lrowlength;
1822        if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
1823          // The rows are not the same. Exclude the common prefix and compare
1824          // the rest of the two rows.
1825          int common = commonPrefix - ROW_LENGTH_SIZE;
1826          comparisonResult = compareRows(left, loffset + common + ROW_LENGTH_SIZE,
1827            lrowlength - common, right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
1828        }
1829      }
1830      if (comparisonResult != 0) {
1831        return comparisonResult;
1832      }
1833
1834      assert lrowlength == rrowlength;
1835      return compareWithoutRow(commonPrefix, left, loffset, llength, right, roffset, rlength,
1836        lrowlength);
1837    }
1838
1839    /**
1840     * Compare columnFamily, qualifier, timestamp, and key type (everything except the row). This
1841     * method is used both in the normal comparator and the "same-prefix" comparator. Note that we
1842     * are assuming that row portions of both KVs have already been parsed and found identical, and
1843     * we don't validate that assumption here. the length of the common prefix of the two key-values
1844     * being compared, including row length and row
1845     */
1846    private int compareWithoutRow(int commonPrefix, byte[] left, int loffset, int llength,
1847      byte[] right, int roffset, int rlength, short rowlength) {
1848      /***
1849       * KeyValue Format and commonLength:
1850       * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
1851       * ------------------|-------commonLength--------|--------------
1852       */
1853      int commonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rowlength;
1854
1855      // commonLength + TIMESTAMP_TYPE_SIZE
1856      int commonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + commonLength;
1857      // ColumnFamily + Qualifier length.
1858      int lcolumnlength = llength - commonLengthWithTSAndType;
1859      int rcolumnlength = rlength - commonLengthWithTSAndType;
1860
1861      byte ltype = left[loffset + (llength - 1)];
1862      byte rtype = right[roffset + (rlength - 1)];
1863
1864      // If the column is not specified, the "minimum" key type appears the
1865      // latest in the sorted order, regardless of the timestamp. This is used
1866      // for specifying the last key/value in a given row, because there is no
1867      // "lexicographically last column" (it would be infinitely long). The
1868      // "maximum" key type does not need this behavior.
1869      if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
1870        // left is "bigger", i.e. it appears later in the sorted order
1871        return 1;
1872      }
1873      if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
1874        return -1;
1875      }
1876
1877      int lfamilyoffset = commonLength + loffset;
1878      int rfamilyoffset = commonLength + roffset;
1879
1880      // Column family length.
1881      int lfamilylength = left[lfamilyoffset - 1];
1882      int rfamilylength = right[rfamilyoffset - 1];
1883      // If left family size is not equal to right family size, we need not
1884      // compare the qualifiers.
1885      boolean sameFamilySize = (lfamilylength == rfamilylength);
1886      int common = 0;
1887      if (commonPrefix > 0) {
1888        common = Math.max(0, commonPrefix - commonLength);
1889        if (!sameFamilySize) {
1890          // Common should not be larger than Math.min(lfamilylength,
1891          // rfamilylength).
1892          common = Math.min(common, Math.min(lfamilylength, rfamilylength));
1893        } else {
1894          common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
1895        }
1896      }
1897      if (!sameFamilySize) {
1898        // comparing column family is enough.
1899        return Bytes.compareTo(left, lfamilyoffset + common, lfamilylength - common, right,
1900          rfamilyoffset + common, rfamilylength - common);
1901      }
1902      // Compare family & qualifier together.
1903      final int comparison = Bytes.compareTo(left, lfamilyoffset + common, lcolumnlength - common,
1904        right, rfamilyoffset + common, rcolumnlength - common);
1905      if (comparison != 0) {
1906        return comparison;
1907      }
1908
1909      ////
1910      // Next compare timestamps.
1911      long ltimestamp = Bytes.toLong(left, loffset + (llength - TIMESTAMP_TYPE_SIZE));
1912      long rtimestamp = Bytes.toLong(right, roffset + (rlength - TIMESTAMP_TYPE_SIZE));
1913      int compare = compareTimestamps(ltimestamp, rtimestamp);
1914      if (compare != 0) {
1915        return compare;
1916      }
1917
1918      // Compare types. Let the delete types sort ahead of puts; i.e. types
1919      // of higher numbers sort before those of lesser numbers. Maximum (255)
1920      // appears ahead of everything, and minimum (0) appears after
1921      // everything.
1922      return (0xff & rtype) - (0xff & ltype);
1923    }
1924
1925    protected int compareFamilies(final byte[] left, final int loffset, final int lfamilylength,
1926      final byte[] right, final int roffset, final int rfamilylength) {
1927      int diff = Bytes.compareTo(left, loffset, lfamilylength, right, roffset, rfamilylength);
1928      return diff;
1929    }
1930
1931    protected int compareColumns(final byte[] left, final int loffset, final int lquallength,
1932      final byte[] right, final int roffset, final int rquallength) {
1933      int diff = Bytes.compareTo(left, loffset, lquallength, right, roffset, rquallength);
1934      return diff;
1935    }
1936
1937    /**
1938     * Compares the row and column of two keyvalues for equality
1939     * @param left  left cell to compare row and column
1940     * @param right right cell to compare row and column
1941     * @return True if same row and column.
1942     */
1943    public boolean matchingRowColumn(final Cell left, final Cell right) {
1944      short lrowlength = left.getRowLength();
1945      short rrowlength = right.getRowLength();
1946
1947      // TsOffset = end of column data. just comparing Row+CF length of each
1948      if (
1949        (left.getRowLength() + left.getFamilyLength() + left.getQualifierLength())
1950            != (right.getRowLength() + right.getFamilyLength() + right.getQualifierLength())
1951      ) {
1952        return false;
1953      }
1954
1955      if (!matchingRows(left, lrowlength, right, rrowlength)) {
1956        return false;
1957      }
1958
1959      int lfoffset = left.getFamilyOffset();
1960      int rfoffset = right.getFamilyOffset();
1961      int lclength = left.getQualifierLength();
1962      int rclength = right.getQualifierLength();
1963      int lfamilylength = left.getFamilyLength();
1964      int rfamilylength = right.getFamilyLength();
1965      int diff = compareFamilies(left.getFamilyArray(), lfoffset, lfamilylength,
1966        right.getFamilyArray(), rfoffset, rfamilylength);
1967      if (diff != 0) {
1968        return false;
1969      } else {
1970        diff = compareColumns(left.getQualifierArray(), left.getQualifierOffset(), lclength,
1971          right.getQualifierArray(), right.getQualifierOffset(), rclength);
1972        return diff == 0;
1973      }
1974    }
1975
1976    /**
1977     * Compares the row of two keyvalues for equality
1978     * @param left  left cell to compare row
1979     * @param right right cell to compare row
1980     * @return True if rows match.
1981     */
1982    public boolean matchingRows(final Cell left, final Cell right) {
1983      short lrowlength = left.getRowLength();
1984      short rrowlength = right.getRowLength();
1985      return matchingRows(left, lrowlength, right, rrowlength);
1986    }
1987
1988    /**
1989     * Compares the row of two keyvalues for equality
1990     * @param left       left cell to compare row
1991     * @param lrowlength left row length
1992     * @param right      right cell to compare row
1993     * @param rrowlength right row length
1994     * @return True if rows match.
1995     */
1996    private boolean matchingRows(final Cell left, final short lrowlength, final Cell right,
1997      final short rrowlength) {
1998      return lrowlength == rrowlength && matchingRows(left.getRowArray(), left.getRowOffset(),
1999        lrowlength, right.getRowArray(), right.getRowOffset(), rrowlength);
2000    }
2001
2002    /**
2003     * Compare rows. Just calls Bytes.equals, but it's good to have this encapsulated.
2004     * @param left    Left row array.
2005     * @param loffset Left row offset.
2006     * @param llength Left row length.
2007     * @param right   Right row array.
2008     * @param roffset Right row offset.
2009     * @param rlength Right row length.
2010     * @return Whether rows are the same row.
2011     */
2012    public boolean matchingRows(final byte[] left, final int loffset, final int llength,
2013      final byte[] right, final int roffset, final int rlength) {
2014      return Bytes.equals(left, loffset, llength, right, roffset, rlength);
2015    }
2016
2017    public byte[] calcIndexKey(byte[] lastKeyOfPreviousBlock, byte[] firstKeyInBlock) {
2018      byte[] fakeKey = getShortMidpointKey(lastKeyOfPreviousBlock, firstKeyInBlock);
2019      if (compareFlatKey(fakeKey, firstKeyInBlock) > 0) {
2020        LOG.error("Unexpected getShortMidpointKey result, fakeKey:" + Bytes.toStringBinary(fakeKey)
2021          + ", firstKeyInBlock:" + Bytes.toStringBinary(firstKeyInBlock));
2022        return firstKeyInBlock;
2023      }
2024      if (lastKeyOfPreviousBlock != null && compareFlatKey(lastKeyOfPreviousBlock, fakeKey) >= 0) {
2025        LOG.error("Unexpected getShortMidpointKey result, lastKeyOfPreviousBlock:"
2026          + Bytes.toStringBinary(lastKeyOfPreviousBlock) + ", fakeKey:"
2027          + Bytes.toStringBinary(fakeKey));
2028        return firstKeyInBlock;
2029      }
2030      return fakeKey;
2031    }
2032
2033    /**
2034     * This is a HFile block index key optimization.
2035     * @param leftKey  byte array for left Key
2036     * @param rightKey byte array for right Key
2037     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
2038     * @deprecated Since 0.99.2;
2039     */
2040    @Deprecated
2041    public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
2042      if (rightKey == null) {
2043        throw new IllegalArgumentException("rightKey can not be null");
2044      }
2045      if (leftKey == null) {
2046        return Arrays.copyOf(rightKey, rightKey.length);
2047      }
2048      if (compareFlatKey(leftKey, rightKey) >= 0) {
2049        throw new IllegalArgumentException("Unexpected input, leftKey:" + Bytes.toString(leftKey)
2050          + ", rightKey:" + Bytes.toString(rightKey));
2051      }
2052
2053      short leftRowLength = Bytes.toShort(leftKey, 0);
2054      short rightRowLength = Bytes.toShort(rightKey, 0);
2055      int leftCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + leftRowLength;
2056      int rightCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rightRowLength;
2057      int leftCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + leftCommonLength;
2058      int rightCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + rightCommonLength;
2059      int leftColumnLength = leftKey.length - leftCommonLengthWithTSAndType;
2060      int rightColumnLength = rightKey.length - rightCommonLengthWithTSAndType;
2061      // rows are equal
2062      if (
2063        leftRowLength == rightRowLength && compareRows(leftKey, ROW_LENGTH_SIZE, leftRowLength,
2064          rightKey, ROW_LENGTH_SIZE, rightRowLength) == 0
2065      ) {
2066        // Compare family & qualifier together.
2067        int comparison = Bytes.compareTo(leftKey, leftCommonLength, leftColumnLength, rightKey,
2068          rightCommonLength, rightColumnLength);
2069        // same with "row + family + qualifier", return rightKey directly
2070        if (comparison == 0) {
2071          return Arrays.copyOf(rightKey, rightKey.length);
2072        }
2073        // "family + qualifier" are different, generate a faked key per rightKey
2074        byte[] newKey = Arrays.copyOf(rightKey, rightKey.length);
2075        Bytes.putLong(newKey, rightKey.length - TIMESTAMP_TYPE_SIZE, HConstants.LATEST_TIMESTAMP);
2076        Bytes.putByte(newKey, rightKey.length - TYPE_SIZE, Type.Maximum.getCode());
2077        return newKey;
2078      }
2079      // rows are different
2080      short minLength = leftRowLength < rightRowLength ? leftRowLength : rightRowLength;
2081      short diffIdx = 0;
2082      while (
2083        diffIdx < minLength
2084          && leftKey[ROW_LENGTH_SIZE + diffIdx] == rightKey[ROW_LENGTH_SIZE + diffIdx]
2085      ) {
2086        diffIdx++;
2087      }
2088      byte[] newRowKey = null;
2089      if (diffIdx >= minLength) {
2090        // leftKey's row is prefix of rightKey's.
2091        newRowKey = new byte[diffIdx + 1];
2092        System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1);
2093      } else {
2094        int diffByte = leftKey[ROW_LENGTH_SIZE + diffIdx];
2095        if (
2096          (0xff & diffByte) < 0xff && (diffByte + 1) < (rightKey[ROW_LENGTH_SIZE + diffIdx] & 0xff)
2097        ) {
2098          newRowKey = new byte[diffIdx + 1];
2099          System.arraycopy(leftKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx);
2100          newRowKey[diffIdx] = (byte) (diffByte + 1);
2101        } else {
2102          newRowKey = new byte[diffIdx + 1];
2103          System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1);
2104        }
2105      }
2106      return new KeyValue(newRowKey, null, null, HConstants.LATEST_TIMESTAMP, Type.Maximum)
2107        .getKey();
2108    }
2109
2110    @Override
2111    protected KVComparator clone() throws CloneNotSupportedException {
2112      return (KVComparator) super.clone();
2113    }
2114
2115  }
2116
2117  /**
2118   * Create a KeyValue reading from <code>in</code>
2119   * @param in Where to read bytes from. Creates a byte array to hold the KeyValue backing bytes
2120   *           copied from the steam.
2121   * @return KeyValue created by deserializing from <code>in</code> OR if we find a length of zero,
2122   *         we will return null which can be useful marking a stream as done.
2123   * @throws IOException if any IO error happen
2124   */
2125  public static KeyValue create(final DataInput in) throws IOException {
2126    return create(in.readInt(), in);
2127  }
2128
2129  /**
2130   * Create a KeyValue reading <code>length</code> from <code>in</code>
2131   * @param length length of the Key
2132   * @param in     Input to read from
2133   * @return Created KeyValue OR if we find a length of zero, we will return null which can be
2134   *         useful marking a stream as done.
2135   * @throws IOException if any IO error happen
2136   */
2137  public static KeyValue create(int length, final DataInput in) throws IOException {
2138
2139    if (length <= 0) {
2140      if (length == 0) {
2141        return null;
2142      }
2143      throw new IOException("Failed read " + length + " bytes, stream corrupt?");
2144    }
2145
2146    // This is how the old Writables.readFrom used to deserialize. Didn't even vint.
2147    byte[] bytes = new byte[length];
2148    in.readFully(bytes);
2149    return new KeyValue(bytes, 0, length);
2150  }
2151
2152  /**
2153   * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable.
2154   * @param kv  the KeyValue on which write is being requested
2155   * @param out OutputStream to write keyValue to
2156   * @return Length written on stream
2157   * @throws IOException if any IO error happen
2158   * @see #create(DataInput) for the inverse function
2159   */
2160  public static long write(final KeyValue kv, final DataOutput out) throws IOException {
2161    // This is how the old Writables write used to serialize KVs. Need to figure way to make it
2162    // work for all implementations.
2163    int length = kv.getLength();
2164    out.writeInt(length);
2165    out.write(kv.getBuffer(), kv.getOffset(), length);
2166    return (long) length + Bytes.SIZEOF_INT;
2167  }
2168
2169  /**
2170   * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable but do not
2171   * require a {@link DataOutput}, just take plain {@link OutputStream} Named <code>oswrite</code>
2172   * so does not clash with {@link #write(KeyValue, DataOutput)}
2173   * @param kv       the KeyValue on which write is being requested
2174   * @param out      OutputStream to write keyValue to
2175   * @param withTags boolean value indicating write is with Tags or not
2176   * @return Length written on stream
2177   * @throws IOException if any IO error happen
2178   * @see #create(DataInput) for the inverse function
2179   * @see #write(KeyValue, DataOutput)
2180   * @see KeyValueUtil#oswrite(Cell, OutputStream, boolean)
2181   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use
2182   *             {@link #write(OutputStream, boolean)}
2183   */
2184  @Deprecated
2185  public static long oswrite(final KeyValue kv, final OutputStream out, final boolean withTags)
2186    throws IOException {
2187    ByteBufferUtils.putInt(out, kv.getSerializedSize(withTags));
2188    return (long) kv.write(out, withTags) + Bytes.SIZEOF_INT;
2189  }
2190
2191  @Override
2192  public int write(OutputStream out, boolean withTags) throws IOException {
2193    int len = getSerializedSize(withTags);
2194    out.write(this.bytes, this.offset, len);
2195    return len;
2196  }
2197
2198  @Override
2199  public int getSerializedSize(boolean withTags) {
2200    if (withTags) {
2201      return this.length;
2202    }
2203    return this.getKeyLength() + this.getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE;
2204  }
2205
2206  @Override
2207  public int getSerializedSize() {
2208    return this.length;
2209  }
2210
2211  @Override
2212  public void write(ByteBuffer buf, int offset) {
2213    ByteBufferUtils.copyFromArrayToBuffer(buf, offset, this.bytes, this.offset, this.length);
2214  }
2215
2216  /**
2217   * Avoids redundant comparisons for better performance. TODO get rid of this wart
2218   */
2219  public interface SamePrefixComparator<T> {
2220    /**
2221     * Compare two keys assuming that the first n bytes are the same.
2222     * @param commonPrefix How many bytes are the same.
2223     */
2224    int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength, byte[] right,
2225      int roffset, int rlength);
2226  }
2227
2228  /**
2229   * HeapSize implementation
2230   * <p/>
2231   * We do not count the bytes in the rowCache because it should be empty for a KeyValue in the
2232   * MemStore.
2233   */
2234  @Override
2235  public long heapSize() {
2236    // Deep object overhead for this KV consists of two parts. The first part is the KV object
2237    // itself, while the second part is the backing byte[]. We will only count the array overhead
2238    // from the byte[] only if this is the first KV in there.
2239    int fixed = ClassSize.align(FIXED_OVERHEAD);
2240    if (offset == 0) {
2241      // count both length and object overhead
2242      return fixed + ClassSize.sizeOfByteArray(length);
2243    } else {
2244      // only count the number of bytes
2245      return (long) fixed + length;
2246    }
2247  }
2248
2249  /**
2250   * A simple form of KeyValue that creates a keyvalue with only the key part of the byte[] Mainly
2251   * used in places where we need to compare two cells. Avoids copying of bytes In places like block
2252   * index keys, we need to compare the key byte[] with a cell. Hence create a Keyvalue(aka Cell)
2253   * that would help in comparing as two cells
2254   */
2255  public static class KeyOnlyKeyValue extends KeyValue {
2256    private short rowLen = -1;
2257
2258    public KeyOnlyKeyValue() {
2259
2260    }
2261
2262    public KeyOnlyKeyValue(byte[] b) {
2263      this(b, 0, b.length);
2264    }
2265
2266    public KeyOnlyKeyValue(byte[] b, int offset, int length) {
2267      this.bytes = b;
2268      this.length = length;
2269      this.offset = offset;
2270      this.rowLen = Bytes.toShort(this.bytes, this.offset);
2271    }
2272
2273    public void set(KeyOnlyKeyValue keyOnlyKeyValue) {
2274      this.bytes = keyOnlyKeyValue.bytes;
2275      this.length = keyOnlyKeyValue.length;
2276      this.offset = keyOnlyKeyValue.offset;
2277      this.rowLen = keyOnlyKeyValue.rowLen;
2278    }
2279
2280    public void clear() {
2281      rowLen = -1;
2282      bytes = null;
2283      offset = 0;
2284      length = 0;
2285    }
2286
2287    @Override
2288    public int getKeyOffset() {
2289      return this.offset;
2290    }
2291
2292    /**
2293     * A setter that helps to avoid object creation every time and whenever there is a need to
2294     * create new KeyOnlyKeyValue.
2295     * @param key    Key to set
2296     * @param offset Offset of the Key
2297     * @param length length of the Key
2298     */
2299    public void setKey(byte[] key, int offset, int length) {
2300      this.bytes = key;
2301      this.offset = offset;
2302      this.length = length;
2303      this.rowLen = Bytes.toShort(this.bytes, this.offset);
2304    }
2305
2306    @Override
2307    public byte[] getKey() {
2308      int keylength = getKeyLength();
2309      byte[] key = new byte[keylength];
2310      System.arraycopy(this.bytes, getKeyOffset(), key, 0, keylength);
2311      return key;
2312    }
2313
2314    @Override
2315    public byte[] getRowArray() {
2316      return bytes;
2317    }
2318
2319    @Override
2320    public int getRowOffset() {
2321      return getKeyOffset() + Bytes.SIZEOF_SHORT;
2322    }
2323
2324    @Override
2325    public byte[] getFamilyArray() {
2326      return bytes;
2327    }
2328
2329    @Override
2330    public byte getFamilyLength() {
2331      return this.bytes[getFamilyOffset() - 1];
2332    }
2333
2334    @Override
2335    int getFamilyLengthPosition(int rowLength) {
2336      return this.offset + Bytes.SIZEOF_SHORT + rowLength;
2337    }
2338
2339    @Override
2340    public int getFamilyOffset() {
2341      return this.offset + Bytes.SIZEOF_SHORT + getRowLength() + Bytes.SIZEOF_BYTE;
2342    }
2343
2344    @Override
2345    public byte[] getQualifierArray() {
2346      return bytes;
2347    }
2348
2349    @Override
2350    public int getQualifierLength() {
2351      return getQualifierLength(getRowLength(), getFamilyLength());
2352    }
2353
2354    @Override
2355    public int getQualifierOffset() {
2356      return getFamilyOffset() + getFamilyLength();
2357    }
2358
2359    @Override
2360    public int getKeyLength() {
2361      return length;
2362    }
2363
2364    @Override
2365    public short getRowLength() {
2366      return rowLen;
2367    }
2368
2369    @Override
2370    public byte getTypeByte() {
2371      return getTypeByte(getKeyLength());
2372    }
2373
2374    @Override
2375    byte getTypeByte(int keyLength) {
2376      return this.bytes[this.offset + keyLength - 1];
2377    }
2378
2379    private int getQualifierLength(int rlength, int flength) {
2380      return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0);
2381    }
2382
2383    @Override
2384    public long getTimestamp() {
2385      int tsOffset = getTimestampOffset();
2386      return Bytes.toLong(this.bytes, tsOffset);
2387    }
2388
2389    @Override
2390    public int getTimestampOffset() {
2391      return getKeyOffset() + getKeyLength() - TIMESTAMP_TYPE_SIZE;
2392    }
2393
2394    @Override
2395    public byte[] getTagsArray() {
2396      return HConstants.EMPTY_BYTE_ARRAY;
2397    }
2398
2399    @Override
2400    public int getTagsOffset() {
2401      return 0;
2402    }
2403
2404    @Override
2405    public byte[] getValueArray() {
2406      throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2407    }
2408
2409    @Override
2410    public int getValueOffset() {
2411      throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2412    }
2413
2414    @Override
2415    public int getValueLength() {
2416      throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2417    }
2418
2419    @Override
2420    public int getTagsLength() {
2421      return 0;
2422    }
2423
2424    @Override
2425    public String toString() {
2426      if (this.bytes == null || this.bytes.length == 0) {
2427        return "empty";
2428      }
2429      return keyToString(this.bytes, this.offset, getKeyLength()) + "/vlen=0/mvcc=0";
2430    }
2431
2432    @Override
2433    public int hashCode() {
2434      return super.hashCode();
2435    }
2436
2437    @Override
2438    public boolean equals(Object other) {
2439      return super.equals(other);
2440    }
2441
2442    @Override
2443    public long heapSize() {
2444      return super.heapSize() + Bytes.SIZEOF_SHORT;
2445    }
2446
2447    @Override
2448    public int write(OutputStream out, boolean withTags) throws IOException {
2449      // This type of Cell is used only to maintain some internal states. We never allow this type
2450      // of Cell to be returned back over the RPC
2451      throw new IllegalStateException("A reader should never return this type of a Cell");
2452    }
2453  }
2454
2455  @Override
2456  public ExtendedCell deepClone() {
2457    byte[] copy = Bytes.copy(this.bytes, this.offset, this.length);
2458    KeyValue kv = new KeyValue(copy, 0, copy.length);
2459    kv.setSequenceId(this.getSequenceId());
2460    return kv;
2461  }
2462}