2 * Copyright The Apache Software Foundation
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 package org
.apache
.hadoop
.hbase
;
22 import static org
.apache
.hadoop
.hbase
.util
.Bytes
.len
;
24 import java
.io
.DataInput
;
25 import java
.io
.DataOutput
;
26 import java
.io
.IOException
;
27 import java
.io
.OutputStream
;
28 import java
.nio
.ByteBuffer
;
29 import java
.util
.ArrayList
;
30 import java
.util
.Arrays
;
31 import java
.util
.HashMap
;
32 import java
.util
.Iterator
;
33 import java
.util
.List
;
35 import org
.apache
.hadoop
.hbase
.util
.ByteBufferUtils
;
36 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
37 import org
.apache
.hadoop
.hbase
.util
.ClassSize
;
38 import org
.apache
.hadoop
.io
.RawComparator
;
39 import org
.apache
.yetus
.audience
.InterfaceAudience
;
40 import org
.slf4j
.Logger
;
41 import org
.slf4j
.LoggerFactory
;
43 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.annotations
.VisibleForTesting
;
46 * An HBase Key/Value. This is the fundamental HBase Type.
48 * HBase applications and users should use the Cell interface and avoid directly using KeyValue and
49 * member functions not defined in Cell.
51 * If being used client-side, the primary methods to access individual fields are
52 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()},
53 * {@link #getTimestamp()}, and {@link #getValueArray()}. These methods allocate new byte arrays
54 * and return copies. Avoid their use server-side.
56 * Instances of this class are immutable. They do not implement Comparable but Comparators are
57 * provided. Comparators change with context, whether user table or a catalog table comparison. Its
58 * critical you use the appropriate comparator. There are Comparators for normal HFiles, Meta's
59 * Hfiles, and bloom filter keys.
61 * KeyValue wraps a byte array and takes offsets and lengths into passed array at where to start
62 * interpreting the content as KeyValue. The KeyValue format inside a byte array is:
63 * <code><keylength> <valuelength> <key> <value></code> Key is further
64 * decomposed as: <code><rowlength> <row> <columnfamilylength>
65 * <columnfamily> <columnqualifier>
66 * <timestamp> <keytype></code> The <code>rowlength</code> maximum is
67 * <code>Short.MAX_SIZE</code>, column family length maximum is <code>Byte.MAX_SIZE</code>, and
68 * column qualifier + key length must be < <code>Integer.MAX_SIZE</code>. The column does not
69 * contain the family/qualifier delimiter, {@link #COLUMN_FAMILY_DELIMITER}<br>
70 * KeyValue can optionally contain Tags. When it contains tags, it is added in the byte array after
71 * the value part. The format for this part is: <code><tagslength><tagsbytes></code>.
72 * <code>tagslength</code> maximum is <code>Short.MAX_SIZE</code>. The <code>tagsbytes</code>
73 * contain one or more tags where as each tag is of the form
74 * <code><taglength><tagtype><tagbytes></code>. <code>tagtype</code> is one byte
75 * and <code>taglength</code> maximum is <code>Short.MAX_SIZE</code> and it includes 1 byte type
76 * length and actual tag bytes length.
78 @InterfaceAudience.Private
79 public class KeyValue
implements ExtendedCell
, Cloneable
{
80 private static final ArrayList
<Tag
> EMPTY_ARRAY_LIST
= new ArrayList
<>();
82 private static final Logger LOG
= LoggerFactory
.getLogger(KeyValue
.class);
84 public static final int FIXED_OVERHEAD
= ClassSize
.OBJECT
+ // the KeyValue object itself
85 ClassSize
.REFERENCE
+ // pointer to "bytes"
86 2 * Bytes
.SIZEOF_INT
+ // offset, length
87 Bytes
.SIZEOF_LONG
;// memstoreTS
90 * Colon character in UTF-8
92 public static final char COLUMN_FAMILY_DELIMITER
= ':';
94 public static final byte[] COLUMN_FAMILY_DELIM_ARRAY
=
95 new byte[]{COLUMN_FAMILY_DELIMITER
};
98 * Comparator for plain key/values; i.e. non-catalog table key/values. Works on Key portion
100 * @deprecated Use {@link CellComparator#getInstance()} instead. Deprecated for hbase 2.0, remove for hbase 3.0.
103 public static final KVComparator COMPARATOR
= new KVComparator();
105 * A {@link KVComparator} for <code>hbase:meta</code> catalog table
107 * @deprecated Use {@link MetaCellComparator#META_COMPARATOR} instead.
108 * Deprecated for hbase 2.0, remove for hbase 3.0.
111 public static final KVComparator META_COMPARATOR
= new MetaComparator();
113 /** Size of the key length field in bytes*/
114 public static final int KEY_LENGTH_SIZE
= Bytes
.SIZEOF_INT
;
116 /** Size of the key type field in bytes */
117 public static final int TYPE_SIZE
= Bytes
.SIZEOF_BYTE
;
119 /** Size of the row length field in bytes */
120 public static final int ROW_LENGTH_SIZE
= Bytes
.SIZEOF_SHORT
;
122 /** Size of the family length field in bytes */
123 public static final int FAMILY_LENGTH_SIZE
= Bytes
.SIZEOF_BYTE
;
125 /** Size of the timestamp field in bytes */
126 public static final int TIMESTAMP_SIZE
= Bytes
.SIZEOF_LONG
;
128 // Size of the timestamp and type byte on end of a key -- a long + a byte.
129 public static final int TIMESTAMP_TYPE_SIZE
= TIMESTAMP_SIZE
+ TYPE_SIZE
;
131 // Size of the length shorts and bytes in key.
132 public static final int KEY_INFRASTRUCTURE_SIZE
= ROW_LENGTH_SIZE
133 + FAMILY_LENGTH_SIZE
+ TIMESTAMP_TYPE_SIZE
;
135 // How far into the key the row starts at. First thing to read is the short
136 // that says how long the row is.
137 public static final int ROW_OFFSET
=
138 Bytes
.SIZEOF_INT
/*keylength*/ +
139 Bytes
.SIZEOF_INT
/*valuelength*/;
141 public static final int ROW_KEY_OFFSET
= ROW_OFFSET
+ ROW_LENGTH_SIZE
;
143 // Size of the length ints in a KeyValue datastructure.
144 public static final int KEYVALUE_INFRASTRUCTURE_SIZE
= ROW_OFFSET
;
146 /** Size of the tags length field in bytes */
147 public static final int TAGS_LENGTH_SIZE
= Bytes
.SIZEOF_SHORT
;
149 public static final int KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE
= ROW_OFFSET
+ TAGS_LENGTH_SIZE
;
152 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
153 * characteristics would take up for its underlying data structure.
155 * @param rlength row length
156 * @param flength family length
157 * @param qlength qualifier length
158 * @param vlength value length
160 * @return the <code>KeyValue</code> data structure length
162 public static long getKeyValueDataStructureSize(int rlength
,
163 int flength
, int qlength
, int vlength
) {
164 return KeyValue
.KEYVALUE_INFRASTRUCTURE_SIZE
165 + getKeyDataStructureSize(rlength
, flength
, qlength
) + vlength
;
169 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
170 * characteristics would take up for its underlying data structure.
172 * @param rlength row length
173 * @param flength family length
174 * @param qlength qualifier length
175 * @param vlength value length
176 * @param tagsLength total length of the tags
178 * @return the <code>KeyValue</code> data structure length
180 public static long getKeyValueDataStructureSize(int rlength
, int flength
, int qlength
,
181 int vlength
, int tagsLength
) {
182 if (tagsLength
== 0) {
183 return getKeyValueDataStructureSize(rlength
, flength
, qlength
, vlength
);
185 return KeyValue
.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE
186 + getKeyDataStructureSize(rlength
, flength
, qlength
) + vlength
+ tagsLength
;
190 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
191 * characteristics would take up for its underlying data structure.
193 * @param klength key length
194 * @param vlength value length
195 * @param tagsLength total length of the tags
197 * @return the <code>KeyValue</code> data structure length
199 public static long getKeyValueDataStructureSize(int klength
, int vlength
, int tagsLength
) {
200 if (tagsLength
== 0) {
201 return (long) KeyValue
.KEYVALUE_INFRASTRUCTURE_SIZE
+ klength
+ vlength
;
203 return (long) KeyValue
.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE
+ klength
+ vlength
+ tagsLength
;
207 * Computes the number of bytes that a <code>KeyValue</code> instance with the provided
208 * characteristics would take up in its underlying data structure for the key.
210 * @param rlength row length
211 * @param flength family length
212 * @param qlength qualifier length
214 * @return the key data structure length
216 public static long getKeyDataStructureSize(int rlength
, int flength
, int qlength
) {
217 return (long) KeyValue
.KEY_INFRASTRUCTURE_SIZE
+ rlength
+ flength
+ qlength
;
222 * Has space for other key types to be added later. Cannot rely on
223 * enum ordinals . They change if item is removed or moved. Do our own codes.
225 public static enum Type
{
230 DeleteFamilyVersion((byte)10),
231 DeleteColumn((byte)12),
232 DeleteFamily((byte)14),
234 // Maximum is used when searching; you look from maximum on down.
237 private final byte code
;
243 public byte getCode() {
247 private static Type
[] codeArray
= new Type
[256];
250 for (Type t
: Type
.values()) {
251 codeArray
[t
.code
& 0xff] = t
;
256 * True to indicate that the byte b is a valid type.
257 * @param b byte to check
258 * @return true or false
260 static boolean isValidType(byte b
) {
261 return codeArray
[b
& 0xff] != null;
265 * Cannot rely on enum ordinals . They change if item is removed or moved.
268 * @return Type associated with passed code.
270 public static Type
codeToType(final byte b
) {
271 Type t
= codeArray
[b
& 0xff];
275 throw new RuntimeException("Unknown code " + b
);
280 * Lowest possible key.
281 * Makes a Key with highest possible Timestamp, empty row and column. No
282 * key can be equal or lower than this one in memstore or in store file.
284 public static final KeyValue LOWESTKEY
=
285 new KeyValue(HConstants
.EMPTY_BYTE_ARRAY
, HConstants
.LATEST_TIMESTAMP
);
288 // KeyValue core instance fields.
289 protected byte [] bytes
= null; // an immutable byte array that contains the KV
290 protected int offset
= 0; // offset into bytes buffer KV starts at
291 protected int length
= 0; // length of the KV starting from offset.
293 /** Here be dragons **/
296 * used to achieve atomic operations in the memstore.
299 public long getSequenceId() {
304 public void setSequenceId(long seqId
) {
308 // multi-version concurrency control version. default value is 0, aka do not care.
309 private long seqId
= 0;
311 /** Dragon time over, return to normal business */
314 /** Writable Constructor -- DO NOT USE */
318 * Creates a KeyValue from the start of the specified byte array.
319 * Presumes <code>bytes</code> content is formatted as a KeyValue blob.
320 * @param bytes byte array
322 public KeyValue(final byte [] bytes
) {
327 * Creates a KeyValue from the specified byte array and offset.
328 * Presumes <code>bytes</code> content starting at <code>offset</code> is
329 * formatted as a KeyValue blob.
330 * @param bytes byte array
331 * @param offset offset to start of KeyValue
333 public KeyValue(final byte [] bytes
, final int offset
) {
334 this(bytes
, offset
, getLength(bytes
, offset
));
338 * Creates a KeyValue from the specified byte array, starting at offset, and
339 * for length <code>length</code>.
340 * @param bytes byte array
341 * @param offset offset to start of the KeyValue
342 * @param length length of the KeyValue
344 public KeyValue(final byte[] bytes
, final int offset
, final int length
) {
345 KeyValueUtil
.checkKeyValueBytes(bytes
, offset
, length
, true);
347 this.offset
= offset
;
348 this.length
= length
;
352 * Creates a KeyValue from the specified byte array, starting at offset, and
353 * for length <code>length</code>.
355 * @param bytes byte array
356 * @param offset offset to start of the KeyValue
357 * @param length length of the KeyValue
360 public KeyValue(final byte[] bytes
, final int offset
, final int length
, long ts
) {
361 this(bytes
, offset
, length
, null, 0, 0, null, 0, 0, ts
, Type
.Maximum
, null, 0, 0, null);
364 /** Constructors that build a new backing byte array from fields */
367 * Constructs KeyValue structure filled with null value.
368 * Sets type to {@link KeyValue.Type#Maximum}
369 * @param row - row key (arbitrary byte array)
372 public KeyValue(final byte [] row
, final long timestamp
) {
373 this(row
, null, null, timestamp
, Type
.Maximum
, null);
377 * Constructs KeyValue structure filled with null value.
378 * @param row - row key (arbitrary byte array)
381 public KeyValue(final byte [] row
, final long timestamp
, Type type
) {
382 this(row
, null, null, timestamp
, type
, null);
386 * Constructs KeyValue structure filled with null value.
387 * Sets type to {@link KeyValue.Type#Maximum}
388 * @param row - row key (arbitrary byte array)
389 * @param family family name
390 * @param qualifier column qualifier
392 public KeyValue(final byte [] row
, final byte [] family
,
393 final byte [] qualifier
) {
394 this(row
, family
, qualifier
, HConstants
.LATEST_TIMESTAMP
, Type
.Maximum
);
398 * Constructs KeyValue structure as a put filled with specified values and
400 * @param row - row key (arbitrary byte array)
401 * @param family family name
402 * @param qualifier column qualifier
404 public KeyValue(final byte [] row
, final byte [] family
,
405 final byte [] qualifier
, final byte [] value
) {
406 this(row
, family
, qualifier
, HConstants
.LATEST_TIMESTAMP
, Type
.Put
, value
);
410 * Constructs KeyValue structure filled with specified values.
412 * @param family family name
413 * @param qualifier column qualifier
414 * @param timestamp version timestamp
415 * @param type key type
416 * @throws IllegalArgumentException
418 public KeyValue(final byte[] row
, final byte[] family
,
419 final byte[] qualifier
, final long timestamp
, Type type
) {
420 this(row
, family
, qualifier
, timestamp
, type
, null);
424 * Constructs KeyValue structure filled with specified values.
426 * @param family family name
427 * @param qualifier column qualifier
428 * @param timestamp version timestamp
429 * @param value column value
430 * @throws IllegalArgumentException
432 public KeyValue(final byte[] row
, final byte[] family
,
433 final byte[] qualifier
, final long timestamp
, final byte[] value
) {
434 this(row
, family
, qualifier
, timestamp
, Type
.Put
, value
);
438 * Constructs KeyValue structure filled with specified values.
440 * @param family family name
441 * @param qualifier column qualifier
442 * @param timestamp version timestamp
443 * @param value column value
445 * @throws IllegalArgumentException
447 public KeyValue(final byte[] row
, final byte[] family
,
448 final byte[] qualifier
, final long timestamp
, final byte[] value
,
450 this(row
, family
, qualifier
, timestamp
, value
, tags
!= null ? Arrays
.asList(tags
) : null);
454 * Constructs KeyValue structure filled with specified values.
456 * @param family family name
457 * @param qualifier column qualifier
458 * @param timestamp version timestamp
459 * @param value column value
460 * @param tags tags non-empty list of tags or null
461 * @throws IllegalArgumentException
463 public KeyValue(final byte[] row
, final byte[] family
,
464 final byte[] qualifier
, final long timestamp
, final byte[] value
,
465 final List
<Tag
> tags
) {
466 this(row
, 0, row
==null ?
0 : row
.length
,
467 family
, 0, family
==null ?
0 : family
.length
,
468 qualifier
, 0, qualifier
==null ?
0 : qualifier
.length
,
470 value
, 0, value
==null ?
0 : value
.length
, tags
);
474 * Constructs KeyValue structure filled with specified values.
476 * @param family family name
477 * @param qualifier column qualifier
478 * @param timestamp version timestamp
479 * @param type key type
480 * @param value column value
481 * @throws IllegalArgumentException
483 public KeyValue(final byte[] row
, final byte[] family
,
484 final byte[] qualifier
, final long timestamp
, Type type
,
485 final byte[] value
) {
486 this(row
, 0, len(row
), family
, 0, len(family
), qualifier
, 0, len(qualifier
),
487 timestamp
, type
, value
, 0, len(value
));
491 * Constructs KeyValue structure filled with specified values.
493 * Column is split into two fields, family and qualifier.
495 * @param family family name
496 * @param qualifier column qualifier
497 * @param timestamp version timestamp
498 * @param type key type
499 * @param value column value
500 * @throws IllegalArgumentException
502 public KeyValue(final byte[] row
, final byte[] family
,
503 final byte[] qualifier
, final long timestamp
, Type type
,
504 final byte[] value
, final List
<Tag
> tags
) {
505 this(row
, family
, qualifier
, 0, qualifier
==null ?
0 : qualifier
.length
,
506 timestamp
, type
, value
, 0, value
==null ?
0 : value
.length
, tags
);
510 * Constructs KeyValue structure filled with specified values.
512 * @param family family name
513 * @param qualifier column qualifier
514 * @param timestamp version timestamp
515 * @param type key type
516 * @param value column value
517 * @throws IllegalArgumentException
519 public KeyValue(final byte[] row
, final byte[] family
,
520 final byte[] qualifier
, final long timestamp
, Type type
,
521 final byte[] value
, final byte[] tags
) {
522 this(row
, family
, qualifier
, 0, qualifier
==null ?
0 : qualifier
.length
,
523 timestamp
, type
, value
, 0, value
==null ?
0 : value
.length
, tags
);
527 * Constructs KeyValue structure filled with specified values.
529 * @param family family name
530 * @param qualifier column qualifier
531 * @param qoffset qualifier offset
532 * @param qlength qualifier length
533 * @param timestamp version timestamp
534 * @param type key type
535 * @param value column value
536 * @param voffset value offset
537 * @param vlength value length
538 * @throws IllegalArgumentException
540 public KeyValue(byte [] row
, byte [] family
,
541 byte [] qualifier
, int qoffset
, int qlength
, long timestamp
, Type type
,
542 byte [] value
, int voffset
, int vlength
, List
<Tag
> tags
) {
543 this(row
, 0, row
==null ?
0 : row
.length
,
544 family
, 0, family
==null ?
0 : family
.length
,
545 qualifier
, qoffset
, qlength
, timestamp
, type
,
546 value
, voffset
, vlength
, tags
);
562 public KeyValue(byte [] row
, byte [] family
,
563 byte [] qualifier
, int qoffset
, int qlength
, long timestamp
, Type type
,
564 byte [] value
, int voffset
, int vlength
, byte[] tags
) {
565 this(row
, 0, row
==null ?
0 : row
.length
,
566 family
, 0, family
==null ?
0 : family
.length
,
567 qualifier
, qoffset
, qlength
, timestamp
, type
,
568 value
, voffset
, vlength
, tags
, 0, tags
==null ?
0 : tags
.length
);
572 * Constructs KeyValue structure filled with specified values.
574 * Column is split into two fields, family and qualifier.
576 * @throws IllegalArgumentException
578 public KeyValue(final byte [] row
, final int roffset
, final int rlength
,
579 final byte [] family
, final int foffset
, final int flength
,
580 final byte [] qualifier
, final int qoffset
, final int qlength
,
581 final long timestamp
, final Type type
,
582 final byte [] value
, final int voffset
, final int vlength
) {
583 this(row
, roffset
, rlength
, family
, foffset
, flength
, qualifier
, qoffset
,
584 qlength
, timestamp
, type
, value
, voffset
, vlength
, null);
588 * Constructs KeyValue structure filled with specified values. Uses the provided buffer as the
591 * Column is split into two fields, family and qualifier.
593 * @param buffer the bytes buffer to use
594 * @param boffset buffer offset
596 * @param roffset row offset
597 * @param rlength row length
598 * @param family family name
599 * @param foffset family offset
600 * @param flength family length
601 * @param qualifier column qualifier
602 * @param qoffset qualifier offset
603 * @param qlength qualifier length
604 * @param timestamp version timestamp
605 * @param type key type
606 * @param value column value
607 * @param voffset value offset
608 * @param vlength value length
609 * @param tags non-empty list of tags or null
610 * @throws IllegalArgumentException an illegal value was passed or there is insufficient space
611 * remaining in the buffer
613 public KeyValue(byte [] buffer
, final int boffset
,
614 final byte [] row
, final int roffset
, final int rlength
,
615 final byte [] family
, final int foffset
, final int flength
,
616 final byte [] qualifier
, final int qoffset
, final int qlength
,
617 final long timestamp
, final Type type
,
618 final byte [] value
, final int voffset
, final int vlength
,
621 this.length
= writeByteArray(buffer
, boffset
,
622 row
, roffset
, rlength
,
623 family
, foffset
, flength
, qualifier
, qoffset
, qlength
,
624 timestamp
, type
, value
, voffset
, vlength
, tags
);
625 this.offset
= boffset
;
629 * Constructs KeyValue structure filled with specified values.
631 * Column is split into two fields, family and qualifier.
633 * @param roffset row offset
634 * @param rlength row length
635 * @param family family name
636 * @param foffset family offset
637 * @param flength family length
638 * @param qualifier column qualifier
639 * @param qoffset qualifier offset
640 * @param qlength qualifier length
641 * @param timestamp version timestamp
642 * @param type key type
643 * @param value column value
644 * @param voffset value offset
645 * @param vlength value length
647 * @throws IllegalArgumentException
649 public KeyValue(final byte [] row
, final int roffset
, final int rlength
,
650 final byte [] family
, final int foffset
, final int flength
,
651 final byte [] qualifier
, final int qoffset
, final int qlength
,
652 final long timestamp
, final Type type
,
653 final byte [] value
, final int voffset
, final int vlength
,
654 final List
<Tag
> tags
) {
655 this.bytes
= createByteArray(row
, roffset
, rlength
,
656 family
, foffset
, flength
, qualifier
, qoffset
, qlength
,
657 timestamp
, type
, value
, voffset
, vlength
, tags
);
658 this.length
= bytes
.length
;
679 public KeyValue(final byte [] row
, final int roffset
, final int rlength
,
680 final byte [] family
, final int foffset
, final int flength
,
681 final byte [] qualifier
, final int qoffset
, final int qlength
,
682 final long timestamp
, final Type type
,
683 final byte [] value
, final int voffset
, final int vlength
,
684 final byte[] tags
, final int tagsOffset
, final int tagsLength
) {
685 this.bytes
= createByteArray(row
, roffset
, rlength
,
686 family
, foffset
, flength
, qualifier
, qoffset
, qlength
,
687 timestamp
, type
, value
, voffset
, vlength
, tags
, tagsOffset
, tagsLength
);
688 this.length
= bytes
.length
;
693 * Constructs an empty KeyValue structure, with specified sizes.
694 * This can be used to partially fill up KeyValues.
696 * Column is split into two fields, family and qualifier.
697 * @param rlength row length
698 * @param flength family length
699 * @param qlength qualifier length
700 * @param timestamp version timestamp
701 * @param type key type
702 * @param vlength value length
703 * @throws IllegalArgumentException
705 public KeyValue(final int rlength
,
708 final long timestamp
, final Type type
,
710 this(rlength
, flength
, qlength
, timestamp
, type
, vlength
, 0);
714 * Constructs an empty KeyValue structure, with specified sizes.
715 * This can be used to partially fill up KeyValues.
717 * Column is split into two fields, family and qualifier.
718 * @param rlength row length
719 * @param flength family length
720 * @param qlength qualifier length
721 * @param timestamp version timestamp
722 * @param type key type
723 * @param vlength value length
725 * @throws IllegalArgumentException
727 public KeyValue(final int rlength
,
730 final long timestamp
, final Type type
,
731 final int vlength
, final int tagsLength
) {
732 this.bytes
= createEmptyByteArray(rlength
, flength
, qlength
, timestamp
, type
, vlength
,
734 this.length
= bytes
.length
;
739 public KeyValue(byte[] row
, int roffset
, int rlength
,
740 byte[] family
, int foffset
, int flength
,
741 ByteBuffer qualifier
, long ts
, Type type
, ByteBuffer value
, List
<Tag
> tags
) {
742 this.bytes
= createByteArray(row
, roffset
, rlength
, family
, foffset
, flength
,
743 qualifier
, 0, qualifier
== null ?
0 : qualifier
.remaining(), ts
, type
,
744 value
, 0, value
== null ?
0 : value
.remaining(), tags
);
745 this.length
= bytes
.length
;
749 public KeyValue(Cell c
) {
750 this(c
.getRowArray(), c
.getRowOffset(), c
.getRowLength(),
751 c
.getFamilyArray(), c
.getFamilyOffset(), c
.getFamilyLength(),
752 c
.getQualifierArray(), c
.getQualifierOffset(), c
.getQualifierLength(),
753 c
.getTimestamp(), Type
.codeToType(c
.getTypeByte()), c
.getValueArray(), c
.getValueOffset(),
754 c
.getValueLength(), c
.getTagsArray(), c
.getTagsOffset(), c
.getTagsLength());
755 this.seqId
= c
.getSequenceId();
759 * Create an empty byte[] representing a KeyValue
760 * All lengths are preset and can be filled in later.
767 * @return The newly created byte array.
769 private static byte[] createEmptyByteArray(final int rlength
, int flength
,
770 int qlength
, final long timestamp
, final Type type
, int vlength
, int tagsLength
) {
771 if (rlength
> Short
.MAX_VALUE
) {
772 throw new IllegalArgumentException("Row > " + Short
.MAX_VALUE
);
774 if (flength
> Byte
.MAX_VALUE
) {
775 throw new IllegalArgumentException("Family > " + Byte
.MAX_VALUE
);
778 if (qlength
> Integer
.MAX_VALUE
- rlength
- flength
) {
779 throw new IllegalArgumentException("Qualifier > " + Integer
.MAX_VALUE
);
781 RawCell
.checkForTagsLength(tagsLength
);
783 long longkeylength
= getKeyDataStructureSize(rlength
, flength
, qlength
);
784 if (longkeylength
> Integer
.MAX_VALUE
) {
785 throw new IllegalArgumentException("keylength " + longkeylength
+ " > " +
788 int keylength
= (int)longkeylength
;
790 if (vlength
> HConstants
.MAXIMUM_VALUE_LENGTH
) { // FindBugs INT_VACUOUS_COMPARISON
791 throw new IllegalArgumentException("Valuer > " +
792 HConstants
.MAXIMUM_VALUE_LENGTH
);
795 // Allocate right-sized byte array.
796 byte[] bytes
= new byte[(int) getKeyValueDataStructureSize(rlength
, flength
, qlength
, vlength
,
798 // Write the correct size markers
800 pos
= Bytes
.putInt(bytes
, pos
, keylength
);
801 pos
= Bytes
.putInt(bytes
, pos
, vlength
);
802 pos
= Bytes
.putShort(bytes
, pos
, (short)(rlength
& 0x0000ffff));
804 pos
= Bytes
.putByte(bytes
, pos
, (byte)(flength
& 0x0000ff));
805 pos
+= flength
+ qlength
;
806 pos
= Bytes
.putLong(bytes
, pos
, timestamp
);
807 pos
= Bytes
.putByte(bytes
, pos
, type
.getCode());
809 if (tagsLength
> 0) {
810 pos
= Bytes
.putAsShort(bytes
, pos
, tagsLength
);
816 * Checks the parameters passed to a constructor.
819 * @param rlength row length
820 * @param family family name
821 * @param flength family length
822 * @param qlength qualifier length
823 * @param vlength value length
825 * @throws IllegalArgumentException an illegal value was passed
827 static void checkParameters(final byte [] row
, final int rlength
,
828 final byte [] family
, int flength
, int qlength
, int vlength
)
829 throws IllegalArgumentException
{
830 if (rlength
> Short
.MAX_VALUE
) {
831 throw new IllegalArgumentException("Row > " + Short
.MAX_VALUE
);
834 throw new IllegalArgumentException("Row is null");
837 flength
= family
== null ?
0 : flength
;
838 if (flength
> Byte
.MAX_VALUE
) {
839 throw new IllegalArgumentException("Family > " + Byte
.MAX_VALUE
);
842 if (qlength
> Integer
.MAX_VALUE
- rlength
- flength
) {
843 throw new IllegalArgumentException("Qualifier > " + Integer
.MAX_VALUE
);
846 long longKeyLength
= getKeyDataStructureSize(rlength
, flength
, qlength
);
847 if (longKeyLength
> Integer
.MAX_VALUE
) {
848 throw new IllegalArgumentException("keylength " + longKeyLength
+ " > " +
852 if (vlength
> HConstants
.MAXIMUM_VALUE_LENGTH
) { // FindBugs INT_VACUOUS_COMPARISON
853 throw new IllegalArgumentException("Value length " + vlength
+ " > " +
854 HConstants
.MAXIMUM_VALUE_LENGTH
);
859 * Write KeyValue format into the provided byte array.
861 * @param buffer the bytes buffer to use
862 * @param boffset buffer offset
864 * @param roffset row offset
865 * @param rlength row length
866 * @param family family name
867 * @param foffset family offset
868 * @param flength family length
869 * @param qualifier column qualifier
870 * @param qoffset qualifier offset
871 * @param qlength qualifier length
872 * @param timestamp version timestamp
873 * @param type key type
874 * @param value column value
875 * @param voffset value offset
876 * @param vlength value length
878 * @return The number of useful bytes in the buffer.
880 * @throws IllegalArgumentException an illegal value was passed or there is insufficient space
881 * remaining in the buffer
883 public static int writeByteArray(byte [] buffer
, final int boffset
,
884 final byte [] row
, final int roffset
, final int rlength
,
885 final byte [] family
, final int foffset
, int flength
,
886 final byte [] qualifier
, final int qoffset
, int qlength
,
887 final long timestamp
, final Type type
,
888 final byte [] value
, final int voffset
, int vlength
, Tag
[] tags
) {
890 checkParameters(row
, rlength
, family
, flength
, qlength
, vlength
);
892 // Calculate length of tags area
894 if (tags
!= null && tags
.length
> 0) {
896 tagsLength
+= t
.getValueLength() + Tag
.INFRASTRUCTURE_SIZE
;
899 RawCell
.checkForTagsLength(tagsLength
);
900 int keyLength
= (int) getKeyDataStructureSize(rlength
, flength
, qlength
);
901 int keyValueLength
= (int) getKeyValueDataStructureSize(rlength
, flength
, qlength
, vlength
,
903 if (keyValueLength
> buffer
.length
- boffset
) {
904 throw new IllegalArgumentException("Buffer size " + (buffer
.length
- boffset
) + " < " +
908 // Write key, value and key row length.
910 pos
= Bytes
.putInt(buffer
, pos
, keyLength
);
911 pos
= Bytes
.putInt(buffer
, pos
, vlength
);
912 pos
= Bytes
.putShort(buffer
, pos
, (short)(rlength
& 0x0000ffff));
913 pos
= Bytes
.putBytes(buffer
, pos
, row
, roffset
, rlength
);
914 pos
= Bytes
.putByte(buffer
, pos
, (byte) (flength
& 0x0000ff));
916 pos
= Bytes
.putBytes(buffer
, pos
, family
, foffset
, flength
);
919 pos
= Bytes
.putBytes(buffer
, pos
, qualifier
, qoffset
, qlength
);
921 pos
= Bytes
.putLong(buffer
, pos
, timestamp
);
922 pos
= Bytes
.putByte(buffer
, pos
, type
.getCode());
923 if (value
!= null && value
.length
> 0) {
924 pos
= Bytes
.putBytes(buffer
, pos
, value
, voffset
, vlength
);
926 // Write the number of tags. If it is 0 then it means there are no tags.
927 if (tagsLength
> 0) {
928 pos
= Bytes
.putAsShort(buffer
, pos
, tagsLength
);
930 int tlen
= t
.getValueLength();
931 pos
= Bytes
.putAsShort(buffer
, pos
, tlen
+ Tag
.TYPE_LENGTH_SIZE
);
932 pos
= Bytes
.putByte(buffer
, pos
, t
.getType());
933 Tag
.copyValueTo(t
, buffer
, pos
);
937 return keyValueLength
;
941 * Write KeyValue format into a byte array.
943 * @param roffset row offset
944 * @param rlength row length
945 * @param family family name
946 * @param foffset family offset
947 * @param flength family length
948 * @param qualifier column qualifier
949 * @param qoffset qualifier offset
950 * @param qlength qualifier length
951 * @param timestamp version timestamp
952 * @param type key type
953 * @param value column value
954 * @param voffset value offset
955 * @param vlength value length
956 * @return The newly created byte array.
958 private static byte [] createByteArray(final byte [] row
, final int roffset
,
959 final int rlength
, final byte [] family
, final int foffset
, int flength
,
960 final byte [] qualifier
, final int qoffset
, int qlength
,
961 final long timestamp
, final Type type
,
962 final byte [] value
, final int voffset
,
963 int vlength
, byte[] tags
, int tagsOffset
, int tagsLength
) {
965 checkParameters(row
, rlength
, family
, flength
, qlength
, vlength
);
966 RawCell
.checkForTagsLength(tagsLength
);
967 // Allocate right-sized byte array.
968 int keyLength
= (int) getKeyDataStructureSize(rlength
, flength
, qlength
);
969 byte[] bytes
= new byte[(int) getKeyValueDataStructureSize(rlength
, flength
, qlength
, vlength
,
971 // Write key, value and key row length.
973 pos
= Bytes
.putInt(bytes
, pos
, keyLength
);
974 pos
= Bytes
.putInt(bytes
, pos
, vlength
);
975 pos
= Bytes
.putShort(bytes
, pos
, (short)(rlength
& 0x0000ffff));
976 pos
= Bytes
.putBytes(bytes
, pos
, row
, roffset
, rlength
);
977 pos
= Bytes
.putByte(bytes
, pos
, (byte)(flength
& 0x0000ff));
979 pos
= Bytes
.putBytes(bytes
, pos
, family
, foffset
, flength
);
982 pos
= Bytes
.putBytes(bytes
, pos
, qualifier
, qoffset
, qlength
);
984 pos
= Bytes
.putLong(bytes
, pos
, timestamp
);
985 pos
= Bytes
.putByte(bytes
, pos
, type
.getCode());
986 if (value
!= null && value
.length
> 0) {
987 pos
= Bytes
.putBytes(bytes
, pos
, value
, voffset
, vlength
);
989 // Add the tags after the value part
990 if (tagsLength
> 0) {
991 pos
= Bytes
.putAsShort(bytes
, pos
, tagsLength
);
992 pos
= Bytes
.putBytes(bytes
, pos
, tags
, tagsOffset
, tagsLength
);
998 * @param qualifier can be a ByteBuffer or a byte[], or null.
999 * @param value can be a ByteBuffer or a byte[], or null.
1001 private static byte [] createByteArray(final byte [] row
, final int roffset
,
1002 final int rlength
, final byte [] family
, final int foffset
, int flength
,
1003 final Object qualifier
, final int qoffset
, int qlength
,
1004 final long timestamp
, final Type type
,
1005 final Object value
, final int voffset
, int vlength
, List
<Tag
> tags
) {
1007 checkParameters(row
, rlength
, family
, flength
, qlength
, vlength
);
1009 // Calculate length of tags area
1011 if (tags
!= null && !tags
.isEmpty()) {
1012 for (Tag t
: tags
) {
1013 tagsLength
+= t
.getValueLength() + Tag
.INFRASTRUCTURE_SIZE
;
1016 RawCell
.checkForTagsLength(tagsLength
);
1017 // Allocate right-sized byte array.
1018 int keyLength
= (int) getKeyDataStructureSize(rlength
, flength
, qlength
);
1019 byte[] bytes
= new byte[(int) getKeyValueDataStructureSize(rlength
, flength
, qlength
, vlength
,
1022 // Write key, value and key row length.
1024 pos
= Bytes
.putInt(bytes
, pos
, keyLength
);
1026 pos
= Bytes
.putInt(bytes
, pos
, vlength
);
1027 pos
= Bytes
.putShort(bytes
, pos
, (short)(rlength
& 0x0000ffff));
1028 pos
= Bytes
.putBytes(bytes
, pos
, row
, roffset
, rlength
);
1029 pos
= Bytes
.putByte(bytes
, pos
, (byte)(flength
& 0x0000ff));
1031 pos
= Bytes
.putBytes(bytes
, pos
, family
, foffset
, flength
);
1034 if (qualifier
instanceof ByteBuffer
) {
1035 pos
= Bytes
.putByteBuffer(bytes
, pos
, (ByteBuffer
) qualifier
);
1037 pos
= Bytes
.putBytes(bytes
, pos
, (byte[]) qualifier
, qoffset
, qlength
);
1040 pos
= Bytes
.putLong(bytes
, pos
, timestamp
);
1041 pos
= Bytes
.putByte(bytes
, pos
, type
.getCode());
1043 if (value
instanceof ByteBuffer
) {
1044 pos
= Bytes
.putByteBuffer(bytes
, pos
, (ByteBuffer
) value
);
1046 pos
= Bytes
.putBytes(bytes
, pos
, (byte[]) value
, voffset
, vlength
);
1049 // Add the tags after the value part
1050 if (tagsLength
> 0) {
1051 pos
= Bytes
.putAsShort(bytes
, pos
, tagsLength
);
1052 for (Tag t
: tags
) {
1053 int tlen
= t
.getValueLength();
1054 pos
= Bytes
.putAsShort(bytes
, pos
, tlen
+ Tag
.TYPE_LENGTH_SIZE
);
1055 pos
= Bytes
.putByte(bytes
, pos
, t
.getType());
1056 Tag
.copyValueTo(t
, bytes
, pos
);
1064 * Needed doing 'contains' on List. Only compares the key portion, not the value.
1067 public boolean equals(Object other
) {
1068 if (!(other
instanceof Cell
)) {
1071 return CellUtil
.equals(this, (Cell
)other
);
1075 * In line with {@link #equals(Object)}, only uses the key portion, not the value.
1078 public int hashCode() {
1079 return calculateHashForKey(this);
1082 private int calculateHashForKey(Cell cell
) {
1083 // pre-calculate the 3 hashes made of byte ranges
1084 int rowHash
= Bytes
.hashCode(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
1085 int familyHash
= Bytes
.hashCode(cell
.getFamilyArray(), cell
.getFamilyOffset(),
1086 cell
.getFamilyLength());
1087 int qualifierHash
= Bytes
.hashCode(cell
.getQualifierArray(), cell
.getQualifierOffset(),
1088 cell
.getQualifierLength());
1090 // combine the 6 sub-hashes
1091 int hash
= 31 * rowHash
+ familyHash
;
1092 hash
= 31 * hash
+ qualifierHash
;
1093 hash
= 31 * hash
+ (int) cell
.getTimestamp();
1094 hash
= 31 * hash
+ cell
.getTypeByte();
1098 //---------------------------------------------------------------------------
1102 //---------------------------------------------------------------------------
1105 * Clones a KeyValue. This creates a copy, re-allocating the buffer.
1106 * @return Fully copied clone of this KeyValue
1107 * @throws CloneNotSupportedException
1110 public KeyValue
clone() throws CloneNotSupportedException
{
1112 byte [] b
= new byte[this.length
];
1113 System
.arraycopy(this.bytes
, this.offset
, b
, 0, this.length
);
1114 KeyValue ret
= new KeyValue(b
, 0, b
.length
);
1115 // Important to clone the memstoreTS as well - otherwise memstore's
1116 // update-in-place methods (eg increment) will end up creating
1118 ret
.setSequenceId(seqId
);
1123 * Creates a shallow copy of this KeyValue, reusing the data byte buffer.
1124 * http://en.wikipedia.org/wiki/Object_copy
1125 * @return Shallow copy of this KeyValue
1127 public KeyValue
shallowCopy() {
1128 KeyValue shallowCopy
= new KeyValue(this.bytes
, this.offset
, this.length
);
1129 shallowCopy
.setSequenceId(this.seqId
);
1133 //---------------------------------------------------------------------------
1135 // String representation
1137 //---------------------------------------------------------------------------
1140 public String
toString() {
1141 if (this.bytes
== null || this.bytes
.length
== 0) {
1144 return keyToString(this.bytes
, this.offset
+ ROW_OFFSET
, getKeyLength()) + "/vlen="
1145 + getValueLength() + "/seqid=" + seqId
;
1149 * @param k Key portion of a KeyValue.
1150 * @return Key as a String, empty string if k is null.
1152 public static String
keyToString(final byte [] k
) {
1156 return keyToString(k
, 0, k
.length
);
1160 * Produces a string map for this key/value pair. Useful for programmatic use
1161 * and manipulation of the data stored in an WALKey, for example, printing
1162 * as JSON. Values are left out due to their tendency to be large. If needed,
1163 * they can be added manually.
1165 * @return the Map<String,?> containing data from this key
1167 public Map
<String
, Object
> toStringMap() {
1168 Map
<String
, Object
> stringMap
= new HashMap
<>();
1169 stringMap
.put("row", Bytes
.toStringBinary(getRowArray(), getRowOffset(), getRowLength()));
1170 stringMap
.put("family",
1171 Bytes
.toStringBinary(getFamilyArray(), getFamilyOffset(), getFamilyLength()));
1172 stringMap
.put("qualifier",
1173 Bytes
.toStringBinary(getQualifierArray(), getQualifierOffset(), getQualifierLength()));
1174 stringMap
.put("timestamp", getTimestamp());
1175 stringMap
.put("vlen", getValueLength());
1176 Iterator
<Tag
> tags
= getTags();
1178 List
<String
> tagsString
= new ArrayList
<String
>();
1179 while (tags
.hasNext()) {
1180 tagsString
.add(tags
.next().toString());
1182 stringMap
.put("tag", tagsString
);
1189 * @param b Key portion of a KeyValue.
1190 * @param o Offset to start of key
1191 * @param l Length of key.
1192 * @return Key as a String.
1194 public static String
keyToString(final byte [] b
, final int o
, final int l
) {
1195 if (b
== null) return "";
1196 int rowlength
= Bytes
.toShort(b
, o
);
1197 String row
= Bytes
.toStringBinary(b
, o
+ Bytes
.SIZEOF_SHORT
, rowlength
);
1198 int columnoffset
= o
+ Bytes
.SIZEOF_SHORT
+ 1 + rowlength
;
1199 int familylength
= b
[columnoffset
- 1];
1200 int columnlength
= l
- ((columnoffset
- o
) + TIMESTAMP_TYPE_SIZE
);
1201 String family
= familylength
== 0?
"":
1202 Bytes
.toStringBinary(b
, columnoffset
, familylength
);
1203 String qualifier
= columnlength
== 0?
"":
1204 Bytes
.toStringBinary(b
, columnoffset
+ familylength
,
1205 columnlength
- familylength
);
1206 long timestamp
= Bytes
.toLong(b
, o
+ (l
- TIMESTAMP_TYPE_SIZE
));
1207 String timestampStr
= humanReadableTimestamp(timestamp
);
1208 byte type
= b
[o
+ l
- 1];
1209 return row
+ "/" + family
+
1210 (family
!= null && family
.length() > 0?
":" :"") +
1211 qualifier
+ "/" + timestampStr
+ "/" + Type
.codeToType(type
);
1214 public static String
humanReadableTimestamp(final long timestamp
) {
1215 if (timestamp
== HConstants
.LATEST_TIMESTAMP
) {
1216 return "LATEST_TIMESTAMP";
1218 if (timestamp
== HConstants
.OLDEST_TIMESTAMP
) {
1219 return "OLDEST_TIMESTAMP";
1221 return String
.valueOf(timestamp
);
1224 //---------------------------------------------------------------------------
1226 // Public Member Accessors
1228 //---------------------------------------------------------------------------
1231 * To be used only in tests where the Cells are clearly assumed to be of type KeyValue
1232 * and that we need access to the backing array to do some test case related assertions.
1233 * @return The byte array backing this KeyValue.
1236 public byte [] getBuffer() {
1241 * @return Offset into {@link #getBuffer()} at which this KeyValue starts.
1243 public int getOffset() {
1248 * @return Length of bytes this KeyValue occupies in {@link #getBuffer()}.
1250 public int getLength() {
1254 //---------------------------------------------------------------------------
1256 // Length and Offset Calculators
1258 //---------------------------------------------------------------------------
1261 * Determines the total length of the KeyValue stored in the specified
1262 * byte array and offset. Includes all headers.
1263 * @param bytes byte array
1264 * @param offset offset to start of the KeyValue
1265 * @return length of entire KeyValue, in bytes
1267 private static int getLength(byte [] bytes
, int offset
) {
1268 int klength
= ROW_OFFSET
+ Bytes
.toInt(bytes
, offset
);
1269 int vlength
= Bytes
.toInt(bytes
, offset
+ Bytes
.SIZEOF_INT
);
1270 return klength
+ vlength
;
1274 * @return Key offset in backing buffer..
1276 public int getKeyOffset() {
1277 return this.offset
+ ROW_OFFSET
;
1280 public String
getKeyString() {
1281 return Bytes
.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
1285 * @return Length of key portion.
1287 public int getKeyLength() {
1288 return Bytes
.toInt(this.bytes
, this.offset
);
1292 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1295 public byte[] getValueArray() {
1300 * @return the value offset
1303 public int getValueOffset() {
1304 int voffset
= getKeyOffset() + getKeyLength();
1309 * @return Value length
1312 public int getValueLength() {
1313 int vlength
= Bytes
.toInt(this.bytes
, this.offset
+ Bytes
.SIZEOF_INT
);
1318 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1321 public byte[] getRowArray() {
1326 * @return Row offset
1329 public int getRowOffset() {
1330 return this.offset
+ ROW_KEY_OFFSET
;
1334 * @return Row length
1337 public short getRowLength() {
1338 return Bytes
.toShort(this.bytes
, getKeyOffset());
1342 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1345 public byte[] getFamilyArray() {
1350 * @return Family offset
1353 public int getFamilyOffset() {
1354 return getFamilyOffset(getRowLength());
1358 * @return Family offset
1360 private int getFamilyOffset(int rlength
) {
1361 return this.offset
+ ROW_KEY_OFFSET
+ rlength
+ Bytes
.SIZEOF_BYTE
;
1365 * @return Family length
1368 public byte getFamilyLength() {
1369 return getFamilyLength(getFamilyOffset());
1373 * @return Family length
1375 public byte getFamilyLength(int foffset
) {
1376 return this.bytes
[foffset
-1];
1380 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1383 public byte[] getQualifierArray() {
1388 * @return Qualifier offset
1391 public int getQualifierOffset() {
1392 return getQualifierOffset(getFamilyOffset());
1396 * @return Qualifier offset
1398 private int getQualifierOffset(int foffset
) {
1399 return foffset
+ getFamilyLength(foffset
);
1403 * @return Qualifier length
1406 public int getQualifierLength() {
1407 return getQualifierLength(getRowLength(),getFamilyLength());
1411 * @return Qualifier length
1413 private int getQualifierLength(int rlength
, int flength
) {
1414 return getKeyLength() - (int) getKeyDataStructureSize(rlength
, flength
, 0);
1418 * @return Timestamp offset
1420 public int getTimestampOffset() {
1421 return getTimestampOffset(getKeyLength());
1425 * @param keylength Pass if you have it to save on a int creation.
1426 * @return Timestamp offset
1428 private int getTimestampOffset(final int keylength
) {
1429 return getKeyOffset() + keylength
- TIMESTAMP_TYPE_SIZE
;
1433 * @return True if this KeyValue has a LATEST_TIMESTAMP timestamp.
1435 public boolean isLatestTimestamp() {
1436 return Bytes
.equals(getBuffer(), getTimestampOffset(), Bytes
.SIZEOF_LONG
,
1437 HConstants
.LATEST_TIMESTAMP_BYTES
, 0, Bytes
.SIZEOF_LONG
);
1441 * @param now Time to set into <code>this</code> IFF timestamp ==
1442 * {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
1443 * @return True is we modified this.
1445 public boolean updateLatestStamp(final byte [] now
) {
1446 if (this.isLatestTimestamp()) {
1447 int tsOffset
= getTimestampOffset();
1448 System
.arraycopy(now
, 0, this.bytes
, tsOffset
, Bytes
.SIZEOF_LONG
);
1449 // clear cache or else getTimestamp() possibly returns an old value
1456 public void setTimestamp(long ts
) {
1457 Bytes
.putBytes(this.bytes
, this.getTimestampOffset(), Bytes
.toBytes(ts
), 0, Bytes
.SIZEOF_LONG
);
1461 public void setTimestamp(byte[] ts
) {
1462 Bytes
.putBytes(this.bytes
, this.getTimestampOffset(), ts
, 0, Bytes
.SIZEOF_LONG
);
1465 //---------------------------------------------------------------------------
1467 // Methods that return copies of fields
1469 //---------------------------------------------------------------------------
1472 * Do not use unless you have to. Used internally for compacting and testing. Use
1473 * {@link #getRowArray()}, {@link #getFamilyArray()}, {@link #getQualifierArray()}, and
1474 * {@link #getValueArray()} if accessing a KeyValue client-side.
1475 * @return Copy of the key portion only.
1477 public byte [] getKey() {
1478 int keylength
= getKeyLength();
1479 byte [] key
= new byte[keylength
];
1480 System
.arraycopy(getBuffer(), getKeyOffset(), key
, 0, keylength
);
1489 public long getTimestamp() {
1490 return getTimestamp(getKeyLength());
1494 * @param keylength Pass if you have it to save on a int creation.
1497 long getTimestamp(final int keylength
) {
1498 int tsOffset
= getTimestampOffset(keylength
);
1499 return Bytes
.toLong(this.bytes
, tsOffset
);
1503 * @return KeyValue.TYPE byte representation
1506 public byte getTypeByte() {
1507 return this.bytes
[this.offset
+ getKeyLength() - 1 + ROW_OFFSET
];
1511 * This returns the offset where the tag actually starts.
1514 public int getTagsOffset() {
1515 int tagsLen
= getTagsLength();
1517 return this.offset
+ this.length
;
1519 return this.offset
+ this.length
- tagsLen
;
1523 * This returns the total length of the tag bytes
1526 public int getTagsLength() {
1527 int tagsLen
= this.length
- (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE
);
1529 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is added to denote the tags
1531 tagsLen
-= TAGS_LENGTH_SIZE
;
1537 * @return the backing array of the entire KeyValue (all KeyValue fields are in a single array)
1540 public byte[] getTagsArray() {
1545 * Creates a new KeyValue that only contains the key portion (the value is
1548 * TODO only used by KeyOnlyFilter -- move there.
1549 * @param lenAsVal replace value with the actual value length (false=empty)
1551 public KeyValue
createKeyOnly(boolean lenAsVal
) {
1552 // KV format: <keylen:4><valuelen:4><key:keylen><value:valuelen>
1553 // Rebuild as: <keylen:4><0:4><key:keylen>
1554 int dataLen
= lenAsVal? Bytes
.SIZEOF_INT
: 0;
1555 byte [] newBuffer
= new byte[getKeyLength() + ROW_OFFSET
+ dataLen
];
1556 System
.arraycopy(this.bytes
, this.offset
, newBuffer
, 0,
1557 Math
.min(newBuffer
.length
,this.length
));
1558 Bytes
.putInt(newBuffer
, Bytes
.SIZEOF_INT
, dataLen
);
1560 Bytes
.putInt(newBuffer
, newBuffer
.length
- dataLen
, this.getValueLength());
1562 return new KeyValue(newBuffer
);
1568 * @return Index of delimiter having started from start of <code>b</code>
1571 public static int getDelimiter(final byte [] b
, int offset
, final int length
,
1572 final int delimiter
) {
1574 throw new IllegalArgumentException("Passed buffer is null");
1577 for (int i
= offset
; i
< length
+ offset
; i
++) {
1578 if (b
[i
] == delimiter
) {
1587 * Find index of passed delimiter walking from end of buffer backwards.
1590 * @return Index of delimiter
1592 public static int getDelimiterInReverse(final byte [] b
, final int offset
,
1593 final int length
, final int delimiter
) {
1595 throw new IllegalArgumentException("Passed buffer is null");
1598 for (int i
= (offset
+ length
) - 1; i
>= offset
; i
--) {
1599 if (b
[i
] == delimiter
) {
1608 * A {@link KVComparator} for <code>hbase:meta</code> catalog table
1609 * {@link KeyValue}s.
1610 * @deprecated : {@link MetaCellComparator#META_COMPARATOR} to be used.
1611 * Deprecated for hbase 2.0, remove for hbase 3.0.
1614 public static class MetaComparator
extends KVComparator
{
1616 * Compare key portion of a {@link KeyValue} for keys in <code>hbase:meta</code>
1620 public int compare(final Cell left
, final Cell right
) {
1621 return PrivateCellUtil
.compareKeyIgnoresMvcc(MetaCellComparator
.META_COMPARATOR
, left
,
1626 public int compareOnlyKeyPortion(Cell left
, Cell right
) {
1627 return compare(left
, right
);
1631 public int compareRows(byte [] left
, int loffset
, int llength
,
1632 byte [] right
, int roffset
, int rlength
) {
1633 int leftDelimiter
= getDelimiter(left
, loffset
, llength
,
1634 HConstants
.DELIMITER
);
1635 int rightDelimiter
= getDelimiter(right
, roffset
, rlength
,
1636 HConstants
.DELIMITER
);
1637 // Compare up to the delimiter
1638 int lpart
= (leftDelimiter
< 0 ? llength
:leftDelimiter
- loffset
);
1639 int rpart
= (rightDelimiter
< 0 ? rlength
:rightDelimiter
- roffset
);
1640 int result
= Bytes
.compareTo(left
, loffset
, lpart
, right
, roffset
, rpart
);
1644 if (leftDelimiter
< 0 && rightDelimiter
>= 0) {
1646 } else if (rightDelimiter
< 0 && leftDelimiter
>= 0) {
1648 } else if (leftDelimiter
< 0 && rightDelimiter
< 0) {
1652 // Compare middle bit of the row.
1653 // Move past delimiter
1656 int leftFarDelimiter
= getDelimiterInReverse(left
, leftDelimiter
,
1657 llength
- (leftDelimiter
- loffset
), HConstants
.DELIMITER
);
1658 int rightFarDelimiter
= getDelimiterInReverse(right
,
1659 rightDelimiter
, rlength
- (rightDelimiter
- roffset
),
1660 HConstants
.DELIMITER
);
1661 // Now compare middlesection of row.
1662 lpart
= (leftFarDelimiter
< 0 ? llength
+ loffset
: leftFarDelimiter
) - leftDelimiter
;
1663 rpart
= (rightFarDelimiter
< 0 ? rlength
+ roffset
: rightFarDelimiter
)- rightDelimiter
;
1664 result
= super.compareRows(left
, leftDelimiter
, lpart
, right
, rightDelimiter
, rpart
);
1668 if (leftDelimiter
< 0 && rightDelimiter
>= 0) {
1670 } else if (rightDelimiter
< 0 && leftDelimiter
>= 0) {
1672 } else if (leftDelimiter
< 0 && rightDelimiter
< 0) {
1676 // Compare last part of row, the rowid.
1678 rightFarDelimiter
++;
1679 result
= Bytes
.compareTo(left
, leftFarDelimiter
, llength
- (leftFarDelimiter
- loffset
),
1680 right
, rightFarDelimiter
, rlength
- (rightFarDelimiter
- roffset
));
1685 * Don't do any fancy Block Index splitting tricks.
1688 public byte[] getShortMidpointKey(final byte[] leftKey
, final byte[] rightKey
) {
1689 return Arrays
.copyOf(rightKey
, rightKey
.length
);
1693 * The HFileV2 file format's trailer contains this class name. We reinterpret this and
1694 * instantiate the appropriate comparator.
1695 * TODO: With V3 consider removing this.
1696 * @return legacy class name for FileFileTrailer#comparatorClassName
1699 public String
getLegacyKeyComparatorName() {
1700 return "org.apache.hadoop.hbase.KeyValue$MetaKeyComparator";
1704 protected Object
clone() throws CloneNotSupportedException
{
1705 return new MetaComparator();
1709 * Override the row key comparison to parse and compare the meta row key parts.
1712 protected int compareRowKey(final Cell l
, final Cell r
) {
1713 byte[] left
= l
.getRowArray();
1714 int loffset
= l
.getRowOffset();
1715 int llength
= l
.getRowLength();
1716 byte[] right
= r
.getRowArray();
1717 int roffset
= r
.getRowOffset();
1718 int rlength
= r
.getRowLength();
1719 return compareRows(left
, loffset
, llength
, right
, roffset
, rlength
);
1724 * Compare KeyValues. When we compare KeyValues, we only compare the Key
1725 * portion. This means two KeyValues with same Key but different Values are
1726 * considered the same as far as this Comparator is concerned.
1727 * @deprecated : Use {@link CellComparatorImpl}. Deprecated for hbase 2.0, remove for hbase 3.0.
1730 public static class KVComparator
implements RawComparator
<Cell
>, SamePrefixComparator
<byte[]> {
1733 * The HFileV2 file format's trailer contains this class name. We reinterpret this and
1734 * instantiate the appropriate comparator.
1735 * TODO: With V3 consider removing this.
1736 * @return legacy class name for FileFileTrailer#comparatorClassName
1738 public String
getLegacyKeyComparatorName() {
1739 return "org.apache.hadoop.hbase.KeyValue$KeyComparator";
1742 @Override // RawComparator
1743 public int compare(byte[] l
, int loff
, int llen
, byte[] r
, int roff
, int rlen
) {
1744 return compareFlatKey(l
,loff
,llen
, r
,roff
,rlen
);
1749 * Compares the only the user specified portion of a Key. This is overridden by MetaComparator.
1752 * @return 0 if equal, <0 if left smaller, >0 if right smaller
1754 protected int compareRowKey(final Cell left
, final Cell right
) {
1755 return CellComparatorImpl
.COMPARATOR
.compareRows(left
, right
);
1759 * Compares left to right assuming that left,loffset,llength and right,roffset,rlength are
1760 * full KVs laid out in a flat byte[]s.
1767 * @return 0 if equal, <0 if left smaller, >0 if right smaller
1769 public int compareFlatKey(byte[] left
, int loffset
, int llength
,
1770 byte[] right
, int roffset
, int rlength
) {
1772 short lrowlength
= Bytes
.toShort(left
, loffset
);
1773 short rrowlength
= Bytes
.toShort(right
, roffset
);
1774 int compare
= compareRows(left
, loffset
+ Bytes
.SIZEOF_SHORT
,
1775 lrowlength
, right
, roffset
+ Bytes
.SIZEOF_SHORT
, rrowlength
);
1780 // Compare the rest of the two KVs without making any assumptions about
1781 // the common prefix. This function will not compare rows anyway, so we
1782 // don't need to tell it that the common prefix includes the row.
1783 return compareWithoutRow(0, left
, loffset
, llength
, right
, roffset
,
1784 rlength
, rrowlength
);
1787 public int compareFlatKey(byte[] left
, byte[] right
) {
1788 return compareFlatKey(left
, 0, left
.length
, right
, 0, right
.length
);
1791 // compare a key against row/fam/qual/ts/type
1792 public int compareKey(Cell cell
,
1793 byte[] row
, int roff
, int rlen
,
1794 byte[] fam
, int foff
, int flen
,
1795 byte[] col
, int coff
, int clen
,
1796 long ts
, byte type
) {
1798 int compare
= compareRows(
1799 cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
1804 // If the column is not specified, the "minimum" key type appears the
1805 // latest in the sorted order, regardless of the timestamp. This is used
1806 // for specifying the last key/value in a given row, because there is no
1807 // "lexicographically last column" (it would be infinitely long). The
1808 // "maximum" key type does not need this behavior.
1809 if (cell
.getFamilyLength() + cell
.getQualifierLength() == 0
1810 && cell
.getTypeByte() == Type
.Minimum
.getCode()) {
1811 // left is "bigger", i.e. it appears later in the sorted order
1814 if (flen
+clen
== 0 && type
== Type
.Minimum
.getCode()) {
1818 compare
= compareFamilies(
1819 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
1824 compare
= compareColumns(
1825 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength(),
1830 // Next compare timestamps.
1831 compare
= compareTimestamps(cell
.getTimestamp(), ts
);
1836 // Compare types. Let the delete types sort ahead of puts; i.e. types
1837 // of higher numbers sort before those of lesser numbers. Maximum (255)
1838 // appears ahead of everything, and minimum (0) appears after
1840 return (0xff & type
) - (0xff & cell
.getTypeByte());
1843 public int compareOnlyKeyPortion(Cell left
, Cell right
) {
1844 return PrivateCellUtil
.compareKeyIgnoresMvcc(CellComparatorImpl
.COMPARATOR
, left
, right
);
1848 * Compares the Key of a cell -- with fields being more significant in this order:
1849 * rowkey, colfam/qual, timestamp, type, mvcc
1852 public int compare(final Cell left
, final Cell right
) {
1853 int compare
= CellComparatorImpl
.COMPARATOR
.compare(left
, right
);
1857 public int compareTimestamps(final Cell left
, final Cell right
) {
1858 return CellComparatorImpl
.COMPARATOR
.compareTimestamps(left
, right
);
1864 * @return Result comparing rows.
1866 public int compareRows(final Cell left
, final Cell right
) {
1867 return compareRows(left
.getRowArray(),left
.getRowOffset(), left
.getRowLength(),
1868 right
.getRowArray(), right
.getRowOffset(), right
.getRowLength());
1872 * Get the b[],o,l for left and right rowkey portions and compare.
1879 * @return 0 if equal, <0 if left smaller, >0 if right smaller
1881 public int compareRows(byte [] left
, int loffset
, int llength
,
1882 byte [] right
, int roffset
, int rlength
) {
1883 return Bytes
.compareTo(left
, loffset
, llength
, right
, roffset
, rlength
);
1886 int compareColumns(final Cell left
, final short lrowlength
, final Cell right
,
1887 final short rrowlength
) {
1888 return CellComparatorImpl
.COMPARATOR
.compareColumns(left
, right
);
1891 protected int compareColumns(
1892 byte [] left
, int loffset
, int llength
, final int lfamilylength
,
1893 byte [] right
, int roffset
, int rlength
, final int rfamilylength
) {
1894 // Compare family portion first.
1895 int diff
= Bytes
.compareTo(left
, loffset
, lfamilylength
,
1896 right
, roffset
, rfamilylength
);
1900 // Compare qualifier portion
1901 return Bytes
.compareTo(left
, loffset
+ lfamilylength
,
1902 llength
- lfamilylength
,
1903 right
, roffset
+ rfamilylength
, rlength
- rfamilylength
);
1906 static int compareTimestamps(final long ltimestamp
, final long rtimestamp
) {
1907 // The below older timestamps sorting ahead of newer timestamps looks
1908 // wrong but it is intentional. This way, newer timestamps are first
1909 // found when we iterate over a memstore and newer versions are the
1910 // first we trip over when reading from a store file.
1911 if (ltimestamp
< rtimestamp
) {
1913 } else if (ltimestamp
> rtimestamp
) {
1921 * @param commonPrefix
1928 * @return 0 if equal, <0 if left smaller, >0 if right smaller
1930 @Override // SamePrefixComparator
1931 public int compareIgnoringPrefix(int commonPrefix
, byte[] left
,
1932 int loffset
, int llength
, byte[] right
, int roffset
, int rlength
) {
1934 short lrowlength
= Bytes
.toShort(left
, loffset
);
1937 int comparisonResult
= 0;
1938 if (commonPrefix
< ROW_LENGTH_SIZE
) {
1939 // almost nothing in common
1940 rrowlength
= Bytes
.toShort(right
, roffset
);
1941 comparisonResult
= compareRows(left
, loffset
+ ROW_LENGTH_SIZE
,
1942 lrowlength
, right
, roffset
+ ROW_LENGTH_SIZE
, rrowlength
);
1943 } else { // the row length is the same
1944 rrowlength
= lrowlength
;
1945 if (commonPrefix
< ROW_LENGTH_SIZE
+ rrowlength
) {
1946 // The rows are not the same. Exclude the common prefix and compare
1947 // the rest of the two rows.
1948 int common
= commonPrefix
- ROW_LENGTH_SIZE
;
1949 comparisonResult
= compareRows(
1950 left
, loffset
+ common
+ ROW_LENGTH_SIZE
, lrowlength
- common
,
1951 right
, roffset
+ common
+ ROW_LENGTH_SIZE
, rrowlength
- common
);
1954 if (comparisonResult
!= 0) {
1955 return comparisonResult
;
1958 assert lrowlength
== rrowlength
;
1959 return compareWithoutRow(commonPrefix
, left
, loffset
, llength
, right
,
1960 roffset
, rlength
, lrowlength
);
1964 * Compare columnFamily, qualifier, timestamp, and key type (everything
1965 * except the row). This method is used both in the normal comparator and
1966 * the "same-prefix" comparator. Note that we are assuming that row portions
1967 * of both KVs have already been parsed and found identical, and we don't
1968 * validate that assumption here.
1969 * @param commonPrefix
1970 * the length of the common prefix of the two key-values being
1971 * compared, including row length and row
1973 private int compareWithoutRow(int commonPrefix
, byte[] left
, int loffset
,
1974 int llength
, byte[] right
, int roffset
, int rlength
, short rowlength
) {
1976 * KeyValue Format and commonLength:
1977 * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
1978 * ------------------|-------commonLength--------|--------------
1980 int commonLength
= ROW_LENGTH_SIZE
+ FAMILY_LENGTH_SIZE
+ rowlength
;
1982 // commonLength + TIMESTAMP_TYPE_SIZE
1983 int commonLengthWithTSAndType
= TIMESTAMP_TYPE_SIZE
+ commonLength
;
1984 // ColumnFamily + Qualifier length.
1985 int lcolumnlength
= llength
- commonLengthWithTSAndType
;
1986 int rcolumnlength
= rlength
- commonLengthWithTSAndType
;
1988 byte ltype
= left
[loffset
+ (llength
- 1)];
1989 byte rtype
= right
[roffset
+ (rlength
- 1)];
1991 // If the column is not specified, the "minimum" key type appears the
1992 // latest in the sorted order, regardless of the timestamp. This is used
1993 // for specifying the last key/value in a given row, because there is no
1994 // "lexicographically last column" (it would be infinitely long). The
1995 // "maximum" key type does not need this behavior.
1996 if (lcolumnlength
== 0 && ltype
== Type
.Minimum
.getCode()) {
1997 // left is "bigger", i.e. it appears later in the sorted order
2000 if (rcolumnlength
== 0 && rtype
== Type
.Minimum
.getCode()) {
2004 int lfamilyoffset
= commonLength
+ loffset
;
2005 int rfamilyoffset
= commonLength
+ roffset
;
2007 // Column family length.
2008 int lfamilylength
= left
[lfamilyoffset
- 1];
2009 int rfamilylength
= right
[rfamilyoffset
- 1];
2010 // If left family size is not equal to right family size, we need not
2011 // compare the qualifiers.
2012 boolean sameFamilySize
= (lfamilylength
== rfamilylength
);
2014 if (commonPrefix
> 0) {
2015 common
= Math
.max(0, commonPrefix
- commonLength
);
2016 if (!sameFamilySize
) {
2017 // Common should not be larger than Math.min(lfamilylength,
2019 common
= Math
.min(common
, Math
.min(lfamilylength
, rfamilylength
));
2021 common
= Math
.min(common
, Math
.min(lcolumnlength
, rcolumnlength
));
2024 if (!sameFamilySize
) {
2025 // comparing column family is enough.
2026 return Bytes
.compareTo(left
, lfamilyoffset
+ common
, lfamilylength
2027 - common
, right
, rfamilyoffset
+ common
, rfamilylength
- common
);
2029 // Compare family & qualifier together.
2030 final int comparison
= Bytes
.compareTo(left
, lfamilyoffset
+ common
,
2031 lcolumnlength
- common
, right
, rfamilyoffset
+ common
,
2032 rcolumnlength
- common
);
2033 if (comparison
!= 0) {
2038 // Next compare timestamps.
2039 long ltimestamp
= Bytes
.toLong(left
,
2040 loffset
+ (llength
- TIMESTAMP_TYPE_SIZE
));
2041 long rtimestamp
= Bytes
.toLong(right
,
2042 roffset
+ (rlength
- TIMESTAMP_TYPE_SIZE
));
2043 int compare
= compareTimestamps(ltimestamp
, rtimestamp
);
2048 // Compare types. Let the delete types sort ahead of puts; i.e. types
2049 // of higher numbers sort before those of lesser numbers. Maximum (255)
2050 // appears ahead of everything, and minimum (0) appears after
2052 return (0xff & rtype
) - (0xff & ltype
);
2055 protected int compareFamilies(final byte[] left
, final int loffset
, final int lfamilylength
,
2056 final byte[] right
, final int roffset
, final int rfamilylength
) {
2057 int diff
= Bytes
.compareTo(left
, loffset
, lfamilylength
, right
, roffset
, rfamilylength
);
2061 protected int compareColumns(final byte[] left
, final int loffset
, final int lquallength
,
2062 final byte[] right
, final int roffset
, final int rquallength
) {
2063 int diff
= Bytes
.compareTo(left
, loffset
, lquallength
, right
, roffset
, rquallength
);
2067 * Compares the row and column of two keyvalues for equality
2070 * @return True if same row and column.
2072 public boolean matchingRowColumn(final Cell left
,
2074 short lrowlength
= left
.getRowLength();
2075 short rrowlength
= right
.getRowLength();
2077 // TsOffset = end of column data. just comparing Row+CF length of each
2078 if ((left
.getRowLength() + left
.getFamilyLength() + left
.getQualifierLength()) != (right
2079 .getRowLength() + right
.getFamilyLength() + right
.getQualifierLength())) {
2083 if (!matchingRows(left
, lrowlength
, right
, rrowlength
)) {
2087 int lfoffset
= left
.getFamilyOffset();
2088 int rfoffset
= right
.getFamilyOffset();
2089 int lclength
= left
.getQualifierLength();
2090 int rclength
= right
.getQualifierLength();
2091 int lfamilylength
= left
.getFamilyLength();
2092 int rfamilylength
= right
.getFamilyLength();
2093 int diff
= compareFamilies(left
.getFamilyArray(), lfoffset
, lfamilylength
,
2094 right
.getFamilyArray(), rfoffset
, rfamilylength
);
2098 diff
= compareColumns(left
.getQualifierArray(), left
.getQualifierOffset(), lclength
,
2099 right
.getQualifierArray(), right
.getQualifierOffset(), rclength
);
2105 * Compares the row of two keyvalues for equality
2108 * @return True if rows match.
2110 public boolean matchingRows(final Cell left
, final Cell right
) {
2111 short lrowlength
= left
.getRowLength();
2112 short rrowlength
= right
.getRowLength();
2113 return matchingRows(left
, lrowlength
, right
, rrowlength
);
2121 * @return True if rows match.
2123 private boolean matchingRows(final Cell left
, final short lrowlength
,
2124 final Cell right
, final short rrowlength
) {
2125 return lrowlength
== rrowlength
&&
2126 matchingRows(left
.getRowArray(), left
.getRowOffset(), lrowlength
,
2127 right
.getRowArray(), right
.getRowOffset(), rrowlength
);
2131 * Compare rows. Just calls Bytes.equals, but it's good to have this encapsulated.
2132 * @param left Left row array.
2133 * @param loffset Left row offset.
2134 * @param llength Left row length.
2135 * @param right Right row array.
2136 * @param roffset Right row offset.
2137 * @param rlength Right row length.
2138 * @return Whether rows are the same row.
2140 public boolean matchingRows(final byte [] left
, final int loffset
, final int llength
,
2141 final byte [] right
, final int roffset
, final int rlength
) {
2142 return Bytes
.equals(left
, loffset
, llength
, right
, roffset
, rlength
);
2145 public byte[] calcIndexKey(byte[] lastKeyOfPreviousBlock
, byte[] firstKeyInBlock
) {
2146 byte[] fakeKey
= getShortMidpointKey(lastKeyOfPreviousBlock
, firstKeyInBlock
);
2147 if (compareFlatKey(fakeKey
, firstKeyInBlock
) > 0) {
2148 LOG
.error("Unexpected getShortMidpointKey result, fakeKey:"
2149 + Bytes
.toStringBinary(fakeKey
) + ", firstKeyInBlock:"
2150 + Bytes
.toStringBinary(firstKeyInBlock
));
2151 return firstKeyInBlock
;
2153 if (lastKeyOfPreviousBlock
!= null && compareFlatKey(lastKeyOfPreviousBlock
, fakeKey
) >= 0) {
2154 LOG
.error("Unexpected getShortMidpointKey result, lastKeyOfPreviousBlock:" +
2155 Bytes
.toStringBinary(lastKeyOfPreviousBlock
) + ", fakeKey:" +
2156 Bytes
.toStringBinary(fakeKey
));
2157 return firstKeyInBlock
;
2163 * This is a HFile block index key optimization.
2166 * @return 0 if equal, <0 if left smaller, >0 if right smaller
2167 * @deprecated Since 0.99.2;
2170 public byte[] getShortMidpointKey(final byte[] leftKey
, final byte[] rightKey
) {
2171 if (rightKey
== null) {
2172 throw new IllegalArgumentException("rightKey can not be null");
2174 if (leftKey
== null) {
2175 return Arrays
.copyOf(rightKey
, rightKey
.length
);
2177 if (compareFlatKey(leftKey
, rightKey
) >= 0) {
2178 throw new IllegalArgumentException("Unexpected input, leftKey:" + Bytes
.toString(leftKey
)
2179 + ", rightKey:" + Bytes
.toString(rightKey
));
2182 short leftRowLength
= Bytes
.toShort(leftKey
, 0);
2183 short rightRowLength
= Bytes
.toShort(rightKey
, 0);
2184 int leftCommonLength
= ROW_LENGTH_SIZE
+ FAMILY_LENGTH_SIZE
+ leftRowLength
;
2185 int rightCommonLength
= ROW_LENGTH_SIZE
+ FAMILY_LENGTH_SIZE
+ rightRowLength
;
2186 int leftCommonLengthWithTSAndType
= TIMESTAMP_TYPE_SIZE
+ leftCommonLength
;
2187 int rightCommonLengthWithTSAndType
= TIMESTAMP_TYPE_SIZE
+ rightCommonLength
;
2188 int leftColumnLength
= leftKey
.length
- leftCommonLengthWithTSAndType
;
2189 int rightColumnLength
= rightKey
.length
- rightCommonLengthWithTSAndType
;
2191 if (leftRowLength
== rightRowLength
&& compareRows(leftKey
, ROW_LENGTH_SIZE
, leftRowLength
,
2192 rightKey
, ROW_LENGTH_SIZE
, rightRowLength
) == 0) {
2193 // Compare family & qualifier together.
2194 int comparison
= Bytes
.compareTo(leftKey
, leftCommonLength
, leftColumnLength
, rightKey
,
2195 rightCommonLength
, rightColumnLength
);
2196 // same with "row + family + qualifier", return rightKey directly
2197 if (comparison
== 0) {
2198 return Arrays
.copyOf(rightKey
, rightKey
.length
);
2200 // "family + qualifier" are different, generate a faked key per rightKey
2201 byte[] newKey
= Arrays
.copyOf(rightKey
, rightKey
.length
);
2202 Bytes
.putLong(newKey
, rightKey
.length
- TIMESTAMP_TYPE_SIZE
, HConstants
.LATEST_TIMESTAMP
);
2203 Bytes
.putByte(newKey
, rightKey
.length
- TYPE_SIZE
, Type
.Maximum
.getCode());
2206 // rows are different
2207 short minLength
= leftRowLength
< rightRowLength ? leftRowLength
: rightRowLength
;
2209 while (diffIdx
< minLength
2210 && leftKey
[ROW_LENGTH_SIZE
+ diffIdx
] == rightKey
[ROW_LENGTH_SIZE
+ diffIdx
]) {
2213 byte[] newRowKey
= null;
2214 if (diffIdx
>= minLength
) {
2215 // leftKey's row is prefix of rightKey's.
2216 newRowKey
= new byte[diffIdx
+ 1];
2217 System
.arraycopy(rightKey
, ROW_LENGTH_SIZE
, newRowKey
, 0, diffIdx
+ 1);
2219 int diffByte
= leftKey
[ROW_LENGTH_SIZE
+ diffIdx
];
2220 if ((0xff & diffByte
) < 0xff && (diffByte
+ 1) <
2221 (rightKey
[ROW_LENGTH_SIZE
+ diffIdx
] & 0xff)) {
2222 newRowKey
= new byte[diffIdx
+ 1];
2223 System
.arraycopy(leftKey
, ROW_LENGTH_SIZE
, newRowKey
, 0, diffIdx
);
2224 newRowKey
[diffIdx
] = (byte) (diffByte
+ 1);
2226 newRowKey
= new byte[diffIdx
+ 1];
2227 System
.arraycopy(rightKey
, ROW_LENGTH_SIZE
, newRowKey
, 0, diffIdx
+ 1);
2230 return new KeyValue(newRowKey
, null, null, HConstants
.LATEST_TIMESTAMP
,
2231 Type
.Maximum
).getKey();
2235 protected Object
clone() throws CloneNotSupportedException
{
2237 return new KVComparator();
2243 * @param in Where to read bytes from. Creates a byte array to hold the KeyValue
2244 * backing bytes copied from the steam.
2245 * @return KeyValue created by deserializing from <code>in</code> OR if we find a length
2246 * of zero, we will return null which can be useful marking a stream as done.
2247 * @throws IOException
2249 public static KeyValue
create(final DataInput in
) throws IOException
{
2250 return create(in
.readInt(), in
);
2254 * Create a KeyValue reading <code>length</code> from <code>in</code>
2257 * @return Created KeyValue OR if we find a length of zero, we will return null which
2258 * can be useful marking a stream as done.
2259 * @throws IOException
2261 public static KeyValue
create(int length
, final DataInput in
) throws IOException
{
2264 if (length
== 0) return null;
2265 throw new IOException("Failed read " + length
+ " bytes, stream corrupt?");
2268 // This is how the old Writables.readFrom used to deserialize. Didn't even vint.
2269 byte [] bytes
= new byte[length
];
2270 in
.readFully(bytes
);
2271 return new KeyValue(bytes
, 0, length
);
2275 * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable.
2278 * @return Length written on stream
2279 * @throws IOException
2280 * @see #create(DataInput) for the inverse function
2282 public static long write(final KeyValue kv
, final DataOutput out
) throws IOException
{
2283 // This is how the old Writables write used to serialize KVs. Need to figure way to make it
2284 // work for all implementations.
2285 int length
= kv
.getLength();
2286 out
.writeInt(length
);
2287 out
.write(kv
.getBuffer(), kv
.getOffset(), length
);
2288 return (long) length
+ Bytes
.SIZEOF_INT
;
2292 * Write out a KeyValue in the manner in which we used to when KeyValue was a Writable but do
2293 * not require a {@link DataOutput}, just take plain {@link OutputStream}
2294 * Named <code>oswrite</code> so does not clash with {@link #write(KeyValue, DataOutput)}
2298 * @return Length written on stream
2299 * @throws IOException
2300 * @see #create(DataInput) for the inverse function
2301 * @see #write(KeyValue, DataOutput)
2302 * @see KeyValueUtil#oswrite(Cell, OutputStream, boolean)
2303 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
2304 * Instead use {@link #write(OutputStream, boolean)}
2307 public static long oswrite(final KeyValue kv
, final OutputStream out
, final boolean withTags
)
2308 throws IOException
{
2309 ByteBufferUtils
.putInt(out
, kv
.getSerializedSize(withTags
));
2310 return (long) kv
.write(out
, withTags
) + Bytes
.SIZEOF_INT
;
2314 public int write(OutputStream out
, boolean withTags
) throws IOException
{
2315 int len
= getSerializedSize(withTags
);
2316 out
.write(this.bytes
, this.offset
, len
);
2321 public int getSerializedSize(boolean withTags
) {
2325 return this.getKeyLength() + this.getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE
;
2329 public int getSerializedSize() {
2334 public void write(ByteBuffer buf
, int offset
) {
2335 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, this.bytes
, this.offset
, this.length
);
2339 * Avoids redundant comparisons for better performance.
2341 * TODO get rid of this wart
2343 public interface SamePrefixComparator
<T
> {
2345 * Compare two keys assuming that the first n bytes are the same.
2346 * @param commonPrefix How many bytes are the same.
2348 int compareIgnoringPrefix(int commonPrefix
, byte[] left
, int loffset
, int llength
,
2349 byte[] right
, int roffset
, int rlength
2354 * HeapSize implementation
2356 * We do not count the bytes in the rowCache because it should be empty for a KeyValue in the
2360 public long heapSize() {
2362 * Deep object overhead for this KV consists of two parts. The first part is the KV object
2363 * itself, while the second part is the backing byte[]. We will only count the array overhead
2364 * from the byte[] only if this is the first KV in there.
2366 return ClassSize
.align(FIXED_OVERHEAD
) +
2368 ? ClassSize
.sizeOfByteArray(length
) // count both length and object overhead
2369 : length
); // only count the number of bytes
2373 * A simple form of KeyValue that creates a keyvalue with only the key part of the byte[]
2374 * Mainly used in places where we need to compare two cells. Avoids copying of bytes
2375 * In places like block index keys, we need to compare the key byte[] with a cell.
2376 * Hence create a Keyvalue(aka Cell) that would help in comparing as two cells
2378 public static class KeyOnlyKeyValue
extends KeyValue
{
2379 private short rowLen
= -1;
2380 public KeyOnlyKeyValue() {
2383 public KeyOnlyKeyValue(byte[] b
) {
2384 this(b
, 0, b
.length
);
2387 public KeyOnlyKeyValue(byte[] b
, int offset
, int length
) {
2389 this.length
= length
;
2390 this.offset
= offset
;
2391 this.rowLen
= Bytes
.toShort(this.bytes
, this.offset
);
2394 public void set(KeyOnlyKeyValue keyOnlyKeyValue
) {
2395 this.bytes
= keyOnlyKeyValue
.bytes
;
2396 this.length
= keyOnlyKeyValue
.length
;
2397 this.offset
= keyOnlyKeyValue
.offset
;
2398 this.rowLen
= keyOnlyKeyValue
.rowLen
;
2401 public void clear() {
2409 public int getKeyOffset() {
2414 * A setter that helps to avoid object creation every time and whenever
2415 * there is a need to create new KeyOnlyKeyValue.
2420 public void setKey(byte[] key
, int offset
, int length
) {
2422 this.offset
= offset
;
2423 this.length
= length
;
2424 this.rowLen
= Bytes
.toShort(this.bytes
, this.offset
);
2428 public byte[] getKey() {
2429 int keylength
= getKeyLength();
2430 byte[] key
= new byte[keylength
];
2431 System
.arraycopy(this.bytes
, getKeyOffset(), key
, 0, keylength
);
2436 public byte[] getRowArray() {
2441 public int getRowOffset() {
2442 return getKeyOffset() + Bytes
.SIZEOF_SHORT
;
2446 public byte[] getFamilyArray() {
2451 public byte getFamilyLength() {
2452 return this.bytes
[getFamilyOffset() - 1];
2456 public int getFamilyOffset() {
2457 return this.offset
+ Bytes
.SIZEOF_SHORT
+ getRowLength() + Bytes
.SIZEOF_BYTE
;
2461 public byte[] getQualifierArray() {
2466 public int getQualifierLength() {
2467 return getQualifierLength(getRowLength(), getFamilyLength());
2471 public int getQualifierOffset() {
2472 return getFamilyOffset() + getFamilyLength();
2476 public int getKeyLength() {
2481 public short getRowLength() {
2486 public byte getTypeByte() {
2487 return this.bytes
[this.offset
+ getKeyLength() - 1];
2490 private int getQualifierLength(int rlength
, int flength
) {
2491 return getKeyLength() - (int) getKeyDataStructureSize(rlength
, flength
, 0);
2495 public long getTimestamp() {
2496 int tsOffset
= getTimestampOffset();
2497 return Bytes
.toLong(this.bytes
, tsOffset
);
2501 public int getTimestampOffset() {
2502 return getKeyOffset() + getKeyLength() - TIMESTAMP_TYPE_SIZE
;
2506 public byte[] getTagsArray() {
2507 return HConstants
.EMPTY_BYTE_ARRAY
;
2511 public int getTagsOffset() {
2516 public byte[] getValueArray() {
2517 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2521 public int getValueOffset() {
2522 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2526 public int getValueLength() {
2527 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2531 public int getTagsLength() {
2536 public String
toString() {
2537 if (this.bytes
== null || this.bytes
.length
== 0) {
2540 return keyToString(this.bytes
, this.offset
, getKeyLength()) + "/vlen=0/mvcc=0";
2544 public int hashCode() {
2545 return super.hashCode();
2549 public boolean equals(Object other
) {
2550 return super.equals(other
);
2554 public long heapSize() {
2555 return super.heapSize() + Bytes
.SIZEOF_SHORT
;
2559 public int write(OutputStream out
, boolean withTags
) throws IOException
{
2560 // This type of Cell is used only to maintain some internal states. We never allow this type
2561 // of Cell to be returned back over the RPC
2562 throw new IllegalStateException("A reader should never return this type of a Cell");
2567 public ExtendedCell
deepClone() {
2568 byte[] copy
= Bytes
.copy(this.bytes
, this.offset
, this.length
);
2569 KeyValue kv
= new KeyValue(copy
, 0, copy
.length
);
2570 kv
.setSequenceId(this.getSequenceId());