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  /**
1079   * @param k Key portion of a KeyValue.
1080   * @return Key as a String, empty string if k is null.
1081   */
1082  public static String keyToString(final byte[] k) {
1083    if (k == null) {
1084      return "";
1085    }
1086    return keyToString(k, 0, k.length);
1087  }
1088
1089  /**
1090   * Produces a string map for this key/value pair. Useful for programmatic use and manipulation of
1091   * the data stored in an WALKey, for example, printing as JSON. Values are left out due to their
1092   * tendency to be large. If needed, they can be added manually.
1093   * @return the Map&lt;String,?&gt; containing data from this key
1094   */
1095  public Map<String, Object> toStringMap() {
1096    Map<String, Object> stringMap = new HashMap<>();
1097    stringMap.put("row", Bytes.toStringBinary(getRowArray(), getRowOffset(), getRowLength()));
1098    stringMap.put("family",
1099      Bytes.toStringBinary(getFamilyArray(), getFamilyOffset(), getFamilyLength()));
1100    stringMap.put("qualifier",
1101      Bytes.toStringBinary(getQualifierArray(), getQualifierOffset(), getQualifierLength()));
1102    stringMap.put("timestamp", getTimestamp());
1103    stringMap.put("vlen", getValueLength());
1104    Iterator<Tag> tags = getTags();
1105    if (tags != null) {
1106      List<String> tagsString = new ArrayList<String>();
1107      while (tags.hasNext()) {
1108        tagsString.add(tags.next().toString());
1109      }
1110      stringMap.put("tag", tagsString);
1111    }
1112    return stringMap;
1113  }
1114
1115  /**
1116   * Use for logging.
1117   * @param b Key portion of a KeyValue.
1118   * @param o Offset to start of key
1119   * @param l Length of key.
1120   * @return Key as a String.
1121   */
1122  public static String keyToString(final byte[] b, final int o, final int l) {
1123    if (b == null) {
1124      return "";
1125    }
1126    int rowlength = Bytes.toShort(b, o);
1127    String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
1128    int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
1129    int familylength = b[columnoffset - 1];
1130    int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
1131    String family = familylength == 0 ? "" : Bytes.toStringBinary(b, columnoffset, familylength);
1132    String qualifier = columnlength == 0
1133      ? ""
1134      : Bytes.toStringBinary(b, columnoffset + familylength, columnlength - familylength);
1135    long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
1136    String timestampStr = humanReadableTimestamp(timestamp);
1137    byte type = b[o + l - 1];
1138    return row + "/" + family + (family != null && family.length() > 0 ? ":" : "") + qualifier + "/"
1139      + timestampStr + "/" + Type.codeToType(type);
1140  }
1141
1142  public static String humanReadableTimestamp(final long timestamp) {
1143    if (timestamp == HConstants.LATEST_TIMESTAMP) {
1144      return "LATEST_TIMESTAMP";
1145    }
1146    if (timestamp == PrivateConstants.OLDEST_TIMESTAMP) {
1147      return "OLDEST_TIMESTAMP";
1148    }
1149    return String.valueOf(timestamp);
1150  }
1151
1152  // ---------------------------------------------------------------------------
1153  //
1154  // Public Member Accessors
1155  //
1156  // ---------------------------------------------------------------------------
1157
1158  /**
1159   * To be used only in tests where the Cells are clearly assumed to be of type KeyValue and that we
1160   * need access to the backing array to do some test case related assertions.
1161   * @return The byte array backing this KeyValue.
1162   */
1163  public byte[] getBuffer() {
1164    return this.bytes;
1165  }
1166
1167  /** Returns Offset into {@link #getBuffer()} at which this KeyValue starts. */
1168  public int getOffset() {
1169    return this.offset;
1170  }
1171
1172  /** Returns Length of bytes this KeyValue occupies in {@link #getBuffer()}. */
1173  public int getLength() {
1174    return length;
1175  }
1176
1177  // ---------------------------------------------------------------------------
1178  //
1179  // Length and Offset Calculators
1180  //
1181  // ---------------------------------------------------------------------------
1182
1183  /**
1184   * Determines the total length of the KeyValue stored in the specified byte array and offset.
1185   * Includes all headers.
1186   * @param bytes  byte array
1187   * @param offset offset to start of the KeyValue
1188   * @return length of entire KeyValue, in bytes
1189   */
1190  private static int getLength(byte[] bytes, int offset) {
1191    int klength = ROW_OFFSET + Bytes.toInt(bytes, offset);
1192    int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
1193    return klength + vlength;
1194  }
1195
1196  /** Returns Key offset in backing buffer.. */
1197  public int getKeyOffset() {
1198    return this.offset + ROW_OFFSET;
1199  }
1200
1201  public String getKeyString() {
1202    return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
1203  }
1204
1205  /** Returns Length of key portion. */
1206  public int getKeyLength() {
1207    return Bytes.toInt(this.bytes, this.offset);
1208  }
1209
1210  /**
1211   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1212   */
1213  @Override
1214  public byte[] getValueArray() {
1215    return bytes;
1216  }
1217
1218  /** Returns the value offset */
1219  @Override
1220  public int getValueOffset() {
1221    int voffset = getKeyOffset() + getKeyLength();
1222    return voffset;
1223  }
1224
1225  /** Returns Value length */
1226  @Override
1227  public int getValueLength() {
1228    int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
1229    return vlength;
1230  }
1231
1232  /**
1233   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1234   */
1235  @Override
1236  public byte[] getRowArray() {
1237    return bytes;
1238  }
1239
1240  /** Returns Row offset */
1241  @Override
1242  public int getRowOffset() {
1243    return this.offset + ROW_KEY_OFFSET;
1244  }
1245
1246  /** Returns Row length */
1247  @Override
1248  public short getRowLength() {
1249    return Bytes.toShort(this.bytes, getKeyOffset());
1250  }
1251
1252  /**
1253   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1254   */
1255  @Override
1256  public byte[] getFamilyArray() {
1257    return bytes;
1258  }
1259
1260  /** Returns Family offset */
1261  @Override
1262  public int getFamilyOffset() {
1263    return getFamilyOffset(getFamilyLengthPosition(getRowLength()));
1264  }
1265
1266  /** Returns Family offset */
1267  int getFamilyOffset(int familyLenPosition) {
1268    return familyLenPosition + Bytes.SIZEOF_BYTE;
1269  }
1270
1271  /** Returns Family length */
1272  @Override
1273  public byte getFamilyLength() {
1274    return getFamilyLength(getFamilyLengthPosition(getRowLength()));
1275  }
1276
1277  /** Returns Family length */
1278  public byte getFamilyLength(int famLenPos) {
1279    return this.bytes[famLenPos];
1280  }
1281
1282  int getFamilyLengthPosition(int rowLength) {
1283    return this.offset + KeyValue.ROW_KEY_OFFSET + rowLength;
1284  }
1285
1286  /**
1287   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1288   */
1289  @Override
1290  public byte[] getQualifierArray() {
1291    return bytes;
1292  }
1293
1294  /** Returns Qualifier offset */
1295  @Override
1296  public int getQualifierOffset() {
1297    return getQualifierOffset(getFamilyOffset());
1298  }
1299
1300  /** Returns Qualifier offset */
1301  private int getQualifierOffset(int foffset) {
1302    return getQualifierOffset(foffset, getFamilyLength());
1303  }
1304
1305  /** Returns Qualifier offset */
1306  int getQualifierOffset(int foffset, int flength) {
1307    return foffset + flength;
1308  }
1309
1310  /** Returns Qualifier length */
1311  @Override
1312  public int getQualifierLength() {
1313    return getQualifierLength(getRowLength(), getFamilyLength());
1314  }
1315
1316  /** Returns Qualifier length */
1317  private int getQualifierLength(int rlength, int flength) {
1318    return getQualifierLength(getKeyLength(), rlength, flength);
1319  }
1320
1321  /** Returns Qualifier length */
1322  int getQualifierLength(int keyLength, int rlength, int flength) {
1323    return keyLength - (int) getKeyDataStructureSize(rlength, flength, 0);
1324  }
1325
1326  /** Returns Timestamp offset */
1327  public int getTimestampOffset() {
1328    return getTimestampOffset(getKeyLength());
1329  }
1330
1331  /**
1332   * @param keylength Pass if you have it to save on a int creation.
1333   * @return Timestamp offset
1334   */
1335  private int getTimestampOffset(final int keylength) {
1336    return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
1337  }
1338
1339  /** Returns True if this KeyValue has a LATEST_TIMESTAMP timestamp. */
1340  public boolean isLatestTimestamp() {
1341    return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
1342      HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
1343  }
1344
1345  /**
1346   * @param now Time to set into <code>this</code> IFF timestamp ==
1347   *            {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
1348   * @return True is we modified this.
1349   */
1350  public boolean updateLatestStamp(final byte[] now) {
1351    if (this.isLatestTimestamp()) {
1352      int tsOffset = getTimestampOffset();
1353      System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
1354      // clear cache or else getTimestamp() possibly returns an old value
1355      return true;
1356    }
1357    return false;
1358  }
1359
1360  @Override
1361  public void setTimestamp(long ts) {
1362    Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG);
1363  }
1364
1365  @Override
1366  public void setTimestamp(byte[] ts) {
1367    Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, 0, Bytes.SIZEOF_LONG);
1368  }
1369
1370  // ---------------------------------------------------------------------------
1371  //
1372  // Methods that return copies of fields
1373  //
1374  // ---------------------------------------------------------------------------
1375
1376  /**
1377   * Do not use unless you have to. Used internally for compacting and testing. Use
1378   * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and
1379   * {@link #getValueArray()} if accessing a KeyValue client-side.
1380   * @return Copy of the key portion only.
1381   */
1382  public byte[] getKey() {
1383    int keylength = getKeyLength();
1384    byte[] key = new byte[keylength];
1385    System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
1386    return key;
1387  }
1388
1389  /**
1390   * n
1391   */
1392  @Override
1393  public long getTimestamp() {
1394    return getTimestamp(getKeyLength());
1395  }
1396
1397  /**
1398   * @param keylength Pass if you have it to save on a int creation. n
1399   */
1400  long getTimestamp(final int keylength) {
1401    int tsOffset = getTimestampOffset(keylength);
1402    return Bytes.toLong(this.bytes, tsOffset);
1403  }
1404
1405  /** Returns KeyValue.TYPE byte representation */
1406  @Override
1407  public byte getTypeByte() {
1408    return getTypeByte(getKeyLength());
1409  }
1410
1411  byte getTypeByte(int keyLength) {
1412    return this.bytes[this.offset + keyLength - 1 + ROW_OFFSET];
1413  }
1414
1415  /**
1416   * This returns the offset where the tag actually starts.
1417   */
1418  @Override
1419  public int getTagsOffset() {
1420    int tagsLen = getTagsLength();
1421    if (tagsLen == 0) {
1422      return this.offset + this.length;
1423    }
1424    return this.offset + this.length - tagsLen;
1425  }
1426
1427  /**
1428   * This returns the total length of the tag bytes
1429   */
1430  @Override
1431  public int getTagsLength() {
1432    int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE);
1433    if (tagsLen > 0) {
1434      // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags
1435      // length
1436      tagsLen -= TAGS_LENGTH_SIZE;
1437    }
1438    return tagsLen;
1439  }
1440
1441  /**
1442   * Returns the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1443   */
1444  @Override
1445  public byte[] getTagsArray() {
1446    return bytes;
1447  }
1448
1449  /**
1450   * Creates a new KeyValue that only contains the key portion (the value is set to be null). TODO
1451   * only used by KeyOnlyFilter -- move there.
1452   * @param lenAsVal replace value with the actual value length (false=empty)
1453   */
1454  public KeyValue createKeyOnly(boolean lenAsVal) {
1455    // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen>
1456    // Rebuild as: <keylen:4><0:4><key:keylen>
1457    int dataLen = lenAsVal ? Bytes.SIZEOF_INT : 0;
1458    byte[] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1459    System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1460      Math.min(newBuffer.length, this.length));
1461    Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1462    if (lenAsVal) {
1463      Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1464    }
1465    return new KeyValue(newBuffer);
1466  }
1467
1468  /**
1469   * @param b         the kv serialized byte[] to process
1470   * @param delimiter input delimeter to fetch index from start
1471   * @return Index of delimiter having started from start of <code>b</code> moving rightward.
1472   */
1473  public static int getDelimiter(final byte[] b, int offset, final int length,
1474    final int delimiter) {
1475    if (b == null) {
1476      throw new IllegalArgumentException("Passed buffer is null");
1477    }
1478    int result = -1;
1479    for (int i = offset; i < length + offset; i++) {
1480      if (b[i] == delimiter) {
1481        result = i;
1482        break;
1483      }
1484    }
1485    return result;
1486  }
1487
1488  /**
1489   * Find index of passed delimiter walking from end of buffer backwards.
1490   * @param b         the kv serialized byte[] to process
1491   * @param offset    the offset in the byte[]
1492   * @param length    the length in the byte[]
1493   * @param delimiter input delimeter to fetch index from end
1494   * @return Index of delimiter
1495   */
1496  public static int getDelimiterInReverse(final byte[] b, final int offset, final int length,
1497    final int delimiter) {
1498    if (b == null) {
1499      throw new IllegalArgumentException("Passed buffer is null");
1500    }
1501    int result = -1;
1502    for (int i = (offset + length) - 1; i >= offset; i--) {
1503      if (b[i] == delimiter) {
1504        result = i;
1505        break;
1506      }
1507    }
1508    return result;
1509  }
1510
1511  /**
1512   * A {@link KVComparator} for <code>hbase:meta</code> catalog table {@link KeyValue}s.
1513   * @deprecated : {@link MetaCellComparator#META_COMPARATOR} to be used. Deprecated for hbase 2.0,
1514   *             remove for hbase 3.0.
1515   */
1516  @Deprecated
1517  public static class MetaComparator extends KVComparator {
1518    /**
1519     * Compare key portion of a {@link KeyValue} for keys in <code>hbase:meta</code> table.
1520     */
1521    @Override
1522    public int compare(final Cell left, final Cell right) {
1523      return PrivateCellUtil.compareKeyIgnoresMvcc(MetaCellComparator.META_COMPARATOR, left, right);
1524    }
1525
1526    @Override
1527    public int compareOnlyKeyPortion(Cell left, Cell right) {
1528      return compare(left, right);
1529    }
1530
1531    @Override
1532    public int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
1533      int rlength) {
1534      int leftDelimiter = getDelimiter(left, loffset, llength, HConstants.DELIMITER);
1535      int rightDelimiter = getDelimiter(right, roffset, rlength, HConstants.DELIMITER);
1536      // Compare up to the delimiter
1537      int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset);
1538      int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset);
1539      int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart);
1540      if (result != 0) {
1541        return result;
1542      } else {
1543        if (leftDelimiter < 0 && rightDelimiter >= 0) {
1544          return -1;
1545        } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1546          return 1;
1547        } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1548          return 0;
1549        }
1550      }
1551      // Compare middle bit of the row.
1552      // Move past delimiter
1553      leftDelimiter++;
1554      rightDelimiter++;
1555      int leftFarDelimiter = getDelimiterInReverse(left, leftDelimiter,
1556        llength - (leftDelimiter - loffset), HConstants.DELIMITER);
1557      int rightFarDelimiter = getDelimiterInReverse(right, rightDelimiter,
1558        rlength - (rightDelimiter - roffset), HConstants.DELIMITER);
1559      // Now compare middlesection of row.
1560      lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter;
1561      rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter;
1562      result = super.compareRows(left, leftDelimiter, lpart, right, rightDelimiter, rpart);
1563      if (result != 0) {
1564        return result;
1565      } else {
1566        if (leftDelimiter < 0 && rightDelimiter >= 0) {
1567          return -1;
1568        } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1569          return 1;
1570        } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1571          return 0;
1572        }
1573      }
1574      // Compare last part of row, the rowid.
1575      leftFarDelimiter++;
1576      rightFarDelimiter++;
1577      result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset),
1578        right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
1579      return result;
1580    }
1581
1582    /**
1583     * Don't do any fancy Block Index splitting tricks.
1584     */
1585    @Override
1586    public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
1587      return Arrays.copyOf(rightKey, rightKey.length);
1588    }
1589
1590    /**
1591     * The HFileV2 file format's trailer contains this class name. We reinterpret this and
1592     * instantiate the appropriate comparator. TODO: With V3 consider removing this.
1593     * @return legacy class name for FileFileTrailer#comparatorClassName
1594     */
1595    @Override
1596    public String getLegacyKeyComparatorName() {
1597      return "org.apache.hadoop.hbase.KeyValue$MetaKeyComparator";
1598    }
1599
1600    @Override
1601    protected MetaComparator clone() throws CloneNotSupportedException {
1602      return (MetaComparator) super.clone();
1603    }
1604
1605    /**
1606     * Override the row key comparison to parse and compare the meta row key parts.
1607     */
1608    @Override
1609    protected int compareRowKey(final Cell l, final Cell r) {
1610      byte[] left = l.getRowArray();
1611      int loffset = l.getRowOffset();
1612      int llength = l.getRowLength();
1613      byte[] right = r.getRowArray();
1614      int roffset = r.getRowOffset();
1615      int rlength = r.getRowLength();
1616      return compareRows(left, loffset, llength, right, roffset, rlength);
1617    }
1618  }
1619
1620  /**
1621   * Compare KeyValues. When we compare KeyValues, we only compare the Key portion. This means two
1622   * KeyValues with same Key but different Values are considered the same as far as this Comparator
1623   * is concerned.
1624   * @deprecated : Use {@link CellComparatorImpl}. Deprecated for hbase 2.0, remove for hbase 3.0.
1625   */
1626  @Deprecated
1627  public static class KVComparator implements RawComparator<Cell>, SamePrefixComparator<byte[]> {
1628
1629    /**
1630     * The HFileV2 file format's trailer contains this class name. We reinterpret this and
1631     * instantiate the appropriate comparator. TODO: With V3 consider removing this.
1632     * @return legacy class name for FileFileTrailer#comparatorClassName
1633     */
1634    public String getLegacyKeyComparatorName() {
1635      return "org.apache.hadoop.hbase.KeyValue$KeyComparator";
1636    }
1637
1638    @Override // RawComparator
1639    public int compare(byte[] l, int loff, int llen, byte[] r, int roff, int rlen) {
1640      return compareFlatKey(l, loff, llen, r, roff, rlen);
1641    }
1642
1643    /**
1644     * Compares the only the user specified portion of a Key. This is overridden by MetaComparator.
1645     * @param left  left cell to compare row key
1646     * @param right right cell to compare row key
1647     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1648     */
1649    protected int compareRowKey(final Cell left, final Cell right) {
1650      return CellComparatorImpl.COMPARATOR.compareRows(left, right);
1651    }
1652
1653    /**
1654     * Compares left to right assuming that left,loffset,llength and right,roffset,rlength are full
1655     * KVs laid out in a flat byte[]s.
1656     * @param left    the left kv serialized byte[] to be compared with
1657     * @param loffset the offset in the left byte[]
1658     * @param llength the length in the left byte[]
1659     * @param right   the right kv serialized byte[] to be compared with
1660     * @param roffset the offset in the right byte[]
1661     * @param rlength the length in the right byte[]
1662     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1663     */
1664    public int compareFlatKey(byte[] left, int loffset, int llength, byte[] right, int roffset,
1665      int rlength) {
1666      // Compare row
1667      short lrowlength = Bytes.toShort(left, loffset);
1668      short rrowlength = Bytes.toShort(right, roffset);
1669      int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT, lrowlength, right,
1670        roffset + Bytes.SIZEOF_SHORT, rrowlength);
1671      if (compare != 0) {
1672        return compare;
1673      }
1674
1675      // Compare the rest of the two KVs without making any assumptions about
1676      // the common prefix. This function will not compare rows anyway, so we
1677      // don't need to tell it that the common prefix includes the row.
1678      return compareWithoutRow(0, left, loffset, llength, right, roffset, rlength, rrowlength);
1679    }
1680
1681    public int compareFlatKey(byte[] left, byte[] right) {
1682      return compareFlatKey(left, 0, left.length, right, 0, right.length);
1683    }
1684
1685    // compare a key against row/fam/qual/ts/type
1686    public int compareKey(Cell cell, byte[] row, int roff, int rlen, byte[] fam, int foff, int flen,
1687      byte[] col, int coff, int clen, long ts, byte type) {
1688
1689      int compare =
1690        compareRows(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), row, roff, rlen);
1691      if (compare != 0) {
1692        return compare;
1693      }
1694      // If the column is not specified, the "minimum" key type appears the
1695      // latest in the sorted order, regardless of the timestamp. This is used
1696      // for specifying the last key/value in a given row, because there is no
1697      // "lexicographically last column" (it would be infinitely long). The
1698      // "maximum" key type does not need this behavior.
1699      if (
1700        cell.getFamilyLength() + cell.getQualifierLength() == 0
1701          && cell.getTypeByte() == Type.Minimum.getCode()
1702      ) {
1703        // left is "bigger", i.e. it appears later in the sorted order
1704        return 1;
1705      }
1706      if (flen + clen == 0 && type == Type.Minimum.getCode()) {
1707        return -1;
1708      }
1709
1710      compare = compareFamilies(cell.getFamilyArray(), cell.getFamilyOffset(),
1711        cell.getFamilyLength(), fam, foff, flen);
1712      if (compare != 0) {
1713        return compare;
1714      }
1715      compare = compareColumns(cell.getQualifierArray(), cell.getQualifierOffset(),
1716        cell.getQualifierLength(), col, coff, clen);
1717      if (compare != 0) {
1718        return compare;
1719      }
1720      // Next compare timestamps.
1721      compare = compareTimestamps(cell.getTimestamp(), ts);
1722      if (compare != 0) {
1723        return compare;
1724      }
1725
1726      // Compare types. Let the delete types sort ahead of puts; i.e. types
1727      // of higher numbers sort before those of lesser numbers. Maximum (255)
1728      // appears ahead of everything, and minimum (0) appears after
1729      // everything.
1730      return (0xff & type) - (0xff & cell.getTypeByte());
1731    }
1732
1733    public int compareOnlyKeyPortion(Cell left, Cell right) {
1734      return PrivateCellUtil.compareKeyIgnoresMvcc(CellComparatorImpl.COMPARATOR, left, right);
1735    }
1736
1737    /**
1738     * Compares the Key of a cell -- with fields being more significant in this order: rowkey,
1739     * colfam/qual, timestamp, type, mvcc
1740     */
1741    @Override
1742    public int compare(final Cell left, final Cell right) {
1743      int compare = CellComparatorImpl.COMPARATOR.compare(left, right);
1744      return compare;
1745    }
1746
1747    public int compareTimestamps(final Cell left, final Cell right) {
1748      return CellComparatorImpl.COMPARATOR.compareTimestamps(left, right);
1749    }
1750
1751    /**
1752     * @param left  left cell to compare rows for
1753     * @param right right cell to compare rows for
1754     * @return Result comparing rows.
1755     */
1756    public int compareRows(final Cell left, final Cell right) {
1757      return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
1758        right.getRowArray(), right.getRowOffset(), right.getRowLength());
1759    }
1760
1761    /**
1762     * Get the b[],o,l for left and right rowkey portions and compare.
1763     * @param left    the left kv serialized byte[] to be compared with
1764     * @param loffset the offset in the left byte[]
1765     * @param llength the length in the left byte[]
1766     * @param right   the right kv serialized byte[] to be compared with
1767     * @param roffset the offset in the right byte[]
1768     * @param rlength the length in the right byte[]
1769     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1770     */
1771    public int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
1772      int rlength) {
1773      return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
1774    }
1775
1776    int compareColumns(final Cell left, final short lrowlength, final Cell right,
1777      final short rrowlength) {
1778      return CellComparatorImpl.COMPARATOR.compareColumns(left, right);
1779    }
1780
1781    protected int compareColumns(byte[] left, int loffset, int llength, final int lfamilylength,
1782      byte[] right, int roffset, int rlength, final int rfamilylength) {
1783      // Compare family portion first.
1784      int diff = Bytes.compareTo(left, loffset, lfamilylength, right, roffset, rfamilylength);
1785      if (diff != 0) {
1786        return diff;
1787      }
1788      // Compare qualifier portion
1789      return Bytes.compareTo(left, loffset + lfamilylength, llength - lfamilylength, right,
1790        roffset + rfamilylength, rlength - rfamilylength);
1791    }
1792
1793    static int compareTimestamps(final long ltimestamp, final long rtimestamp) {
1794      // The below older timestamps sorting ahead of newer timestamps looks
1795      // wrong but it is intentional. This way, newer timestamps are first
1796      // found when we iterate over a memstore and newer versions are the
1797      // first we trip over when reading from a store file.
1798      if (ltimestamp < rtimestamp) {
1799        return 1;
1800      } else if (ltimestamp > rtimestamp) {
1801        return -1;
1802      }
1803      return 0;
1804    }
1805
1806    /**
1807     * Overridden
1808     * @param commonPrefix location of expected common prefix
1809     * @param left         the left kv serialized byte[] to be compared with
1810     * @param loffset      the offset in the left byte[]
1811     * @param llength      the length in the left byte[]
1812     * @param right        the right kv serialized byte[] to be compared with
1813     * @param roffset      the offset in the byte[]
1814     * @param rlength      the length in the right byte[]
1815     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
1816     */
1817    @Override // SamePrefixComparator
1818    public int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength,
1819      byte[] right, int roffset, int rlength) {
1820      // Compare row
1821      short lrowlength = Bytes.toShort(left, loffset);
1822      short rrowlength;
1823
1824      int comparisonResult = 0;
1825      if (commonPrefix < ROW_LENGTH_SIZE) {
1826        // almost nothing in common
1827        rrowlength = Bytes.toShort(right, roffset);
1828        comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE, lrowlength, right,
1829          roffset + ROW_LENGTH_SIZE, rrowlength);
1830      } else { // the row length is the same
1831        rrowlength = lrowlength;
1832        if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
1833          // The rows are not the same. Exclude the common prefix and compare
1834          // the rest of the two rows.
1835          int common = commonPrefix - ROW_LENGTH_SIZE;
1836          comparisonResult = compareRows(left, loffset + common + ROW_LENGTH_SIZE,
1837            lrowlength - common, right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
1838        }
1839      }
1840      if (comparisonResult != 0) {
1841        return comparisonResult;
1842      }
1843
1844      assert lrowlength == rrowlength;
1845      return compareWithoutRow(commonPrefix, left, loffset, llength, right, roffset, rlength,
1846        lrowlength);
1847    }
1848
1849    /**
1850     * Compare columnFamily, qualifier, timestamp, and key type (everything except the row). This
1851     * method is used both in the normal comparator and the "same-prefix" comparator. Note that we
1852     * are assuming that row portions of both KVs have already been parsed and found identical, and
1853     * we don't validate that assumption here. n * the length of the common prefix of the two
1854     * key-values being compared, including row length and row
1855     */
1856    private int compareWithoutRow(int commonPrefix, byte[] left, int loffset, int llength,
1857      byte[] right, int roffset, int rlength, short rowlength) {
1858      /***
1859       * KeyValue Format and commonLength:
1860       * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
1861       * ------------------|-------commonLength--------|--------------
1862       */
1863      int commonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rowlength;
1864
1865      // commonLength + TIMESTAMP_TYPE_SIZE
1866      int commonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + commonLength;
1867      // ColumnFamily + Qualifier length.
1868      int lcolumnlength = llength - commonLengthWithTSAndType;
1869      int rcolumnlength = rlength - commonLengthWithTSAndType;
1870
1871      byte ltype = left[loffset + (llength - 1)];
1872      byte rtype = right[roffset + (rlength - 1)];
1873
1874      // If the column is not specified, the "minimum" key type appears the
1875      // latest in the sorted order, regardless of the timestamp. This is used
1876      // for specifying the last key/value in a given row, because there is no
1877      // "lexicographically last column" (it would be infinitely long). The
1878      // "maximum" key type does not need this behavior.
1879      if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
1880        // left is "bigger", i.e. it appears later in the sorted order
1881        return 1;
1882      }
1883      if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
1884        return -1;
1885      }
1886
1887      int lfamilyoffset = commonLength + loffset;
1888      int rfamilyoffset = commonLength + roffset;
1889
1890      // Column family length.
1891      int lfamilylength = left[lfamilyoffset - 1];
1892      int rfamilylength = right[rfamilyoffset - 1];
1893      // If left family size is not equal to right family size, we need not
1894      // compare the qualifiers.
1895      boolean sameFamilySize = (lfamilylength == rfamilylength);
1896      int common = 0;
1897      if (commonPrefix > 0) {
1898        common = Math.max(0, commonPrefix - commonLength);
1899        if (!sameFamilySize) {
1900          // Common should not be larger than Math.min(lfamilylength,
1901          // rfamilylength).
1902          common = Math.min(common, Math.min(lfamilylength, rfamilylength));
1903        } else {
1904          common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
1905        }
1906      }
1907      if (!sameFamilySize) {
1908        // comparing column family is enough.
1909        return Bytes.compareTo(left, lfamilyoffset + common, lfamilylength - common, right,
1910          rfamilyoffset + common, rfamilylength - common);
1911      }
1912      // Compare family & qualifier together.
1913      final int comparison = Bytes.compareTo(left, lfamilyoffset + common, lcolumnlength - common,
1914        right, rfamilyoffset + common, rcolumnlength - common);
1915      if (comparison != 0) {
1916        return comparison;
1917      }
1918
1919      ////
1920      // Next compare timestamps.
1921      long ltimestamp = Bytes.toLong(left, loffset + (llength - TIMESTAMP_TYPE_SIZE));
1922      long rtimestamp = Bytes.toLong(right, roffset + (rlength - TIMESTAMP_TYPE_SIZE));
1923      int compare = compareTimestamps(ltimestamp, rtimestamp);
1924      if (compare != 0) {
1925        return compare;
1926      }
1927
1928      // Compare types. Let the delete types sort ahead of puts; i.e. types
1929      // of higher numbers sort before those of lesser numbers. Maximum (255)
1930      // appears ahead of everything, and minimum (0) appears after
1931      // everything.
1932      return (0xff & rtype) - (0xff & ltype);
1933    }
1934
1935    protected int compareFamilies(final byte[] left, final int loffset, final int lfamilylength,
1936      final byte[] right, final int roffset, final int rfamilylength) {
1937      int diff = Bytes.compareTo(left, loffset, lfamilylength, right, roffset, rfamilylength);
1938      return diff;
1939    }
1940
1941    protected int compareColumns(final byte[] left, final int loffset, final int lquallength,
1942      final byte[] right, final int roffset, final int rquallength) {
1943      int diff = Bytes.compareTo(left, loffset, lquallength, right, roffset, rquallength);
1944      return diff;
1945    }
1946
1947    /**
1948     * Compares the row and column of two keyvalues for equality
1949     * @param left  left cell to compare row and column
1950     * @param right right cell to compare row and column
1951     * @return True if same row and column.
1952     */
1953    public boolean matchingRowColumn(final Cell left, final Cell right) {
1954      short lrowlength = left.getRowLength();
1955      short rrowlength = right.getRowLength();
1956
1957      // TsOffset = end of column data. just comparing Row+CF length of each
1958      if (
1959        (left.getRowLength() + left.getFamilyLength() + left.getQualifierLength())
1960            != (right.getRowLength() + right.getFamilyLength() + right.getQualifierLength())
1961      ) {
1962        return false;
1963      }
1964
1965      if (!matchingRows(left, lrowlength, right, rrowlength)) {
1966        return false;
1967      }
1968
1969      int lfoffset = left.getFamilyOffset();
1970      int rfoffset = right.getFamilyOffset();
1971      int lclength = left.getQualifierLength();
1972      int rclength = right.getQualifierLength();
1973      int lfamilylength = left.getFamilyLength();
1974      int rfamilylength = right.getFamilyLength();
1975      int diff = compareFamilies(left.getFamilyArray(), lfoffset, lfamilylength,
1976        right.getFamilyArray(), rfoffset, rfamilylength);
1977      if (diff != 0) {
1978        return false;
1979      } else {
1980        diff = compareColumns(left.getQualifierArray(), left.getQualifierOffset(), lclength,
1981          right.getQualifierArray(), right.getQualifierOffset(), rclength);
1982        return diff == 0;
1983      }
1984    }
1985
1986    /**
1987     * Compares the row of two keyvalues for equality
1988     * @param left  left cell to compare row
1989     * @param right right cell to compare row
1990     * @return True if rows match.
1991     */
1992    public boolean matchingRows(final Cell left, final Cell right) {
1993      short lrowlength = left.getRowLength();
1994      short rrowlength = right.getRowLength();
1995      return matchingRows(left, lrowlength, right, rrowlength);
1996    }
1997
1998    /**
1999     * @param left       left cell to compare row
2000     * @param lrowlength left row length
2001     * @param right      right cell to compare row
2002     * @param rrowlength right row length
2003     * @return True if rows match.
2004     */
2005    private boolean matchingRows(final Cell left, final short lrowlength, final Cell right,
2006      final short rrowlength) {
2007      return lrowlength == rrowlength && matchingRows(left.getRowArray(), left.getRowOffset(),
2008        lrowlength, right.getRowArray(), right.getRowOffset(), rrowlength);
2009    }
2010
2011    /**
2012     * Compare rows. Just calls Bytes.equals, but it's good to have this encapsulated.
2013     * @param left    Left row array.
2014     * @param loffset Left row offset.
2015     * @param llength Left row length.
2016     * @param right   Right row array.
2017     * @param roffset Right row offset.
2018     * @param rlength Right row length.
2019     * @return Whether rows are the same row.
2020     */
2021    public boolean matchingRows(final byte[] left, final int loffset, final int llength,
2022      final byte[] right, final int roffset, final int rlength) {
2023      return Bytes.equals(left, loffset, llength, right, roffset, rlength);
2024    }
2025
2026    public byte[] calcIndexKey(byte[] lastKeyOfPreviousBlock, byte[] firstKeyInBlock) {
2027      byte[] fakeKey = getShortMidpointKey(lastKeyOfPreviousBlock, firstKeyInBlock);
2028      if (compareFlatKey(fakeKey, firstKeyInBlock) > 0) {
2029        LOG.error("Unexpected getShortMidpointKey result, fakeKey:" + Bytes.toStringBinary(fakeKey)
2030          + ", firstKeyInBlock:" + Bytes.toStringBinary(firstKeyInBlock));
2031        return firstKeyInBlock;
2032      }
2033      if (lastKeyOfPreviousBlock != null && compareFlatKey(lastKeyOfPreviousBlock, fakeKey) >= 0) {
2034        LOG.error("Unexpected getShortMidpointKey result, lastKeyOfPreviousBlock:"
2035          + Bytes.toStringBinary(lastKeyOfPreviousBlock) + ", fakeKey:"
2036          + Bytes.toStringBinary(fakeKey));
2037        return firstKeyInBlock;
2038      }
2039      return fakeKey;
2040    }
2041
2042    /**
2043     * This is a HFile block index key optimization.
2044     * @param leftKey  byte array for left Key
2045     * @param rightKey byte array for right Key
2046     * @return 0 if equal, &lt;0 if left smaller, &gt;0 if right smaller
2047     * @deprecated Since 0.99.2;
2048     */
2049    @Deprecated
2050    public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
2051      if (rightKey == null) {
2052        throw new IllegalArgumentException("rightKey can not be null");
2053      }
2054      if (leftKey == null) {
2055        return Arrays.copyOf(rightKey, rightKey.length);
2056      }
2057      if (compareFlatKey(leftKey, rightKey) >= 0) {
2058        throw new IllegalArgumentException("Unexpected input, leftKey:" + Bytes.toString(leftKey)
2059          + ", rightKey:" + Bytes.toString(rightKey));
2060      }
2061
2062      short leftRowLength = Bytes.toShort(leftKey, 0);
2063      short rightRowLength = Bytes.toShort(rightKey, 0);
2064      int leftCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + leftRowLength;
2065      int rightCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rightRowLength;
2066      int leftCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + leftCommonLength;
2067      int rightCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + rightCommonLength;
2068      int leftColumnLength = leftKey.length - leftCommonLengthWithTSAndType;
2069      int rightColumnLength = rightKey.length - rightCommonLengthWithTSAndType;
2070      // rows are equal
2071      if (
2072        leftRowLength == rightRowLength && compareRows(leftKey, ROW_LENGTH_SIZE, leftRowLength,
2073          rightKey, ROW_LENGTH_SIZE, rightRowLength) == 0
2074      ) {
2075        // Compare family & qualifier together.
2076        int comparison = Bytes.compareTo(leftKey, leftCommonLength, leftColumnLength, rightKey,
2077          rightCommonLength, rightColumnLength);
2078        // same with "row + family + qualifier", return rightKey directly
2079        if (comparison == 0) {
2080          return Arrays.copyOf(rightKey, rightKey.length);
2081        }
2082        // "family + qualifier" are different, generate a faked key per rightKey
2083        byte[] newKey = Arrays.copyOf(rightKey, rightKey.length);
2084        Bytes.putLong(newKey, rightKey.length - TIMESTAMP_TYPE_SIZE, HConstants.LATEST_TIMESTAMP);
2085        Bytes.putByte(newKey, rightKey.length - TYPE_SIZE, Type.Maximum.getCode());
2086        return newKey;
2087      }
2088      // rows are different
2089      short minLength = leftRowLength < rightRowLength ? leftRowLength : rightRowLength;
2090      short diffIdx = 0;
2091      while (
2092        diffIdx < minLength
2093          && leftKey[ROW_LENGTH_SIZE + diffIdx] == rightKey[ROW_LENGTH_SIZE + diffIdx]
2094      ) {
2095        diffIdx++;
2096      }
2097      byte[] newRowKey = null;
2098      if (diffIdx >= minLength) {
2099        // leftKey's row is prefix of rightKey's.
2100        newRowKey = new byte[diffIdx + 1];
2101        System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1);
2102      } else {
2103        int diffByte = leftKey[ROW_LENGTH_SIZE + diffIdx];
2104        if (
2105          (0xff & diffByte) < 0xff && (diffByte + 1) < (rightKey[ROW_LENGTH_SIZE + diffIdx] & 0xff)
2106        ) {
2107          newRowKey = new byte[diffIdx + 1];
2108          System.arraycopy(leftKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx);
2109          newRowKey[diffIdx] = (byte) (diffByte + 1);
2110        } else {
2111          newRowKey = new byte[diffIdx + 1];
2112          System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1);
2113        }
2114      }
2115      return new KeyValue(newRowKey, null, null, HConstants.LATEST_TIMESTAMP, Type.Maximum)
2116        .getKey();
2117    }
2118
2119    @Override
2120    protected KVComparator clone() throws CloneNotSupportedException {
2121      return (KVComparator) super.clone();
2122    }
2123
2124  }
2125
2126  /**
2127   * @param in Where to read bytes from. Creates a byte array to hold the KeyValue backing bytes
2128   *           copied from the steam.
2129   * @return KeyValue created by deserializing from <code>in</code> OR if we find a length of zero,
2130   *         we will return null which can be useful marking a stream as done.
2131   * @throws IOException if any IO error happen
2132   */
2133  public static KeyValue create(final DataInput in) throws IOException {
2134    return create(in.readInt(), in);
2135  }
2136
2137  /**
2138   * Create a KeyValue reading <code>length</code> from <code>in</code>
2139   * @param length length of the Key
2140   * @param in     Input to read from
2141   * @return Created KeyValue OR if we find a length of zero, we will return null which can be
2142   *         useful marking a stream as done.
2143   * @throws IOException if any IO error happen
2144   */
2145  public static KeyValue create(int length, final DataInput in) throws IOException {
2146
2147    if (length <= 0) {
2148      if (length == 0) {
2149        return null;
2150      }
2151      throw new IOException("Failed read " + length + " bytes, stream corrupt?");
2152    }
2153
2154    // This is how the old Writables.readFrom used to deserialize. Didn't even vint.
2155    byte[] bytes = new byte[length];
2156    in.readFully(bytes);
2157    return new KeyValue(bytes, 0, length);
2158  }
2159
2160  /**
2161   * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable.
2162   * @param kv  the KeyValue on which write is being requested
2163   * @param out OutputStream to write keyValue to
2164   * @return Length written on stream
2165   * @throws IOException if any IO error happen
2166   * @see #create(DataInput) for the inverse function
2167   */
2168  public static long write(final KeyValue kv, final DataOutput out) throws IOException {
2169    // This is how the old Writables write used to serialize KVs. Need to figure way to make it
2170    // work for all implementations.
2171    int length = kv.getLength();
2172    out.writeInt(length);
2173    out.write(kv.getBuffer(), kv.getOffset(), length);
2174    return (long) length + Bytes.SIZEOF_INT;
2175  }
2176
2177  /**
2178   * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable but do not
2179   * require a {@link DataOutput}, just take plain {@link OutputStream} Named <code>oswrite</code>
2180   * so does not clash with {@link #write(KeyValue, DataOutput)}
2181   * @param kv       the KeyValue on which write is being requested
2182   * @param out      OutputStream to write keyValue to
2183   * @param withTags boolean value indicating write is with Tags or not
2184   * @return Length written on stream
2185   * @throws IOException if any IO error happen
2186   * @see #create(DataInput) for the inverse function
2187   * @see #write(KeyValue, DataOutput)
2188   * @see KeyValueUtil#oswrite(Cell, OutputStream, boolean)
2189   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0. Instead use
2190   *             {@link #write(OutputStream, boolean)}
2191   */
2192  @Deprecated
2193  public static long oswrite(final KeyValue kv, final OutputStream out, final boolean withTags)
2194    throws IOException {
2195    ByteBufferUtils.putInt(out, kv.getSerializedSize(withTags));
2196    return (long) kv.write(out, withTags) + Bytes.SIZEOF_INT;
2197  }
2198
2199  @Override
2200  public int write(OutputStream out, boolean withTags) throws IOException {
2201    int len = getSerializedSize(withTags);
2202    out.write(this.bytes, this.offset, len);
2203    return len;
2204  }
2205
2206  @Override
2207  public int getSerializedSize(boolean withTags) {
2208    if (withTags) {
2209      return this.length;
2210    }
2211    return this.getKeyLength() + this.getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE;
2212  }
2213
2214  @Override
2215  public int getSerializedSize() {
2216    return this.length;
2217  }
2218
2219  @Override
2220  public void write(ByteBuffer buf, int offset) {
2221    ByteBufferUtils.copyFromArrayToBuffer(buf, offset, this.bytes, this.offset, this.length);
2222  }
2223
2224  /**
2225   * Avoids redundant comparisons for better performance. TODO get rid of this wart
2226   */
2227  public interface SamePrefixComparator<T> {
2228    /**
2229     * Compare two keys assuming that the first n bytes are the same.
2230     * @param commonPrefix How many bytes are the same.
2231     */
2232    int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength, byte[] right,
2233      int roffset, int rlength);
2234  }
2235
2236  /**
2237   * HeapSize implementation
2238   * <p/>
2239   * We do not count the bytes in the rowCache because it should be empty for a KeyValue in the
2240   * MemStore.
2241   */
2242  @Override
2243  public long heapSize() {
2244    // Deep object overhead for this KV consists of two parts. The first part is the KV object
2245    // itself, while the second part is the backing byte[]. We will only count the array overhead
2246    // from the byte[] only if this is the first KV in there.
2247    int fixed = ClassSize.align(FIXED_OVERHEAD);
2248    if (offset == 0) {
2249      // count both length and object overhead
2250      return fixed + ClassSize.sizeOfByteArray(length);
2251    } else {
2252      // only count the number of bytes
2253      return fixed + length;
2254    }
2255  }
2256
2257  /**
2258   * A simple form of KeyValue that creates a keyvalue with only the key part of the byte[] Mainly
2259   * used in places where we need to compare two cells. Avoids copying of bytes In places like block
2260   * index keys, we need to compare the key byte[] with a cell. Hence create a Keyvalue(aka Cell)
2261   * that would help in comparing as two cells
2262   */
2263  public static class KeyOnlyKeyValue extends KeyValue {
2264    private short rowLen = -1;
2265
2266    public KeyOnlyKeyValue() {
2267
2268    }
2269
2270    public KeyOnlyKeyValue(byte[] b) {
2271      this(b, 0, b.length);
2272    }
2273
2274    public KeyOnlyKeyValue(byte[] b, int offset, int length) {
2275      this.bytes = b;
2276      this.length = length;
2277      this.offset = offset;
2278      this.rowLen = Bytes.toShort(this.bytes, this.offset);
2279    }
2280
2281    public void set(KeyOnlyKeyValue keyOnlyKeyValue) {
2282      this.bytes = keyOnlyKeyValue.bytes;
2283      this.length = keyOnlyKeyValue.length;
2284      this.offset = keyOnlyKeyValue.offset;
2285      this.rowLen = keyOnlyKeyValue.rowLen;
2286    }
2287
2288    public void clear() {
2289      rowLen = -1;
2290      bytes = null;
2291      offset = 0;
2292      length = 0;
2293    }
2294
2295    @Override
2296    public int getKeyOffset() {
2297      return this.offset;
2298    }
2299
2300    /**
2301     * A setter that helps to avoid object creation every time and whenever there is a need to
2302     * create new KeyOnlyKeyValue.
2303     * @param key    Key to set
2304     * @param offset Offset of the Key
2305     * @param length length of the Key
2306     */
2307    public void setKey(byte[] key, int offset, int length) {
2308      this.bytes = key;
2309      this.offset = offset;
2310      this.length = length;
2311      this.rowLen = Bytes.toShort(this.bytes, this.offset);
2312    }
2313
2314    @Override
2315    public byte[] getKey() {
2316      int keylength = getKeyLength();
2317      byte[] key = new byte[keylength];
2318      System.arraycopy(this.bytes, getKeyOffset(), key, 0, keylength);
2319      return key;
2320    }
2321
2322    @Override
2323    public byte[] getRowArray() {
2324      return bytes;
2325    }
2326
2327    @Override
2328    public int getRowOffset() {
2329      return getKeyOffset() + Bytes.SIZEOF_SHORT;
2330    }
2331
2332    @Override
2333    public byte[] getFamilyArray() {
2334      return bytes;
2335    }
2336
2337    @Override
2338    public byte getFamilyLength() {
2339      return this.bytes[getFamilyOffset() - 1];
2340    }
2341
2342    int getFamilyLengthPosition(int rowLength) {
2343      return this.offset + Bytes.SIZEOF_SHORT + rowLength;
2344    }
2345
2346    @Override
2347    public int getFamilyOffset() {
2348      return this.offset + Bytes.SIZEOF_SHORT + getRowLength() + Bytes.SIZEOF_BYTE;
2349    }
2350
2351    @Override
2352    public byte[] getQualifierArray() {
2353      return bytes;
2354    }
2355
2356    @Override
2357    public int getQualifierLength() {
2358      return getQualifierLength(getRowLength(), getFamilyLength());
2359    }
2360
2361    @Override
2362    public int getQualifierOffset() {
2363      return getFamilyOffset() + getFamilyLength();
2364    }
2365
2366    @Override
2367    public int getKeyLength() {
2368      return length;
2369    }
2370
2371    @Override
2372    public short getRowLength() {
2373      return rowLen;
2374    }
2375
2376    @Override
2377    public byte getTypeByte() {
2378      return getTypeByte(getKeyLength());
2379    }
2380
2381    byte getTypeByte(int keyLength) {
2382      return this.bytes[this.offset + keyLength - 1];
2383    }
2384
2385    private int getQualifierLength(int rlength, int flength) {
2386      return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0);
2387    }
2388
2389    @Override
2390    public long getTimestamp() {
2391      int tsOffset = getTimestampOffset();
2392      return Bytes.toLong(this.bytes, tsOffset);
2393    }
2394
2395    @Override
2396    public int getTimestampOffset() {
2397      return getKeyOffset() + getKeyLength() - TIMESTAMP_TYPE_SIZE;
2398    }
2399
2400    @Override
2401    public byte[] getTagsArray() {
2402      return HConstants.EMPTY_BYTE_ARRAY;
2403    }
2404
2405    @Override
2406    public int getTagsOffset() {
2407      return 0;
2408    }
2409
2410    @Override
2411    public byte[] getValueArray() {
2412      throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2413    }
2414
2415    @Override
2416    public int getValueOffset() {
2417      throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2418    }
2419
2420    @Override
2421    public int getValueLength() {
2422      throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2423    }
2424
2425    @Override
2426    public int getTagsLength() {
2427      return 0;
2428    }
2429
2430    @Override
2431    public String toString() {
2432      if (this.bytes == null || this.bytes.length == 0) {
2433        return "empty";
2434      }
2435      return keyToString(this.bytes, this.offset, getKeyLength()) + "/vlen=0/mvcc=0";
2436    }
2437
2438    @Override
2439    public int hashCode() {
2440      return super.hashCode();
2441    }
2442
2443    @Override
2444    public boolean equals(Object other) {
2445      return super.equals(other);
2446    }
2447
2448    @Override
2449    public long heapSize() {
2450      return super.heapSize() + Bytes.SIZEOF_SHORT;
2451    }
2452
2453    @Override
2454    public int write(OutputStream out, boolean withTags) throws IOException {
2455      // This type of Cell is used only to maintain some internal states. We never allow this type
2456      // of Cell to be returned back over the RPC
2457      throw new IllegalStateException("A reader should never return this type of a Cell");
2458    }
2459  }
2460
2461  @Override
2462  public ExtendedCell deepClone() {
2463    byte[] copy = Bytes.copy(this.bytes, this.offset, this.length);
2464    KeyValue kv = new KeyValue(copy, 0, copy.length);
2465    kv.setSequenceId(this.getSequenceId());
2466    return kv;
2467  }
2468}