2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
;
20 import static org
.apache
.hadoop
.hbase
.HConstants
.EMPTY_BYTE_ARRAY
;
21 import static org
.apache
.hadoop
.hbase
.Tag
.TAG_LENGTH_SIZE
;
23 import java
.io
.DataOutput
;
24 import java
.io
.DataOutputStream
;
25 import java
.io
.IOException
;
26 import java
.io
.OutputStream
;
27 import java
.math
.BigDecimal
;
28 import java
.nio
.ByteBuffer
;
29 import java
.util
.ArrayList
;
30 import java
.util
.Iterator
;
31 import java
.util
.List
;
32 import java
.util
.Optional
;
33 import org
.apache
.hadoop
.hbase
.filter
.ByteArrayComparable
;
34 import org
.apache
.hadoop
.hbase
.io
.TagCompressionContext
;
35 import org
.apache
.hadoop
.hbase
.io
.util
.Dictionary
;
36 import org
.apache
.hadoop
.hbase
.io
.util
.StreamUtils
;
37 import org
.apache
.hadoop
.hbase
.util
.ByteBufferUtils
;
38 import org
.apache
.hadoop
.hbase
.util
.ByteRange
;
39 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
40 import org
.apache
.hadoop
.hbase
.util
.ClassSize
;
41 import org
.apache
.yetus
.audience
.InterfaceAudience
;
44 * Utility methods helpful slinging {@link Cell} instances. It has more powerful and
45 * rich set of APIs than those in {@link CellUtil} for internal usage.
47 @InterfaceAudience.Private
48 public final class PrivateCellUtil
{
51 * Private constructor to keep this class from being instantiated.
53 private PrivateCellUtil() {
56 /******************* ByteRange *******************************/
58 public static ByteRange
fillRowRange(Cell cell
, ByteRange range
) {
59 return range
.set(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
62 public static ByteRange
fillFamilyRange(Cell cell
, ByteRange range
) {
63 return range
.set(cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength());
66 public static ByteRange
fillQualifierRange(Cell cell
, ByteRange range
) {
67 return range
.set(cell
.getQualifierArray(), cell
.getQualifierOffset(),
68 cell
.getQualifierLength());
71 public static ByteRange
fillValueRange(Cell cell
, ByteRange range
) {
72 return range
.set(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
75 public static ByteRange
fillTagRange(Cell cell
, ByteRange range
) {
76 return range
.set(cell
.getTagsArray(), cell
.getTagsOffset(), cell
.getTagsLength());
79 /********************* misc *************************************/
81 public static byte getRowByte(Cell cell
, int index
) {
82 if (cell
instanceof ByteBufferExtendedCell
) {
83 return ((ByteBufferExtendedCell
) cell
).getRowByteBuffer()
84 .get(((ByteBufferExtendedCell
) cell
).getRowPosition() + index
);
86 return cell
.getRowArray()[cell
.getRowOffset() + index
];
89 public static byte getQualifierByte(Cell cell
, int index
) {
90 if (cell
instanceof ByteBufferExtendedCell
) {
91 return ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer()
92 .get(((ByteBufferExtendedCell
) cell
).getQualifierPosition() + index
);
94 return cell
.getQualifierArray()[cell
.getQualifierOffset() + index
];
97 public static ByteBuffer
getValueBufferShallowCopy(Cell cell
) {
99 ByteBuffer
.wrap(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
104 * @return A new cell which is having the extra tags also added to it.
106 public static Cell
createCell(Cell cell
, List
<Tag
> tags
) {
107 return createCell(cell
, TagUtil
.fromList(tags
));
111 * @return A new cell which is having the extra tags also added to it.
113 public static Cell
createCell(Cell cell
, byte[] tags
) {
114 if (cell
instanceof ByteBufferExtendedCell
) {
115 return new TagRewriteByteBufferExtendedCell((ByteBufferExtendedCell
) cell
, tags
);
117 return new TagRewriteCell(cell
, tags
);
120 public static Cell
createCell(Cell cell
, byte[] value
, byte[] tags
) {
121 if (cell
instanceof ByteBufferExtendedCell
) {
122 return new ValueAndTagRewriteByteBufferExtendedCell((ByteBufferExtendedCell
) cell
,
125 return new ValueAndTagRewriteCell(cell
, value
, tags
);
129 * This can be used when a Cell has to change with addition/removal of one or more tags. This is
130 * an efficient way to do so in which only the tags bytes part need to recreated and copied. All
131 * other parts, refer to the original Cell.
133 static class TagRewriteCell
implements ExtendedCell
{
135 protected byte[] tags
;
136 private static final int HEAP_SIZE_OVERHEAD
= ClassSize
.OBJECT
+ 2 * ClassSize
.REFERENCE
;
139 * @param cell The original Cell which it rewrites
140 * @param tags the tags bytes. The array suppose to contain the tags bytes alone.
142 public TagRewriteCell(Cell cell
, byte[] tags
) {
143 assert cell
instanceof ExtendedCell
;
147 // tag offset will be treated as 0 and length this.tags.length
148 if (this.cell
instanceof TagRewriteCell
) {
149 // Cleaning the ref so that the byte[] can be GCed
150 ((TagRewriteCell
) this.cell
).tags
= null;
155 public byte[] getRowArray() {
156 return cell
.getRowArray();
160 public int getRowOffset() {
161 return cell
.getRowOffset();
165 public short getRowLength() {
166 return cell
.getRowLength();
170 public byte[] getFamilyArray() {
171 return cell
.getFamilyArray();
175 public int getFamilyOffset() {
176 return cell
.getFamilyOffset();
180 public byte getFamilyLength() {
181 return cell
.getFamilyLength();
185 public byte[] getQualifierArray() {
186 return cell
.getQualifierArray();
190 public int getQualifierOffset() {
191 return cell
.getQualifierOffset();
195 public int getQualifierLength() {
196 return cell
.getQualifierLength();
200 public long getTimestamp() {
201 return cell
.getTimestamp();
205 public byte getTypeByte() {
206 return cell
.getTypeByte();
210 public long getSequenceId() {
211 return cell
.getSequenceId();
215 public byte[] getValueArray() {
216 return cell
.getValueArray();
220 public int getValueOffset() {
221 return cell
.getValueOffset();
225 public int getValueLength() {
226 return cell
.getValueLength();
230 public byte[] getTagsArray() {
235 public int getTagsOffset() {
240 public int getTagsLength() {
241 if (null == this.tags
) {
242 // Nulled out tags array optimization in constructor
245 return this.tags
.length
;
249 public long heapSize() {
250 long sum
= HEAP_SIZE_OVERHEAD
+ cell
.heapSize();
251 if (this.tags
!= null) {
252 sum
+= ClassSize
.sizeOf(this.tags
);
258 public void setTimestamp(long ts
) throws IOException
{
259 // The incoming cell is supposed to be ExtendedCell type.
260 PrivateCellUtil
.setTimestamp(cell
, ts
);
264 public void setTimestamp(byte[] ts
) throws IOException
{
265 // The incoming cell is supposed to be ExtendedCell type.
266 PrivateCellUtil
.setTimestamp(cell
, ts
);
270 public void setSequenceId(long seqId
) throws IOException
{
271 // The incoming cell is supposed to be ExtendedCell type.
272 PrivateCellUtil
.setSequenceId(cell
, seqId
);
276 public int write(OutputStream out
, boolean withTags
) throws IOException
{
277 int len
= ((ExtendedCell
) this.cell
).write(out
, false);
278 if (withTags
&& this.tags
!= null) {
279 // Write the tagsLength 2 bytes
280 out
.write((byte) (0xff & (this.tags
.length
>> 8)));
281 out
.write((byte) (0xff & this.tags
.length
));
282 out
.write(this.tags
);
283 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
289 public int getSerializedSize(boolean withTags
) {
290 int len
= ((ExtendedCell
) this.cell
).getSerializedSize(false);
291 if (withTags
&& this.tags
!= null) {
292 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
298 public void write(ByteBuffer buf
, int offset
) {
299 offset
= KeyValueUtil
.appendTo(this.cell
, buf
, offset
, false);
300 int tagsLen
= this.tags
== null ?
0 : this.tags
.length
;
302 offset
= ByteBufferUtils
.putAsShort(buf
, offset
, tagsLen
);
303 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, this.tags
, 0, tagsLen
);
308 public ExtendedCell
deepClone() {
309 Cell clonedBaseCell
= ((ExtendedCell
) this.cell
).deepClone();
310 return new TagRewriteCell(clonedBaseCell
, this.tags
);
314 static class TagRewriteByteBufferExtendedCell
extends ByteBufferExtendedCell
{
316 protected ByteBufferExtendedCell cell
;
317 protected byte[] tags
;
318 private static final int HEAP_SIZE_OVERHEAD
= ClassSize
.OBJECT
+ 2 * ClassSize
.REFERENCE
;
321 * @param cell The original ByteBufferExtendedCell which it rewrites
322 * @param tags the tags bytes. The array suppose to contain the tags bytes alone.
324 public TagRewriteByteBufferExtendedCell(ByteBufferExtendedCell cell
, byte[] tags
) {
328 // tag offset will be treated as 0 and length this.tags.length
329 if (this.cell
instanceof TagRewriteByteBufferExtendedCell
) {
330 // Cleaning the ref so that the byte[] can be GCed
331 ((TagRewriteByteBufferExtendedCell
) this.cell
).tags
= null;
336 public byte[] getRowArray() {
337 return this.cell
.getRowArray();
341 public int getRowOffset() {
342 return this.cell
.getRowOffset();
346 public short getRowLength() {
347 return this.cell
.getRowLength();
351 public byte[] getFamilyArray() {
352 return this.cell
.getFamilyArray();
356 public int getFamilyOffset() {
357 return this.cell
.getFamilyOffset();
361 public byte getFamilyLength() {
362 return this.cell
.getFamilyLength();
366 public byte[] getQualifierArray() {
367 return this.cell
.getQualifierArray();
371 public int getQualifierOffset() {
372 return this.cell
.getQualifierOffset();
376 public int getQualifierLength() {
377 return this.cell
.getQualifierLength();
381 public long getTimestamp() {
382 return this.cell
.getTimestamp();
386 public byte getTypeByte() {
387 return this.cell
.getTypeByte();
391 public long getSequenceId() {
392 return this.cell
.getSequenceId();
396 public byte[] getValueArray() {
397 return this.cell
.getValueArray();
401 public int getValueOffset() {
402 return this.cell
.getValueOffset();
406 public int getValueLength() {
407 return this.cell
.getValueLength();
411 public byte[] getTagsArray() {
416 public int getTagsOffset() {
421 public int getTagsLength() {
422 if (null == this.tags
) {
423 // Nulled out tags array optimization in constructor
426 return this.tags
.length
;
430 public void setSequenceId(long seqId
) throws IOException
{
431 PrivateCellUtil
.setSequenceId(this.cell
, seqId
);
435 public void setTimestamp(long ts
) throws IOException
{
436 PrivateCellUtil
.setTimestamp(this.cell
, ts
);
440 public void setTimestamp(byte[] ts
) throws IOException
{
441 PrivateCellUtil
.setTimestamp(this.cell
, ts
);
445 public long heapSize() {
446 long sum
= HEAP_SIZE_OVERHEAD
+ cell
.heapSize();
447 // this.tags is on heap byte[]
448 if (this.tags
!= null) {
449 sum
+= ClassSize
.sizeOf(this.tags
);
455 public int write(OutputStream out
, boolean withTags
) throws IOException
{
456 int len
= ((ExtendedCell
) this.cell
).write(out
, false);
457 if (withTags
&& this.tags
!= null) {
458 // Write the tagsLength 2 bytes
459 out
.write((byte) (0xff & (this.tags
.length
>> 8)));
460 out
.write((byte) (0xff & this.tags
.length
));
461 out
.write(this.tags
);
462 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
468 public int getSerializedSize(boolean withTags
) {
469 int len
= ((ExtendedCell
) this.cell
).getSerializedSize(false);
470 if (withTags
&& this.tags
!= null) {
471 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
477 public void write(ByteBuffer buf
, int offset
) {
478 offset
= KeyValueUtil
.appendTo(this.cell
, buf
, offset
, false);
479 int tagsLen
= this.tags
== null ?
0 : this.tags
.length
;
481 offset
= ByteBufferUtils
.putAsShort(buf
, offset
, tagsLen
);
482 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, this.tags
, 0, tagsLen
);
487 public ExtendedCell
deepClone() {
488 Cell clonedBaseCell
= ((ExtendedCell
) this.cell
).deepClone();
489 if (clonedBaseCell
instanceof ByteBufferExtendedCell
) {
490 return new TagRewriteByteBufferExtendedCell((ByteBufferExtendedCell
) clonedBaseCell
,
493 return new TagRewriteCell(clonedBaseCell
, this.tags
);
497 public ByteBuffer
getRowByteBuffer() {
498 return this.cell
.getRowByteBuffer();
502 public int getRowPosition() {
503 return this.cell
.getRowPosition();
507 public ByteBuffer
getFamilyByteBuffer() {
508 return this.cell
.getFamilyByteBuffer();
512 public int getFamilyPosition() {
513 return this.cell
.getFamilyPosition();
517 public ByteBuffer
getQualifierByteBuffer() {
518 return this.cell
.getQualifierByteBuffer();
522 public int getQualifierPosition() {
523 return this.cell
.getQualifierPosition();
527 public ByteBuffer
getValueByteBuffer() {
528 return this.cell
.getValueByteBuffer();
532 public int getValuePosition() {
533 return this.cell
.getValuePosition();
537 public ByteBuffer
getTagsByteBuffer() {
538 return this.tags
== null ? HConstants
.EMPTY_BYTE_BUFFER
: ByteBuffer
.wrap(this.tags
);
542 public int getTagsPosition() {
547 static class ValueAndTagRewriteCell
extends TagRewriteCell
{
549 protected byte[] value
;
551 public ValueAndTagRewriteCell(Cell cell
, byte[] value
, byte[] tags
) {
557 public byte[] getValueArray() {
562 public int getValueOffset() {
567 public int getValueLength() {
568 return this.value
== null ?
0 : this.value
.length
;
572 public long heapSize() {
573 long sum
= ClassSize
.REFERENCE
+ super.heapSize();
574 if (this.value
!= null) {
575 sum
+= ClassSize
.sizeOf(this.value
);
581 public int write(OutputStream out
, boolean withTags
) throws IOException
{
582 return write(out
, withTags
, this.cell
, this.value
, this.tags
);
586 * Made into a static method so as to reuse the logic within
587 * ValueAndTagRewriteByteBufferExtendedCell
589 static int write(OutputStream out
, boolean withTags
, Cell cell
, byte[] value
, byte[] tags
)
591 int valLen
= value
== null ?
0 : value
.length
;
592 ByteBufferUtils
.putInt(out
, KeyValueUtil
.keyLength(cell
));// Key length
593 ByteBufferUtils
.putInt(out
, valLen
);// Value length
594 int len
= 2 * Bytes
.SIZEOF_INT
;
595 len
+= writeFlatKey(cell
, out
);// Key
597 out
.write(value
);// Value
600 if (withTags
&& tags
!= null) {
601 // Write the tagsLength 2 bytes
602 out
.write((byte) (0xff & (tags
.length
>> 8)));
603 out
.write((byte) (0xff & tags
.length
));
605 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ tags
.length
;
611 public int getSerializedSize(boolean withTags
) {
612 return super.getSerializedSize(withTags
) - this.cell
.getValueLength() + this.value
.length
;
616 public void write(ByteBuffer buf
, int offset
) {
617 write(buf
, offset
, this.cell
, this.value
, this.tags
);
621 * Made into a static method so as to reuse the logic
622 * within ValueAndTagRewriteByteBufferExtendedCell
624 static void write(ByteBuffer buf
, int offset
, Cell cell
, byte[] value
, byte[] tags
) {
625 offset
= ByteBufferUtils
.putInt(buf
, offset
, KeyValueUtil
.keyLength(cell
));// Key length
626 offset
= ByteBufferUtils
.putInt(buf
, offset
, value
.length
);// Value length
627 offset
= KeyValueUtil
.appendKeyTo(cell
, buf
, offset
);
628 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, value
, 0, value
.length
);
629 offset
+= value
.length
;
630 int tagsLen
= tags
== null ?
0 : tags
.length
;
632 offset
= ByteBufferUtils
.putAsShort(buf
, offset
, tagsLen
);
633 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, tags
, 0, tagsLen
);
638 public ExtendedCell
deepClone() {
639 Cell clonedBaseCell
= ((ExtendedCell
) this.cell
).deepClone();
640 return new ValueAndTagRewriteCell(clonedBaseCell
, this.value
, this.tags
);
644 static class ValueAndTagRewriteByteBufferExtendedCell
extends TagRewriteByteBufferExtendedCell
{
646 protected byte[] value
;
648 public ValueAndTagRewriteByteBufferExtendedCell(ByteBufferExtendedCell cell
,
649 byte[] value
, byte[] tags
) {
655 public byte[] getValueArray() {
660 public int getValueOffset() {
665 public int getValueLength() {
666 return this.value
== null ?
0 : this.value
.length
;
670 public ByteBuffer
getValueByteBuffer() {
671 return ByteBuffer
.wrap(this.value
);
675 public int getValuePosition() {
680 public long heapSize() {
681 long sum
= ClassSize
.REFERENCE
+ super.heapSize();
682 if (this.value
!= null) {
683 sum
+= ClassSize
.sizeOf(this.value
);
689 public int write(OutputStream out
, boolean withTags
) throws IOException
{
690 return ValueAndTagRewriteCell
.write(out
, withTags
, this.cell
, this.value
, this.tags
);
694 public int getSerializedSize(boolean withTags
) {
695 return super.getSerializedSize(withTags
) - this.cell
.getValueLength() + this.value
.length
;
699 public void write(ByteBuffer buf
, int offset
) {
700 ValueAndTagRewriteCell
.write(buf
, offset
, this.cell
, this.value
, this.tags
);
704 public ExtendedCell
deepClone() {
705 Cell clonedBaseCell
= this.cell
.deepClone();
706 if (clonedBaseCell
instanceof ByteBufferExtendedCell
) {
707 return new ValueAndTagRewriteByteBufferExtendedCell(
708 (ByteBufferExtendedCell
) clonedBaseCell
, this.value
, this.tags
);
710 return new ValueAndTagRewriteCell(clonedBaseCell
, this.value
, this.tags
);
714 public static boolean matchingRows(final Cell left
, final byte[] buf
, final int offset
,
716 if (left
instanceof ByteBufferExtendedCell
) {
717 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getRowByteBuffer(),
718 ((ByteBufferExtendedCell
) left
).getRowPosition(), left
.getRowLength(),
719 buf
, offset
, length
);
721 return Bytes
.equals(left
.getRowArray(), left
.getRowOffset(), left
.getRowLength(), buf
, offset
,
725 public static boolean matchingFamily(final Cell left
, final byte[] buf
, final int offset
,
727 if (left
instanceof ByteBufferExtendedCell
) {
728 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getFamilyByteBuffer(),
729 ((ByteBufferExtendedCell
) left
).getFamilyPosition(), left
.getFamilyLength(),
730 buf
, offset
, length
);
732 return Bytes
.equals(left
.getFamilyArray(), left
.getFamilyOffset(), left
.getFamilyLength(), buf
,
737 * Finds if the qualifier part of the cell and the KV serialized byte[] are equal
738 * @param left the cell with which we need to match the qualifier
739 * @param buf the serialized keyvalue format byte[]
740 * @param offset the offset of the qualifier in the byte[]
741 * @param length the length of the qualifier in the byte[]
742 * @return true if the qualifier matches, false otherwise
744 public static boolean matchingQualifier(final Cell left
, final byte[] buf
, final int offset
,
747 return left
.getQualifierLength() == 0;
749 if (left
instanceof ByteBufferExtendedCell
) {
750 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getQualifierByteBuffer(),
751 ((ByteBufferExtendedCell
) left
).getQualifierPosition(), left
.getQualifierLength(),
752 buf
, offset
, length
);
754 return Bytes
.equals(left
.getQualifierArray(), left
.getQualifierOffset(),
755 left
.getQualifierLength(), buf
, offset
, length
);
759 * Finds if the start of the qualifier part of the Cell matches <code>buf</code>
760 * @param left the cell with which we need to match the qualifier
761 * @param startsWith the serialized keyvalue format byte[]
762 * @return true if the qualifier have same staring characters, false otherwise
764 public static boolean qualifierStartsWith(final Cell left
, final byte[] startsWith
) {
765 if (startsWith
== null || startsWith
.length
== 0) {
766 throw new IllegalArgumentException("Cannot pass an empty startsWith");
768 if (left
.getQualifierLength() < startsWith
.length
) {
771 if (left
instanceof ByteBufferExtendedCell
) {
772 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getQualifierByteBuffer(),
773 ((ByteBufferExtendedCell
) left
).getQualifierPosition(), startsWith
.length
,
774 startsWith
, 0, startsWith
.length
);
776 return Bytes
.equals(left
.getQualifierArray(), left
.getQualifierOffset(),
777 startsWith
.length
, startsWith
, 0, startsWith
.length
);
780 public static boolean matchingColumn(final Cell left
, final byte[] fam
, final int foffset
,
781 final int flength
, final byte[] qual
, final int qoffset
, final int qlength
) {
782 if (!matchingFamily(left
, fam
, foffset
, flength
)) {
785 return matchingQualifier(left
, qual
, qoffset
, qlength
);
788 public static boolean matchingValue(final Cell left
, final Cell right
, int lvlength
,
790 if (left
instanceof ByteBufferExtendedCell
&& right
instanceof ByteBufferExtendedCell
) {
791 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getValueByteBuffer(),
792 ((ByteBufferExtendedCell
) left
).getValuePosition(), lvlength
,
793 ((ByteBufferExtendedCell
) right
).getValueByteBuffer(),
794 ((ByteBufferExtendedCell
) right
).getValuePosition(), rvlength
);
796 if (left
instanceof ByteBufferExtendedCell
) {
797 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getValueByteBuffer(),
798 ((ByteBufferExtendedCell
) left
).getValuePosition(), lvlength
, right
.getValueArray(),
799 right
.getValueOffset(), rvlength
);
801 if (right
instanceof ByteBufferExtendedCell
) {
802 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) right
).getValueByteBuffer(),
803 ((ByteBufferExtendedCell
) right
).getValuePosition(), rvlength
, left
.getValueArray(),
804 left
.getValueOffset(), lvlength
);
807 .equals(left
.getValueArray(), left
.getValueOffset(), lvlength
, right
.getValueArray(),
808 right
.getValueOffset(), rvlength
);
811 public static boolean matchingType(Cell a
, Cell b
) {
812 return a
.getTypeByte() == b
.getTypeByte();
815 public static boolean matchingTags(final Cell left
, final Cell right
, int llength
,
817 if (left
instanceof ByteBufferExtendedCell
&& right
instanceof ByteBufferExtendedCell
) {
818 ByteBufferExtendedCell leftBBCell
= (ByteBufferExtendedCell
) left
;
819 ByteBufferExtendedCell rightBBCell
= (ByteBufferExtendedCell
) right
;
820 return ByteBufferUtils
.equals(
821 leftBBCell
.getTagsByteBuffer(), leftBBCell
.getTagsPosition(), llength
,
822 rightBBCell
.getTagsByteBuffer(),rightBBCell
.getTagsPosition(), rlength
);
824 if (left
instanceof ByteBufferExtendedCell
) {
825 ByteBufferExtendedCell leftBBCell
= (ByteBufferExtendedCell
) left
;
826 return ByteBufferUtils
.equals(
827 leftBBCell
.getTagsByteBuffer(), leftBBCell
.getTagsPosition(), llength
,
828 right
.getTagsArray(), right
.getTagsOffset(), rlength
);
830 if (right
instanceof ByteBufferExtendedCell
) {
831 ByteBufferExtendedCell rightBBCell
= (ByteBufferExtendedCell
) right
;
832 return ByteBufferUtils
.equals(
833 rightBBCell
.getTagsByteBuffer(), rightBBCell
.getTagsPosition(), rlength
,
834 left
.getTagsArray(), left
.getTagsOffset(), llength
);
836 return Bytes
.equals(left
.getTagsArray(), left
.getTagsOffset(), llength
,
837 right
.getTagsArray(), right
.getTagsOffset(), rlength
);
841 * @return True if a delete type, a {@link KeyValue.Type#Delete} or a {KeyValue.Type#DeleteFamily}
842 * or a {@link KeyValue.Type#DeleteColumn} KeyValue type.
844 public static boolean isDelete(final byte type
) {
845 return KeyValue
.Type
.Delete
.getCode() <= type
&& type
<= KeyValue
.Type
.DeleteFamily
.getCode();
849 * @return True if this cell is a {@link KeyValue.Type#Delete} type.
851 public static boolean isDeleteType(Cell cell
) {
852 return cell
.getTypeByte() == KeyValue
.Type
.Delete
.getCode();
855 public static boolean isDeleteFamily(final Cell cell
) {
856 return cell
.getTypeByte() == KeyValue
.Type
.DeleteFamily
.getCode();
859 public static boolean isDeleteFamilyVersion(final Cell cell
) {
860 return cell
.getTypeByte() == KeyValue
.Type
.DeleteFamilyVersion
.getCode();
863 public static boolean isDeleteColumns(final Cell cell
) {
864 return cell
.getTypeByte() == KeyValue
.Type
.DeleteColumn
.getCode();
867 public static boolean isDeleteColumnVersion(final Cell cell
) {
868 return cell
.getTypeByte() == KeyValue
.Type
.Delete
.getCode();
872 * @return True if this cell is a delete family or column type.
874 public static boolean isDeleteColumnOrFamily(Cell cell
) {
875 int t
= cell
.getTypeByte();
876 return t
== KeyValue
.Type
.DeleteColumn
.getCode() || t
== KeyValue
.Type
.DeleteFamily
.getCode();
879 public static byte[] cloneTags(Cell cell
) {
880 byte[] output
= new byte[cell
.getTagsLength()];
881 copyTagsTo(cell
, output
, 0);
886 * Copies the tags info into the tag portion of the cell
889 * @param destinationOffset
890 * @return position after tags
892 public static int copyTagsTo(Cell cell
, byte[] destination
, int destinationOffset
) {
893 int tlen
= cell
.getTagsLength();
894 if (cell
instanceof ByteBufferExtendedCell
) {
896 .copyFromBufferToArray(destination
, ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
897 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), destinationOffset
, tlen
);
900 .arraycopy(cell
.getTagsArray(), cell
.getTagsOffset(), destination
, destinationOffset
, tlen
);
902 return destinationOffset
+ tlen
;
906 * Copies the tags info into the tag portion of the cell
909 * @param destinationOffset
910 * @return the position after tags
912 public static int copyTagsTo(Cell cell
, ByteBuffer destination
, int destinationOffset
) {
913 int tlen
= cell
.getTagsLength();
914 if (cell
instanceof ByteBufferExtendedCell
) {
915 ByteBufferUtils
.copyFromBufferToBuffer(((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
916 destination
, ((ByteBufferExtendedCell
) cell
).getTagsPosition(), destinationOffset
, tlen
);
918 ByteBufferUtils
.copyFromArrayToBuffer(destination
, destinationOffset
, cell
.getTagsArray(),
919 cell
.getTagsOffset(), tlen
);
921 return destinationOffset
+ tlen
;
925 * @param cell The Cell
926 * @return Tags in the given Cell as a List
928 public static List
<Tag
> getTags(Cell cell
) {
929 List
<Tag
> tags
= new ArrayList
<>();
930 Iterator
<Tag
> tagsItr
= tagsIterator(cell
);
931 while (tagsItr
.hasNext()) {
932 tags
.add(tagsItr
.next());
938 * Retrieve Cell's first tag, matching the passed in type
939 * @param cell The Cell
940 * @param type Type of the Tag to retrieve
941 * @return Optional, empty if there is no tag of the passed in tag type
943 public static Optional
<Tag
> getTag(Cell cell
, byte type
) {
944 boolean bufferBacked
= cell
instanceof ByteBufferExtendedCell
;
945 int length
= cell
.getTagsLength();
947 bufferBacked ?
((ByteBufferExtendedCell
) cell
).getTagsPosition() : cell
.getTagsOffset();
949 while (pos
< offset
+ length
) {
952 ByteBuffer tagsBuffer
= ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer();
953 tagLen
= ByteBufferUtils
.readAsInt(tagsBuffer
, pos
, TAG_LENGTH_SIZE
);
954 if (ByteBufferUtils
.toByte(tagsBuffer
, pos
+ TAG_LENGTH_SIZE
) == type
) {
955 return Optional
.of(new ByteBufferTag(tagsBuffer
, pos
, tagLen
+ TAG_LENGTH_SIZE
));
958 tagLen
= Bytes
.readAsInt(cell
.getTagsArray(), pos
, TAG_LENGTH_SIZE
);
959 if (cell
.getTagsArray()[pos
+ TAG_LENGTH_SIZE
] == type
) {
961 .of(new ArrayBackedTag(cell
.getTagsArray(), pos
, tagLen
+ TAG_LENGTH_SIZE
));
964 pos
+= TAG_LENGTH_SIZE
+ tagLen
;
966 return Optional
.empty();
970 * Util method to iterate through the tags in the given cell.
971 * @param cell The Cell over which tags iterator is needed.
972 * @return iterator for the tags
974 public static Iterator
<Tag
> tagsIterator(final Cell cell
) {
975 final int tagsLength
= cell
.getTagsLength();
976 // Save an object allocation where we can
977 if (tagsLength
== 0) {
978 return TagUtil
.EMPTY_TAGS_ITR
;
980 if (cell
instanceof ByteBufferExtendedCell
) {
981 return tagsIterator(((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
982 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), tagsLength
);
985 return new Iterator
<Tag
>() {
986 private int offset
= cell
.getTagsOffset();
987 private int pos
= offset
;
988 private int endOffset
= offset
+ cell
.getTagsLength() - 1;
991 public boolean hasNext() {
992 return this.pos
< endOffset
;
998 byte[] tags
= cell
.getTagsArray();
999 int curTagLen
= Bytes
.readAsInt(tags
, this.pos
, Tag
.TAG_LENGTH_SIZE
);
1000 Tag tag
= new ArrayBackedTag(tags
, pos
, curTagLen
+ TAG_LENGTH_SIZE
);
1001 this.pos
+= Bytes
.SIZEOF_SHORT
+ curTagLen
;
1008 public void remove() {
1009 throw new UnsupportedOperationException();
1014 public static Iterator
<Tag
> tagsIterator(final ByteBuffer tags
, final int offset
,
1016 return new Iterator
<Tag
>() {
1017 private int pos
= offset
;
1018 private int endOffset
= offset
+ length
- 1;
1021 public boolean hasNext() {
1022 return this.pos
< endOffset
;
1028 int curTagLen
= ByteBufferUtils
.readAsInt(tags
, this.pos
, Tag
.TAG_LENGTH_SIZE
);
1029 Tag tag
= new ByteBufferTag(tags
, pos
, curTagLen
+ Tag
.TAG_LENGTH_SIZE
);
1030 this.pos
+= Bytes
.SIZEOF_SHORT
+ curTagLen
;
1037 public void remove() {
1038 throw new UnsupportedOperationException();
1044 * Returns true if the first range start1...end1 overlaps with the second range start2...end2,
1045 * assuming the byte arrays represent row keys
1047 public static boolean overlappingKeys(final byte[] start1
, final byte[] end1
, final byte[] start2
,
1048 final byte[] end2
) {
1049 return (end2
.length
== 0 || start1
.length
== 0 || Bytes
.compareTo(start1
, end2
) < 0)
1050 && (end1
.length
== 0 || start2
.length
== 0 || Bytes
.compareTo(start2
, end1
) < 0);
1054 * Write rowkey excluding the common part.
1057 * @param commonPrefix
1059 * @throws IOException
1061 public static void writeRowKeyExcludingCommon(Cell cell
, short rLen
, int commonPrefix
,
1062 DataOutputStream out
) throws IOException
{
1063 if (commonPrefix
== 0) {
1064 out
.writeShort(rLen
);
1065 } else if (commonPrefix
== 1) {
1066 out
.writeByte((byte) rLen
);
1069 commonPrefix
-= KeyValue
.ROW_LENGTH_SIZE
;
1071 if (rLen
> commonPrefix
) {
1072 writeRowSkippingBytes(out
, cell
, rLen
, commonPrefix
);
1077 * Writes the row from the given cell to the output stream excluding the common prefix
1078 * @param out The dataoutputstream to which the data has to be written
1079 * @param cell The cell whose contents has to be written
1080 * @param rlength the row length
1081 * @throws IOException
1083 public static void writeRowSkippingBytes(DataOutputStream out
, Cell cell
, short rlength
,
1084 int commonPrefix
) throws IOException
{
1085 if (cell
instanceof ByteBufferExtendedCell
) {
1087 .copyBufferToStream((DataOutput
) out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
1088 ((ByteBufferExtendedCell
) cell
).getRowPosition() + commonPrefix
,
1089 rlength
- commonPrefix
);
1091 out
.write(cell
.getRowArray(), cell
.getRowOffset() + commonPrefix
, rlength
- commonPrefix
);
1096 * Find length of common prefix in keys of the cells, considering key as byte[] if serialized in
1097 * {@link KeyValue}. The key format is <2 bytes rk len><rk><1 byte cf
1098 * len><cf><qualifier><8 bytes timestamp><1 byte type>
1099 * @param c1 the cell
1100 * @param c2 the cell
1101 * @param bypassFamilyCheck when true assume the family bytes same in both cells. Pass it as true
1102 * when dealing with Cells in same CF so as to avoid some checks
1103 * @param withTsType when true check timestamp and type bytes also.
1104 * @return length of common prefix
1106 public static int findCommonPrefixInFlatKey(Cell c1
, Cell c2
, boolean bypassFamilyCheck
,
1107 boolean withTsType
) {
1108 // Compare the 2 bytes in RK length part
1109 short rLen1
= c1
.getRowLength();
1110 short rLen2
= c2
.getRowLength();
1111 int commonPrefix
= KeyValue
.ROW_LENGTH_SIZE
;
1112 if (rLen1
!= rLen2
) {
1113 // early out when the RK length itself is not matching
1114 return ByteBufferUtils
1115 .findCommonPrefix(Bytes
.toBytes(rLen1
), 0, KeyValue
.ROW_LENGTH_SIZE
, Bytes
.toBytes(rLen2
),
1116 0, KeyValue
.ROW_LENGTH_SIZE
);
1119 int rkCommonPrefix
= 0;
1120 if (c1
instanceof ByteBufferExtendedCell
&& c2
instanceof ByteBufferExtendedCell
) {
1121 rkCommonPrefix
= ByteBufferUtils
1122 .findCommonPrefix(((ByteBufferExtendedCell
) c1
).getRowByteBuffer(),
1123 ((ByteBufferExtendedCell
) c1
).getRowPosition(), rLen1
,
1124 ((ByteBufferExtendedCell
) c2
).getRowByteBuffer(),
1125 ((ByteBufferExtendedCell
) c2
).getRowPosition(), rLen2
);
1127 // There cannot be a case where one cell is BBCell and other is KeyValue. This flow comes
1129 // in flush or compactions. In flushes both cells are KV and in case of compaction it will be
1132 rkCommonPrefix
= ByteBufferUtils
1133 .findCommonPrefix(c1
.getRowArray(), c1
.getRowOffset(), rLen1
, c2
.getRowArray(),
1134 c2
.getRowOffset(), rLen2
);
1136 commonPrefix
+= rkCommonPrefix
;
1137 if (rkCommonPrefix
!= rLen1
) {
1138 // Early out when RK is not fully matching.
1139 return commonPrefix
;
1141 // Compare 1 byte CF length part
1142 byte fLen1
= c1
.getFamilyLength();
1143 if (bypassFamilyCheck
) {
1144 // This flag will be true when caller is sure that the family will be same for both the cells
1145 // Just make commonPrefix to increment by the family part
1146 commonPrefix
+= KeyValue
.FAMILY_LENGTH_SIZE
+ fLen1
;
1148 byte fLen2
= c2
.getFamilyLength();
1149 if (fLen1
!= fLen2
) {
1150 // early out when the CF length itself is not matching
1151 return commonPrefix
;
1153 // CF lengths are same so there is one more byte common in key part
1154 commonPrefix
+= KeyValue
.FAMILY_LENGTH_SIZE
;
1155 // Compare the CF names
1157 if (c1
instanceof ByteBufferExtendedCell
&& c2
instanceof ByteBufferExtendedCell
) {
1158 fCommonPrefix
= ByteBufferUtils
1159 .findCommonPrefix(((ByteBufferExtendedCell
) c1
).getFamilyByteBuffer(),
1160 ((ByteBufferExtendedCell
) c1
).getFamilyPosition(), fLen1
,
1161 ((ByteBufferExtendedCell
) c2
).getFamilyByteBuffer(),
1162 ((ByteBufferExtendedCell
) c2
).getFamilyPosition(), fLen2
);
1164 fCommonPrefix
= ByteBufferUtils
1165 .findCommonPrefix(c1
.getFamilyArray(), c1
.getFamilyOffset(), fLen1
, c2
.getFamilyArray(),
1166 c2
.getFamilyOffset(), fLen2
);
1168 commonPrefix
+= fCommonPrefix
;
1169 if (fCommonPrefix
!= fLen1
) {
1170 return commonPrefix
;
1173 // Compare the Qualifiers
1174 int qLen1
= c1
.getQualifierLength();
1175 int qLen2
= c2
.getQualifierLength();
1177 if (c1
instanceof ByteBufferExtendedCell
&& c2
instanceof ByteBufferExtendedCell
) {
1178 qCommon
= ByteBufferUtils
1179 .findCommonPrefix(((ByteBufferExtendedCell
) c1
).getQualifierByteBuffer(),
1180 ((ByteBufferExtendedCell
) c1
).getQualifierPosition(), qLen1
,
1181 ((ByteBufferExtendedCell
) c2
).getQualifierByteBuffer(),
1182 ((ByteBufferExtendedCell
) c2
).getQualifierPosition(), qLen2
);
1184 qCommon
= ByteBufferUtils
1185 .findCommonPrefix(c1
.getQualifierArray(), c1
.getQualifierOffset(), qLen1
,
1186 c2
.getQualifierArray(), c2
.getQualifierOffset(), qLen2
);
1188 commonPrefix
+= qCommon
;
1189 if (!withTsType
|| Math
.max(qLen1
, qLen2
) != qCommon
) {
1190 return commonPrefix
;
1192 // Compare the timestamp parts
1193 int tsCommonPrefix
= ByteBufferUtils
1194 .findCommonPrefix(Bytes
.toBytes(c1
.getTimestamp()), 0, KeyValue
.TIMESTAMP_SIZE
,
1195 Bytes
.toBytes(c2
.getTimestamp()), 0, KeyValue
.TIMESTAMP_SIZE
);
1196 commonPrefix
+= tsCommonPrefix
;
1197 if (tsCommonPrefix
!= KeyValue
.TIMESTAMP_SIZE
) {
1198 return commonPrefix
;
1201 if (c1
.getTypeByte() == c2
.getTypeByte()) {
1202 commonPrefix
+= KeyValue
.TYPE_SIZE
;
1204 return commonPrefix
;
1208 * Used to compare two cells based on the column hint provided. This is specifically used when we
1209 * need to optimize the seeks based on the next indexed key. This is an advanced usage API
1210 * specifically needed for some optimizations.
1211 * @param nextIndexedCell the next indexed cell
1212 * @param currentCell the cell to be compared
1213 * @param foff the family offset of the currentCell
1214 * @param flen the family length of the currentCell
1215 * @param colHint the column hint provided - could be null
1216 * @param coff the offset of the column hint if provided, if not offset of the currentCell's
1218 * @param clen the length of the column hint if provided, if not length of the currentCell's
1220 * @param ts the timestamp to be seeked
1221 * @param type the type to be seeked
1222 * @return an int based on the given column hint TODO : To be moved out of here because this is a
1223 * special API used in scan optimization.
1225 // compare a key against row/fam/qual/ts/type
1226 public static final int compareKeyBasedOnColHint(CellComparator comparator
, Cell nextIndexedCell
,
1227 Cell currentCell
, int foff
, int flen
, byte[] colHint
, int coff
, int clen
, long ts
,
1229 int compare
= comparator
.compareRows(nextIndexedCell
, currentCell
);
1233 // If the column is not specified, the "minimum" key type appears the
1234 // latest in the sorted order, regardless of the timestamp. This is used
1235 // for specifying the last key/value in a given row, because there is no
1236 // "lexicographically last column" (it would be infinitely long). The
1237 // "maximum" key type does not need this behavior.
1238 if (nextIndexedCell
.getFamilyLength() + nextIndexedCell
.getQualifierLength() == 0
1239 && nextIndexedCell
.getTypeByte() == KeyValue
.Type
.Minimum
.getCode()) {
1240 // left is "bigger", i.e. it appears later in the sorted order
1243 if (flen
+ clen
== 0 && type
== KeyValue
.Type
.Minimum
.getCode()) {
1247 compare
= comparator
.compareFamilies(nextIndexedCell
, currentCell
);
1251 if (colHint
== null) {
1252 compare
= comparator
.compareQualifiers(nextIndexedCell
, currentCell
);
1254 compare
= CellUtil
.compareQualifiers(nextIndexedCell
, colHint
, coff
, clen
);
1259 // Next compare timestamps.
1260 compare
= comparator
.compareTimestamps(nextIndexedCell
.getTimestamp(), ts
);
1265 // Compare types. Let the delete types sort ahead of puts; i.e. types
1266 // of higher numbers sort before those of lesser numbers. Maximum (255)
1267 // appears ahead of everything, and minimum (0) appears after
1269 return (0xff & type
) - (0xff & nextIndexedCell
.getTypeByte());
1273 * Compares only the key portion of a cell. It does not include the sequence id/mvcc of the cell
1276 * @return an int greater than 0 if left > than right lesser than 0 if left < than right
1277 * equal to 0 if left is equal to right
1279 public static final int compareKeyIgnoresMvcc(CellComparator comparator
, Cell left
, Cell right
) {
1280 return ((CellComparatorImpl
) comparator
).compare(left
, right
, true);
1284 * Compare cell's row against given comparator
1285 * @param cell the cell to use for comparison
1286 * @param comparator the {@link CellComparator} to use for comparison
1287 * @return result comparing cell's row
1289 public static int compareRow(Cell cell
, ByteArrayComparable comparator
) {
1290 if (cell
instanceof ByteBufferExtendedCell
) {
1291 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
1292 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength());
1294 return comparator
.compareTo(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
1298 * Compare cell's column family against given comparator
1299 * @param cell the cell to use for comparison
1300 * @param comparator the {@link CellComparator} to use for comparison
1301 * @return result comparing cell's column family
1303 public static int compareFamily(Cell cell
, ByteArrayComparable comparator
) {
1304 if (cell
instanceof ByteBufferExtendedCell
) {
1305 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
1306 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength());
1308 return comparator
.compareTo(cell
.getFamilyArray(), cell
.getFamilyOffset(),
1309 cell
.getFamilyLength());
1313 * Compare cell's qualifier against given comparator
1314 * @param cell the cell to use for comparison
1315 * @param comparator the {@link CellComparator} to use for comparison
1316 * @return result comparing cell's qualifier
1318 public static int compareQualifier(Cell cell
, ByteArrayComparable comparator
) {
1319 if (cell
instanceof ByteBufferExtendedCell
) {
1320 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
1321 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength());
1323 return comparator
.compareTo(cell
.getQualifierArray(), cell
.getQualifierOffset(),
1324 cell
.getQualifierLength());
1327 public static Cell
.Type
toType(byte type
) {
1328 KeyValue
.Type codeToType
= KeyValue
.Type
.codeToType(type
);
1329 switch (codeToType
) {
1330 case Put
: return Cell
.Type
.Put
;
1331 case Delete
: return Cell
.Type
.Delete
;
1332 case DeleteColumn
: return Cell
.Type
.DeleteColumn
;
1333 case DeleteFamily
: return Cell
.Type
.DeleteFamily
;
1334 case DeleteFamilyVersion
: return Cell
.Type
.DeleteFamilyVersion
;
1335 default: throw new UnsupportedOperationException("Invalid type of cell "+type
);
1339 public static KeyValue
.Type
toTypeByte(Cell
.Type type
) {
1341 case Put
: return KeyValue
.Type
.Put
;
1342 case Delete
: return KeyValue
.Type
.Delete
;
1343 case DeleteColumn
: return KeyValue
.Type
.DeleteColumn
;
1344 case DeleteFamilyVersion
: return KeyValue
.Type
.DeleteFamilyVersion
;
1345 case DeleteFamily
: return KeyValue
.Type
.DeleteFamily
;
1346 default: throw new UnsupportedOperationException("Unsupported data type:" + type
);
1351 * Compare cell's value against given comparator
1352 * @param cell the cell to use for comparison
1353 * @param comparator the {@link CellComparator} to use for comparison
1354 * @return result comparing cell's value
1356 public static int compareValue(Cell cell
, ByteArrayComparable comparator
) {
1357 if (cell
instanceof ByteBufferExtendedCell
) {
1358 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
1359 ((ByteBufferExtendedCell
) cell
).getValuePosition(), cell
.getValueLength());
1361 return comparator
.compareTo(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
1365 * These cells are used in reseeks/seeks to improve the read performance. They are not real cells
1366 * that are returned back to the clients
1368 private static abstract class EmptyCell
implements ExtendedCell
{
1371 public void setSequenceId(long seqId
) {
1372 // Fake cells don't need seqId, so leaving it as a noop.
1376 public void setTimestamp(long ts
) {
1377 // Fake cells can't be changed timestamp, so leaving it as a noop.
1381 public void setTimestamp(byte[] ts
) {
1382 // Fake cells can't be changed timestamp, so leaving it as a noop.
1386 public byte[] getRowArray() {
1387 return EMPTY_BYTE_ARRAY
;
1391 public int getRowOffset() {
1396 public short getRowLength() {
1401 public byte[] getFamilyArray() {
1402 return EMPTY_BYTE_ARRAY
;
1406 public int getFamilyOffset() {
1411 public byte getFamilyLength() {
1416 public byte[] getQualifierArray() {
1417 return EMPTY_BYTE_ARRAY
;
1421 public int getQualifierOffset() {
1426 public int getQualifierLength() {
1431 public long getSequenceId() {
1436 public byte[] getValueArray() {
1437 return EMPTY_BYTE_ARRAY
;
1441 public int getValueOffset() {
1446 public int getValueLength() {
1451 public byte[] getTagsArray() {
1452 return EMPTY_BYTE_ARRAY
;
1456 public int getTagsOffset() {
1461 public int getTagsLength() {
1467 * These cells are used in reseeks/seeks to improve the read performance. They are not real cells
1468 * that are returned back to the clients
1470 private static abstract class EmptyByteBufferExtendedCell
extends ByteBufferExtendedCell
{
1473 public void setSequenceId(long seqId
) {
1474 // Fake cells don't need seqId, so leaving it as a noop.
1478 public void setTimestamp(long ts
) {
1479 // Fake cells can't be changed timestamp, so leaving it as a noop.
1483 public void setTimestamp(byte[] ts
) {
1484 // Fake cells can't be changed timestamp, so leaving it as a noop.
1488 public byte[] getRowArray() {
1489 return CellUtil
.cloneRow(this);
1493 public int getRowOffset() {
1498 public short getRowLength() {
1503 public byte[] getFamilyArray() {
1504 return CellUtil
.cloneFamily(this);
1508 public int getFamilyOffset() {
1513 public byte getFamilyLength() {
1518 public byte[] getQualifierArray() {
1519 return CellUtil
.cloneQualifier(this);
1523 public int getQualifierOffset() {
1528 public int getQualifierLength() {
1533 public long getSequenceId() {
1538 public byte[] getValueArray() {
1539 return CellUtil
.cloneValue(this);
1543 public int getValueOffset() {
1548 public int getValueLength() {
1553 public byte[] getTagsArray() {
1554 return PrivateCellUtil
.cloneTags(this);
1558 public int getTagsOffset() {
1563 public int getTagsLength() {
1568 public ByteBuffer
getRowByteBuffer() {
1569 return HConstants
.EMPTY_BYTE_BUFFER
;
1573 public int getRowPosition() {
1578 public ByteBuffer
getFamilyByteBuffer() {
1579 return HConstants
.EMPTY_BYTE_BUFFER
;
1583 public int getFamilyPosition() {
1588 public ByteBuffer
getQualifierByteBuffer() {
1589 return HConstants
.EMPTY_BYTE_BUFFER
;
1593 public int getQualifierPosition() {
1598 public ByteBuffer
getTagsByteBuffer() {
1599 return HConstants
.EMPTY_BYTE_BUFFER
;
1603 public int getTagsPosition() {
1608 public ByteBuffer
getValueByteBuffer() {
1609 return HConstants
.EMPTY_BYTE_BUFFER
;
1613 public int getValuePosition() {
1618 private static class FirstOnRowCell
extends EmptyCell
{
1619 private static final int FIXED_HEAPSIZE
=
1620 ClassSize
.OBJECT
// object
1621 + ClassSize
.REFERENCE
// row array
1622 + Bytes
.SIZEOF_INT
// row offset
1623 + Bytes
.SIZEOF_SHORT
; // row length
1624 private final byte[] rowArray
;
1625 private final int roffset
;
1626 private final short rlength
;
1628 public FirstOnRowCell(final byte[] row
, int roffset
, short rlength
) {
1629 this.rowArray
= row
;
1630 this.roffset
= roffset
;
1631 this.rlength
= rlength
;
1635 public long heapSize() {
1636 return ClassSize
.align(FIXED_HEAPSIZE
)
1638 + (rlength
== 0 ? ClassSize
.sizeOfByteArray(rlength
) : rlength
);
1642 public byte[] getRowArray() {
1643 return this.rowArray
;
1647 public int getRowOffset() {
1648 return this.roffset
;
1652 public short getRowLength() {
1653 return this.rlength
;
1657 public long getTimestamp() {
1658 return HConstants
.LATEST_TIMESTAMP
;
1662 public byte getTypeByte() {
1663 return KeyValue
.Type
.Maximum
.getCode();
1667 public Type
getType() {
1668 throw new UnsupportedOperationException();
1672 private static class FirstOnRowByteBufferExtendedCell
extends EmptyByteBufferExtendedCell
{
1673 private static final int FIXED_OVERHEAD
=
1674 ClassSize
.OBJECT
// object
1675 + ClassSize
.REFERENCE
// row buffer
1676 + Bytes
.SIZEOF_INT
// row offset
1677 + Bytes
.SIZEOF_SHORT
; // row length
1678 private final ByteBuffer rowBuff
;
1679 private final int roffset
;
1680 private final short rlength
;
1682 public FirstOnRowByteBufferExtendedCell(final ByteBuffer row
, int roffset
, short rlength
) {
1684 this.roffset
= roffset
;
1685 this.rlength
= rlength
;
1689 public long heapSize() {
1690 if (this.rowBuff
.hasArray()) {
1691 return ClassSize
.align(FIXED_OVERHEAD
+ rlength
);
1693 return ClassSize
.align(FIXED_OVERHEAD
);
1697 public ByteBuffer
getRowByteBuffer() {
1698 return this.rowBuff
;
1702 public int getRowPosition() {
1703 return this.roffset
;
1707 public short getRowLength() {
1708 return this.rlength
;
1712 public long getTimestamp() {
1713 return HConstants
.LATEST_TIMESTAMP
;
1717 public byte getTypeByte() {
1718 return KeyValue
.Type
.Maximum
.getCode();
1722 public Type
getType() {
1723 throw new UnsupportedOperationException();
1727 private static class LastOnRowByteBufferExtendedCell
extends EmptyByteBufferExtendedCell
{
1728 private static final int FIXED_OVERHEAD
=
1729 ClassSize
.OBJECT
// object
1730 + ClassSize
.REFERENCE
// rowBuff
1731 + Bytes
.SIZEOF_INT
// roffset
1732 + Bytes
.SIZEOF_SHORT
; // rlength
1733 private final ByteBuffer rowBuff
;
1734 private final int roffset
;
1735 private final short rlength
;
1737 public LastOnRowByteBufferExtendedCell(final ByteBuffer row
, int roffset
, short rlength
) {
1739 this.roffset
= roffset
;
1740 this.rlength
= rlength
;
1744 public long heapSize() {
1745 if (this.rowBuff
.hasArray()) {
1746 return ClassSize
.align(FIXED_OVERHEAD
+ rlength
);
1748 return ClassSize
.align(FIXED_OVERHEAD
);
1752 public ByteBuffer
getRowByteBuffer() {
1753 return this.rowBuff
;
1757 public int getRowPosition() {
1758 return this.roffset
;
1762 public short getRowLength() {
1763 return this.rlength
;
1767 public long getTimestamp() {
1768 return PrivateConstants
.OLDEST_TIMESTAMP
;
1772 public byte getTypeByte() {
1773 return KeyValue
.Type
.Minimum
.getCode();
1777 public Type
getType() {
1778 throw new UnsupportedOperationException();
1782 private static class FirstOnRowColByteBufferExtendedCell
1783 extends FirstOnRowByteBufferExtendedCell
{
1784 private static final int FIXED_OVERHEAD
=
1785 FirstOnRowByteBufferExtendedCell
.FIXED_OVERHEAD
1786 + ClassSize
.REFERENCE
* 2 // family buffer and column buffer
1787 + Bytes
.SIZEOF_INT
* 3 // famOffset, colOffset, colLength
1788 + Bytes
.SIZEOF_BYTE
; // famLength
1789 private final ByteBuffer famBuff
;
1790 private final int famOffset
;
1791 private final byte famLength
;
1792 private final ByteBuffer colBuff
;
1793 private final int colOffset
;
1794 private final int colLength
;
1796 public FirstOnRowColByteBufferExtendedCell(final ByteBuffer row
, int roffset
, short rlength
,
1797 final ByteBuffer famBuff
, final int famOffset
, final byte famLength
, final ByteBuffer col
,
1798 final int colOffset
, final int colLength
) {
1799 super(row
, roffset
, rlength
);
1800 this.famBuff
= famBuff
;
1801 this.famOffset
= famOffset
;
1802 this.famLength
= famLength
;
1804 this.colOffset
= colOffset
;
1805 this.colLength
= colLength
;
1809 public long heapSize() {
1810 if (famBuff
.hasArray() && colBuff
.hasArray()) {
1811 return ClassSize
.align(FIXED_OVERHEAD
+ famLength
+ colLength
);
1812 } else if (famBuff
.hasArray()) {
1813 return ClassSize
.align(FIXED_OVERHEAD
+ famLength
);
1814 } else if (colBuff
.hasArray()) {
1815 return ClassSize
.align(FIXED_OVERHEAD
+ colLength
);
1817 return ClassSize
.align(FIXED_OVERHEAD
);
1822 public ByteBuffer
getFamilyByteBuffer() {
1823 return this.famBuff
;
1827 public int getFamilyPosition() {
1828 return this.famOffset
;
1832 public byte getFamilyLength() {
1837 public ByteBuffer
getQualifierByteBuffer() {
1838 return this.colBuff
;
1842 public int getQualifierPosition() {
1843 return this.colOffset
;
1847 public int getQualifierLength() {
1848 return this.colLength
;
1852 private static class FirstOnRowColCell
extends FirstOnRowCell
{
1853 private static final long FIXED_HEAPSIZE
=
1854 FirstOnRowCell
.FIXED_HEAPSIZE
1855 + Bytes
.SIZEOF_BYTE
// flength
1856 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
1857 + ClassSize
.REFERENCE
* 2; // fArray, qArray
1858 private final byte[] fArray
;
1859 private final int foffset
;
1860 private final byte flength
;
1861 private final byte[] qArray
;
1862 private final int qoffset
;
1863 private final int qlength
;
1865 public FirstOnRowColCell(byte[] rArray
, int roffset
, short rlength
, byte[] fArray
, int foffset
,
1866 byte flength
, byte[] qArray
, int qoffset
, int qlength
) {
1867 super(rArray
, roffset
, rlength
);
1868 this.fArray
= fArray
;
1869 this.foffset
= foffset
;
1870 this.flength
= flength
;
1871 this.qArray
= qArray
;
1872 this.qoffset
= qoffset
;
1873 this.qlength
= qlength
;
1877 public long heapSize() {
1878 return ClassSize
.align(FIXED_HEAPSIZE
)
1880 + (flength
== 0 ? ClassSize
.sizeOfByteArray(flength
) : flength
)
1881 + (qlength
== 0 ? ClassSize
.sizeOfByteArray(qlength
) : qlength
);
1885 public byte[] getFamilyArray() {
1890 public int getFamilyOffset() {
1891 return this.foffset
;
1895 public byte getFamilyLength() {
1896 return this.flength
;
1900 public byte[] getQualifierArray() {
1905 public int getQualifierOffset() {
1906 return this.qoffset
;
1910 public int getQualifierLength() {
1911 return this.qlength
;
1915 private static class FirstOnRowColTSCell
extends FirstOnRowColCell
{
1916 private static final long FIXED_HEAPSIZE
=
1917 FirstOnRowColCell
.FIXED_HEAPSIZE
1918 + Bytes
.SIZEOF_LONG
; // ts
1921 public FirstOnRowColTSCell(byte[] rArray
, int roffset
, short rlength
, byte[] fArray
,
1922 int foffset
, byte flength
, byte[] qArray
, int qoffset
, int qlength
, long ts
) {
1923 super(rArray
, roffset
, rlength
, fArray
, foffset
, flength
, qArray
, qoffset
, qlength
);
1928 public long getTimestamp() {
1933 public long heapSize() {
1934 return ClassSize
.align(FIXED_HEAPSIZE
);
1938 private static class FirstOnRowColTSByteBufferExtendedCell
1939 extends FirstOnRowColByteBufferExtendedCell
{
1940 private static final int FIXED_OVERHEAD
=
1941 FirstOnRowColByteBufferExtendedCell
.FIXED_OVERHEAD
1942 + Bytes
.SIZEOF_LONG
; // ts
1945 public FirstOnRowColTSByteBufferExtendedCell(ByteBuffer rBuffer
, int roffset
, short rlength
,
1946 ByteBuffer fBuffer
, int foffset
, byte flength
, ByteBuffer qBuffer
, int qoffset
, int qlength
,
1948 super(rBuffer
, roffset
, rlength
, fBuffer
, foffset
, flength
, qBuffer
, qoffset
, qlength
);
1953 public long getTimestamp() {
1958 public long heapSize() {
1959 return ClassSize
.align(FIXED_OVERHEAD
+ super.heapSize());
1963 private static class LastOnRowCell
extends EmptyCell
{
1964 private static final int FIXED_OVERHEAD
=
1965 ClassSize
.OBJECT
// object
1966 + ClassSize
.REFERENCE
// row array
1967 + Bytes
.SIZEOF_INT
// row offset
1968 + Bytes
.SIZEOF_SHORT
; // row length
1969 private final byte[] rowArray
;
1970 private final int roffset
;
1971 private final short rlength
;
1973 public LastOnRowCell(byte[] row
, int roffset
, short rlength
) {
1974 this.rowArray
= row
;
1975 this.roffset
= roffset
;
1976 this.rlength
= rlength
;
1980 public long heapSize() {
1981 return ClassSize
.align(FIXED_OVERHEAD
)
1983 + (rlength
== 0 ? ClassSize
.sizeOfByteArray(rlength
) : rlength
);
1987 public byte[] getRowArray() {
1988 return this.rowArray
;
1992 public int getRowOffset() {
1993 return this.roffset
;
1997 public short getRowLength() {
1998 return this.rlength
;
2002 public long getTimestamp() {
2003 return PrivateConstants
.OLDEST_TIMESTAMP
;
2007 public byte getTypeByte() {
2008 return KeyValue
.Type
.Minimum
.getCode();
2012 public Type
getType() {
2013 throw new UnsupportedOperationException();
2017 private static class LastOnRowColCell
extends LastOnRowCell
{
2018 private static final long FIXED_OVERHEAD
= LastOnRowCell
.FIXED_OVERHEAD
2019 + ClassSize
.REFERENCE
* 2 // fArray and qArray
2020 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
2021 + Bytes
.SIZEOF_BYTE
; // flength
2022 private final byte[] fArray
;
2023 private final int foffset
;
2024 private final byte flength
;
2025 private final byte[] qArray
;
2026 private final int qoffset
;
2027 private final int qlength
;
2029 public LastOnRowColCell(byte[] rArray
, int roffset
, short rlength
, byte[] fArray
, int foffset
,
2030 byte flength
, byte[] qArray
, int qoffset
, int qlength
) {
2031 super(rArray
, roffset
, rlength
);
2032 this.fArray
= fArray
;
2033 this.foffset
= foffset
;
2034 this.flength
= flength
;
2035 this.qArray
= qArray
;
2036 this.qoffset
= qoffset
;
2037 this.qlength
= qlength
;
2041 public long heapSize() {
2042 return ClassSize
.align(FIXED_OVERHEAD
)
2044 + (flength
== 0 ? ClassSize
.sizeOfByteArray(flength
) : flength
)
2045 + (qlength
== 0 ? ClassSize
.sizeOfByteArray(qlength
) : qlength
);
2049 public byte[] getFamilyArray() {
2054 public int getFamilyOffset() {
2055 return this.foffset
;
2059 public byte getFamilyLength() {
2060 return this.flength
;
2064 public byte[] getQualifierArray() {
2069 public int getQualifierOffset() {
2070 return this.qoffset
;
2074 public int getQualifierLength() {
2075 return this.qlength
;
2079 private static class LastOnRowColByteBufferExtendedCell
extends LastOnRowByteBufferExtendedCell
{
2080 private static final int FIXED_OVERHEAD
=
2081 LastOnRowByteBufferExtendedCell
.FIXED_OVERHEAD
2082 + ClassSize
.REFERENCE
* 2 // fBuffer and qBuffer
2083 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
2084 + Bytes
.SIZEOF_BYTE
; // flength
2085 private final ByteBuffer fBuffer
;
2086 private final int foffset
;
2087 private final byte flength
;
2088 private final ByteBuffer qBuffer
;
2089 private final int qoffset
;
2090 private final int qlength
;
2092 public LastOnRowColByteBufferExtendedCell(ByteBuffer rBuffer
, int roffset
, short rlength
,
2093 ByteBuffer fBuffer
, int foffset
, byte flength
, ByteBuffer qBuffer
, int qoffset
,
2095 super(rBuffer
, roffset
, rlength
);
2096 this.fBuffer
= fBuffer
;
2097 this.foffset
= foffset
;
2098 this.flength
= flength
;
2099 this.qBuffer
= qBuffer
;
2100 this.qoffset
= qoffset
;
2101 this.qlength
= qlength
;
2105 public long heapSize() {
2106 if (fBuffer
.hasArray() && qBuffer
.hasArray()) {
2107 return ClassSize
.align(FIXED_OVERHEAD
+ flength
+ qlength
);
2108 } else if (fBuffer
.hasArray()) {
2109 return ClassSize
.align(FIXED_OVERHEAD
+ flength
);
2110 } else if (qBuffer
.hasArray()) {
2111 return ClassSize
.align(FIXED_OVERHEAD
+ qlength
);
2113 return ClassSize
.align(FIXED_OVERHEAD
);
2118 public ByteBuffer
getFamilyByteBuffer() {
2119 return this.fBuffer
;
2123 public int getFamilyPosition() {
2124 return this.foffset
;
2128 public byte getFamilyLength() {
2129 return this.flength
;
2133 public ByteBuffer
getQualifierByteBuffer() {
2134 return this.qBuffer
;
2138 public int getQualifierPosition() {
2139 return this.qoffset
;
2143 public int getQualifierLength() {
2144 return this.qlength
;
2148 private static class FirstOnRowDeleteFamilyCell
extends EmptyCell
{
2149 private static final int FIXED_OVERHEAD
=
2150 ClassSize
.OBJECT
// object
2151 + ClassSize
.REFERENCE
* 2 // fBuffer and qBuffer
2152 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
2153 + Bytes
.SIZEOF_BYTE
; // flength
2154 private final byte[] row
;
2155 private final byte[] fam
;
2157 public FirstOnRowDeleteFamilyCell(byte[] row
, byte[] fam
) {
2163 public long heapSize() {
2164 return ClassSize
.align(FIXED_OVERHEAD
)
2166 + (getRowLength() == 0 ? ClassSize
.sizeOfByteArray(getRowLength()) : getRowLength())
2167 + (getFamilyLength() == 0 ?
2168 ClassSize
.sizeOfByteArray(getFamilyLength()) : getFamilyLength());
2172 public byte[] getRowArray() {
2177 public short getRowLength() {
2178 return (short) this.row
.length
;
2182 public byte[] getFamilyArray() {
2187 public byte getFamilyLength() {
2188 return (byte) this.fam
.length
;
2192 public long getTimestamp() {
2193 return HConstants
.LATEST_TIMESTAMP
;
2197 public byte getTypeByte() {
2198 return KeyValue
.Type
.DeleteFamily
.getCode();
2202 public Type
getType() {
2203 return Type
.DeleteFamily
;
2208 * Writes the Cell's key part as it would have serialized in a KeyValue. The format is <2 bytes
2209 * rk len><rk><1 byte cf len><cf><qualifier><8 bytes
2210 * timestamp><1 byte type>
2213 * @throws IOException
2215 public static void writeFlatKey(Cell cell
, DataOutput out
) throws IOException
{
2216 short rowLen
= cell
.getRowLength();
2217 byte fLen
= cell
.getFamilyLength();
2218 int qLen
= cell
.getQualifierLength();
2219 // Using just one if/else loop instead of every time checking before writing every
2220 // component of cell
2221 if (cell
instanceof ByteBufferExtendedCell
) {
2222 out
.writeShort(rowLen
);
2223 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2224 ((ByteBufferExtendedCell
) cell
).getRowPosition(), rowLen
);
2225 out
.writeByte(fLen
);
2226 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2227 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), fLen
);
2229 .copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2230 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), qLen
);
2232 out
.writeShort(rowLen
);
2233 out
.write(cell
.getRowArray(), cell
.getRowOffset(), rowLen
);
2234 out
.writeByte(fLen
);
2235 out
.write(cell
.getFamilyArray(), cell
.getFamilyOffset(), fLen
);
2236 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset(), qLen
);
2238 out
.writeLong(cell
.getTimestamp());
2239 out
.writeByte(cell
.getTypeByte());
2243 * Deep clones the given cell if the cell supports deep cloning
2244 * @param cell the cell to be cloned
2245 * @return the cloned cell
2246 * @throws CloneNotSupportedException
2248 public static Cell
deepClone(Cell cell
) throws CloneNotSupportedException
{
2249 if (cell
instanceof ExtendedCell
) {
2250 return ((ExtendedCell
) cell
).deepClone();
2252 throw new CloneNotSupportedException();
2256 * Writes the cell to the given OutputStream
2257 * @param cell the cell to be written
2258 * @param out the outputstream
2259 * @param withTags if tags are to be written or not
2260 * @return the total bytes written
2261 * @throws IOException
2263 public static int writeCell(Cell cell
, OutputStream out
, boolean withTags
) throws IOException
{
2264 if (cell
instanceof ExtendedCell
) {
2265 return ((ExtendedCell
) cell
).write(out
, withTags
);
2267 ByteBufferUtils
.putInt(out
, estimatedSerializedSizeOfKey(cell
));
2268 ByteBufferUtils
.putInt(out
, cell
.getValueLength());
2269 writeFlatKey(cell
, out
);
2270 writeValue(out
, cell
, cell
.getValueLength());
2271 int tagsLength
= cell
.getTagsLength();
2273 byte[] len
= new byte[Bytes
.SIZEOF_SHORT
];
2274 Bytes
.putAsShort(len
, 0, tagsLength
);
2276 if (tagsLength
> 0) {
2277 writeTags(out
, cell
, tagsLength
);
2280 int lenWritten
= (2 * Bytes
.SIZEOF_INT
) + estimatedSerializedSizeOfKey(cell
)
2281 + cell
.getValueLength();
2283 lenWritten
+= Bytes
.SIZEOF_SHORT
+ tagsLength
;
2290 * Writes a cell to the buffer at the given offset
2291 * @param cell the cell to be written
2292 * @param buf the buffer to which the cell has to be wrriten
2293 * @param offset the offset at which the cell should be written
2295 public static void writeCellToBuffer(Cell cell
, ByteBuffer buf
, int offset
) {
2296 if (cell
instanceof ExtendedCell
) {
2297 ((ExtendedCell
) cell
).write(buf
, offset
);
2300 byte[] bytes
= KeyValueUtil
.copyToNewByteArray(cell
);
2301 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, bytes
, 0, bytes
.length
);
2305 public static int writeFlatKey(Cell cell
, OutputStream out
) throws IOException
{
2306 short rowLen
= cell
.getRowLength();
2307 byte fLen
= cell
.getFamilyLength();
2308 int qLen
= cell
.getQualifierLength();
2309 // Using just one if/else loop instead of every time checking before writing every
2310 // component of cell
2311 if (cell
instanceof ByteBufferExtendedCell
) {
2312 StreamUtils
.writeShort(out
, rowLen
);
2313 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2314 ((ByteBufferExtendedCell
) cell
).getRowPosition(), rowLen
);
2316 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2317 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), fLen
);
2319 .copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2320 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), qLen
);
2322 StreamUtils
.writeShort(out
, rowLen
);
2323 out
.write(cell
.getRowArray(), cell
.getRowOffset(), rowLen
);
2325 out
.write(cell
.getFamilyArray(), cell
.getFamilyOffset(), fLen
);
2326 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset(), qLen
);
2328 StreamUtils
.writeLong(out
, cell
.getTimestamp());
2329 out
.write(cell
.getTypeByte());
2330 return Bytes
.SIZEOF_SHORT
+ rowLen
+ Bytes
.SIZEOF_BYTE
+ fLen
+ qLen
+ Bytes
.SIZEOF_LONG
2331 + Bytes
.SIZEOF_BYTE
;
2335 * Sets the given seqId to the cell. Marked as audience Private as of 1.2.0. Setting a Cell
2336 * sequenceid is an internal implementation detail not for general public use.
2339 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2341 public static void setSequenceId(Cell cell
, long seqId
) throws IOException
{
2342 if (cell
instanceof ExtendedCell
) {
2343 ((ExtendedCell
) cell
).setSequenceId(seqId
);
2345 throw new IOException(new UnsupportedOperationException(
2346 "Cell is not of type " + ExtendedCell
.class.getName()));
2351 * Sets the given timestamp to the cell.
2354 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2356 public static void setTimestamp(Cell cell
, long ts
) throws IOException
{
2357 if (cell
instanceof ExtendedCell
) {
2358 ((ExtendedCell
) cell
).setTimestamp(ts
);
2360 throw new IOException(new UnsupportedOperationException(
2361 "Cell is not of type " + ExtendedCell
.class.getName()));
2366 * Sets the given timestamp to the cell.
2368 * @param ts buffer containing the timestamp value
2369 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2371 public static void setTimestamp(Cell cell
, byte[] ts
) throws IOException
{
2372 if (cell
instanceof ExtendedCell
) {
2373 ((ExtendedCell
) cell
).setTimestamp(ts
);
2375 throw new IOException(new UnsupportedOperationException(
2376 "Cell is not of type " + ExtendedCell
.class.getName()));
2381 * Sets the given timestamp to the cell iff current timestamp is
2382 * {@link HConstants#LATEST_TIMESTAMP}.
2385 * @return True if cell timestamp is modified.
2386 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2388 public static boolean updateLatestStamp(Cell cell
, long ts
) throws IOException
{
2389 if (cell
.getTimestamp() == HConstants
.LATEST_TIMESTAMP
) {
2390 setTimestamp(cell
, ts
);
2397 * Sets the given timestamp to the cell iff current timestamp is
2398 * {@link HConstants#LATEST_TIMESTAMP}.
2400 * @param ts buffer containing the timestamp value
2401 * @return True if cell timestamp is modified.
2402 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2404 public static boolean updateLatestStamp(Cell cell
, byte[] ts
) throws IOException
{
2405 if (cell
.getTimestamp() == HConstants
.LATEST_TIMESTAMP
) {
2406 setTimestamp(cell
, ts
);
2413 * Writes the row from the given cell to the output stream
2414 * @param out The outputstream to which the data has to be written
2415 * @param cell The cell whose contents has to be written
2416 * @param rlength the row length
2417 * @throws IOException
2419 public static void writeRow(OutputStream out
, Cell cell
, short rlength
) throws IOException
{
2420 if (cell
instanceof ByteBufferExtendedCell
) {
2421 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2422 ((ByteBufferExtendedCell
) cell
).getRowPosition(), rlength
);
2424 out
.write(cell
.getRowArray(), cell
.getRowOffset(), rlength
);
2429 * Writes the family from the given cell to the output stream
2430 * @param out The outputstream to which the data has to be written
2431 * @param cell The cell whose contents has to be written
2432 * @param flength the family length
2433 * @throws IOException
2435 public static void writeFamily(OutputStream out
, Cell cell
, byte flength
) throws IOException
{
2436 if (cell
instanceof ByteBufferExtendedCell
) {
2437 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2438 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), flength
);
2440 out
.write(cell
.getFamilyArray(), cell
.getFamilyOffset(), flength
);
2445 * Writes the qualifier from the given cell to the output stream
2446 * @param out The outputstream to which the data has to be written
2447 * @param cell The cell whose contents has to be written
2448 * @param qlength the qualifier length
2449 * @throws IOException
2451 public static void writeQualifier(OutputStream out
, Cell cell
, int qlength
) throws IOException
{
2452 if (cell
instanceof ByteBufferExtendedCell
) {
2454 .copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2455 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), qlength
);
2457 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset(), qlength
);
2462 * Writes the qualifier from the given cell to the output stream excluding the common prefix
2463 * @param out The dataoutputstream to which the data has to be written
2464 * @param cell The cell whose contents has to be written
2465 * @param qlength the qualifier length
2466 * @throws IOException
2468 public static void writeQualifierSkippingBytes(DataOutputStream out
, Cell cell
, int qlength
,
2469 int commonPrefix
) throws IOException
{
2470 if (cell
instanceof ByteBufferExtendedCell
) {
2471 ByteBufferUtils
.copyBufferToStream((DataOutput
) out
,
2472 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2473 ((ByteBufferExtendedCell
) cell
).getQualifierPosition() + commonPrefix
,
2474 qlength
- commonPrefix
);
2476 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset() + commonPrefix
,
2477 qlength
- commonPrefix
);
2482 * Writes the value from the given cell to the output stream
2483 * @param out The outputstream to which the data has to be written
2484 * @param cell The cell whose contents has to be written
2485 * @param vlength the value length
2486 * @throws IOException
2488 public static void writeValue(OutputStream out
, Cell cell
, int vlength
) throws IOException
{
2489 if (cell
instanceof ByteBufferExtendedCell
) {
2490 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2491 ((ByteBufferExtendedCell
) cell
).getValuePosition(), vlength
);
2493 out
.write(cell
.getValueArray(), cell
.getValueOffset(), vlength
);
2498 * Writes the tag from the given cell to the output stream
2499 * @param out The outputstream to which the data has to be written
2500 * @param cell The cell whose contents has to be written
2501 * @param tagsLength the tag length
2502 * @throws IOException
2504 public static void writeTags(OutputStream out
, Cell cell
, int tagsLength
) throws IOException
{
2505 if (cell
instanceof ByteBufferExtendedCell
) {
2506 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
2507 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), tagsLength
);
2509 out
.write(cell
.getTagsArray(), cell
.getTagsOffset(), tagsLength
);
2514 * special case for Cell.equals
2516 public static boolean equalsIgnoreMvccVersion(Cell a
, Cell b
) {
2518 boolean res
= CellUtil
.matchingRows(a
, b
);
2519 if (!res
) return res
;
2522 res
= CellUtil
.matchingColumn(a
, b
);
2523 if (!res
) return res
;
2525 // timestamp: later sorts first
2526 if (!CellUtil
.matchingTimestamp(a
, b
)) return false;
2529 int c
= (0xff & b
.getTypeByte()) - (0xff & a
.getTypeByte());
2530 if (c
!= 0) return false;
2535 * Converts the rowkey bytes of the given cell into an int value
2537 * @return rowkey as int
2539 public static int getRowAsInt(Cell cell
) {
2540 if (cell
instanceof ByteBufferExtendedCell
) {
2541 return ByteBufferUtils
.toInt(((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2542 ((ByteBufferExtendedCell
) cell
).getRowPosition());
2544 return Bytes
.toInt(cell
.getRowArray(), cell
.getRowOffset());
2548 * Converts the value bytes of the given cell into a long value
2550 * @return value as long
2552 public static long getValueAsLong(Cell cell
) {
2553 if (cell
instanceof ByteBufferExtendedCell
) {
2554 return ByteBufferUtils
.toLong(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2555 ((ByteBufferExtendedCell
) cell
).getValuePosition());
2557 return Bytes
.toLong(cell
.getValueArray(), cell
.getValueOffset());
2561 * Converts the value bytes of the given cell into a int value
2563 * @return value as int
2565 public static int getValueAsInt(Cell cell
) {
2566 if (cell
instanceof ByteBufferExtendedCell
) {
2567 return ByteBufferUtils
.toInt(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2568 ((ByteBufferExtendedCell
) cell
).getValuePosition());
2570 return Bytes
.toInt(cell
.getValueArray(), cell
.getValueOffset());
2574 * Converts the value bytes of the given cell into a double value
2576 * @return value as double
2578 public static double getValueAsDouble(Cell cell
) {
2579 if (cell
instanceof ByteBufferExtendedCell
) {
2580 return ByteBufferUtils
.toDouble(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2581 ((ByteBufferExtendedCell
) cell
).getValuePosition());
2583 return Bytes
.toDouble(cell
.getValueArray(), cell
.getValueOffset());
2587 * Converts the value bytes of the given cell into a BigDecimal
2589 * @return value as BigDecimal
2591 public static BigDecimal
getValueAsBigDecimal(Cell cell
) {
2592 if (cell
instanceof ByteBufferExtendedCell
) {
2593 return ByteBufferUtils
.toBigDecimal(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2594 ((ByteBufferExtendedCell
) cell
).getValuePosition(), cell
.getValueLength());
2596 return Bytes
.toBigDecimal(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
2600 * Compresses the tags to the given outputstream using the TagcompressionContext
2601 * @param out the outputstream to which the compression should happen
2602 * @param cell the cell which has tags
2603 * @param tagCompressionContext the TagCompressionContext
2604 * @throws IOException can throw IOException if the compression encounters issue
2606 public static void compressTags(OutputStream out
, Cell cell
,
2607 TagCompressionContext tagCompressionContext
) throws IOException
{
2608 if (cell
instanceof ByteBufferExtendedCell
) {
2609 tagCompressionContext
.compressTags(out
, ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
2610 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), cell
.getTagsLength());
2612 tagCompressionContext
.compressTags(out
, cell
.getTagsArray(), cell
.getTagsOffset(),
2613 cell
.getTagsLength());
2617 public static void compressRow(OutputStream out
, Cell cell
, Dictionary dict
) throws IOException
{
2618 if (cell
instanceof ByteBufferExtendedCell
) {
2619 Dictionary
.write(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2620 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(), dict
);
2622 Dictionary
.write(out
, cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(), dict
);
2626 public static void compressFamily(OutputStream out
, Cell cell
, Dictionary dict
)
2627 throws IOException
{
2628 if (cell
instanceof ByteBufferExtendedCell
) {
2629 Dictionary
.write(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2630 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(), dict
);
2632 Dictionary
.write(out
, cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2637 public static void compressQualifier(OutputStream out
, Cell cell
, Dictionary dict
)
2638 throws IOException
{
2639 if (cell
instanceof ByteBufferExtendedCell
) {
2640 Dictionary
.write(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2641 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength(), dict
);
2643 Dictionary
.write(out
, cell
.getQualifierArray(), cell
.getQualifierOffset(),
2644 cell
.getQualifierLength(), dict
);
2649 * Used when a cell needs to be compared with a key byte[] such as cases of finding the index from
2650 * the index block, bloom keys from the bloom blocks This byte[] is expected to be serialized in
2651 * the KeyValue serialization format If the KeyValue (Cell's) serialization format changes this
2652 * method cannot be used.
2653 * @param comparator the {@link CellComparator} to use for comparison
2654 * @param left the cell to be compared
2655 * @param key the serialized key part of a KeyValue
2656 * @param offset the offset in the key byte[]
2657 * @param length the length of the key byte[]
2658 * @return an int greater than 0 if left is greater than right lesser than 0 if left is lesser
2659 * than right equal to 0 if left is equal to right
2661 public static final int compare(CellComparator comparator
, Cell left
, byte[] key
, int offset
,
2664 short rrowlength
= Bytes
.toShort(key
, offset
);
2665 int c
= comparator
.compareRows(left
, key
, offset
+ Bytes
.SIZEOF_SHORT
, rrowlength
);
2666 if (c
!= 0) return c
;
2668 // Compare the rest of the two KVs without making any assumptions about
2669 // the common prefix. This function will not compare rows anyway, so we
2670 // don't need to tell it that the common prefix includes the row.
2671 return compareWithoutRow(comparator
, left
, key
, offset
, length
, rrowlength
);
2675 * Compare columnFamily, qualifier, timestamp, and key type (everything except the row). This
2676 * method is used both in the normal comparator and the "same-prefix" comparator. Note that we are
2677 * assuming that row portions of both KVs have already been parsed and found identical, and we
2678 * don't validate that assumption here.
2679 * @param comparator the {@link CellComparator} to use for comparison
2680 * @param left the cell to be compared
2681 * @param right the serialized key part of a key-value
2682 * @param roffset the offset in the key byte[]
2683 * @param rlength the length of the key byte[]
2684 * @param rowlength the row length
2685 * @return greater than 0 if left cell is bigger, less than 0 if right cell is bigger, 0 if both
2688 static final int compareWithoutRow(CellComparator comparator
, Cell left
, byte[] right
,
2689 int roffset
, int rlength
, short rowlength
) {
2691 * KeyValue Format and commonLength:
2692 * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
2693 * ------------------|-------commonLength--------|--------------
2695 int commonLength
= KeyValue
.ROW_LENGTH_SIZE
+ KeyValue
.FAMILY_LENGTH_SIZE
+ rowlength
;
2697 // commonLength + TIMESTAMP_TYPE_SIZE
2698 int commonLengthWithTSAndType
= KeyValue
.TIMESTAMP_TYPE_SIZE
+ commonLength
;
2699 // ColumnFamily + Qualifier length.
2700 int lcolumnlength
= left
.getFamilyLength() + left
.getQualifierLength();
2701 int rcolumnlength
= rlength
- commonLengthWithTSAndType
;
2703 byte ltype
= left
.getTypeByte();
2704 byte rtype
= right
[roffset
+ (rlength
- 1)];
2706 // If the column is not specified, the "minimum" key type appears the
2707 // latest in the sorted order, regardless of the timestamp. This is used
2708 // for specifying the last key/value in a given row, because there is no
2709 // "lexicographically last column" (it would be infinitely long). The
2710 // "maximum" key type does not need this behavior.
2711 if (lcolumnlength
== 0 && ltype
== KeyValue
.Type
.Minimum
.getCode()) {
2712 // left is "bigger", i.e. it appears later in the sorted order
2715 if (rcolumnlength
== 0 && rtype
== KeyValue
.Type
.Minimum
.getCode()) {
2719 int rfamilyoffset
= commonLength
+ roffset
;
2721 // Column family length.
2722 int lfamilylength
= left
.getFamilyLength();
2723 int rfamilylength
= right
[rfamilyoffset
- 1];
2724 // If left family size is not equal to right family size, we need not
2725 // compare the qualifiers.
2726 boolean sameFamilySize
= (lfamilylength
== rfamilylength
);
2727 if (!sameFamilySize
) {
2728 // comparing column family is enough.
2729 return CellUtil
.compareFamilies(left
, right
, rfamilyoffset
, rfamilylength
);
2731 // Compare family & qualifier together.
2732 // Families are same. Compare on qualifiers.
2733 int comparison
= CellUtil
.compareColumns(left
, right
, rfamilyoffset
, rfamilylength
,
2734 rfamilyoffset
+ rfamilylength
, (rcolumnlength
- rfamilylength
));
2735 if (comparison
!= 0) {
2740 // Next compare timestamps.
2741 long rtimestamp
= Bytes
.toLong(right
, roffset
+ (rlength
- KeyValue
.TIMESTAMP_TYPE_SIZE
));
2742 int compare
= comparator
.compareTimestamps(left
.getTimestamp(), rtimestamp
);
2747 // Compare types. Let the delete types sort ahead of puts; i.e. types
2748 // of higher numbers sort before those of lesser numbers. Maximum (255)
2749 // appears ahead of everything, and minimum (0) appears after
2751 return (0xff & rtype
) - (0xff & ltype
);
2755 * @return An new cell is located following input cell. If both of type and timestamp are minimum,
2756 * the input cell will be returned directly.
2758 public static Cell
createNextOnRowCol(Cell cell
) {
2759 long ts
= cell
.getTimestamp();
2760 byte type
= cell
.getTypeByte();
2761 if (type
!= KeyValue
.Type
.Minimum
.getCode()) {
2762 type
= KeyValue
.Type
.values()[KeyValue
.Type
.codeToType(type
).ordinal() - 1].getCode();
2763 } else if (ts
!= PrivateConstants
.OLDEST_TIMESTAMP
) {
2765 type
= KeyValue
.Type
.Maximum
.getCode();
2769 return createNextOnRowCol(cell
, ts
, type
);
2772 static Cell
createNextOnRowCol(Cell cell
, long ts
, byte type
) {
2773 if (cell
instanceof ByteBufferExtendedCell
) {
2774 return new LastOnRowColByteBufferExtendedCell(
2775 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2776 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2777 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2778 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2779 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2780 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength()) {
2782 public long getTimestamp() {
2787 public byte getTypeByte() {
2792 return new LastOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2793 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2794 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength()) {
2796 public long getTimestamp() {
2801 public byte getTypeByte() {
2808 * Estimate based on keyvalue's serialization format in the RPC layer. Note that there is an extra
2809 * SIZEOF_INT added to the size here that indicates the actual length of the cell for cases where
2810 * cell's are serialized in a contiguous format (For eg in RPCs).
2812 * @return Estimate of the <code>cell</code> size in bytes plus an extra SIZEOF_INT indicating the
2813 * actual cell length.
2815 public static int estimatedSerializedSizeOf(final Cell cell
) {
2816 return cell
.getSerializedSize() + Bytes
.SIZEOF_INT
;
2820 * Calculates the serialized key size. We always serialize in the KeyValue's serialization format.
2821 * @param cell the cell for which the key size has to be calculated.
2822 * @return the key size
2824 public static int estimatedSerializedSizeOfKey(final Cell cell
) {
2825 if (cell
instanceof KeyValue
) return ((KeyValue
) cell
).getKeyLength();
2826 return cell
.getRowLength() + cell
.getFamilyLength() + cell
.getQualifierLength()
2827 + KeyValue
.KEY_INFRASTRUCTURE_SIZE
;
2831 * This method exists just to encapsulate how we serialize keys. To be replaced by a factory that
2832 * we query to figure what the Cell implementation is and then, what serialization engine to use
2833 * and further, how to serialize the key for inclusion in hfile index. TODO.
2835 * @return The key portion of the Cell serialized in the old-school KeyValue way or null if passed
2836 * a null <code>cell</code>
2838 public static byte[] getCellKeySerializedAsKeyValueKey(final Cell cell
) {
2839 if (cell
== null) return null;
2840 byte[] b
= new byte[KeyValueUtil
.keyLength(cell
)];
2841 KeyValueUtil
.appendKeyTo(cell
, b
, 0);
2846 * Create a Cell that is smaller than all other possible Cells for the given Cell's row.
2848 * @return First possible Cell on passed Cell's row.
2850 public static Cell
createFirstOnRow(final Cell cell
) {
2851 if (cell
instanceof ByteBufferExtendedCell
) {
2852 return new FirstOnRowByteBufferExtendedCell(
2853 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2854 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength());
2856 return new FirstOnRowCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
2859 public static Cell
createFirstOnRow(final byte[] row
, int roffset
, short rlength
) {
2860 return new FirstOnRowCell(row
, roffset
, rlength
);
2863 public static Cell
createFirstOnRow(final byte[] row
, final byte[] family
, final byte[] col
) {
2864 return createFirstOnRow(row
, 0, (short) row
.length
, family
, 0, (byte) family
.length
, col
, 0,
2868 public static Cell
createFirstOnRow(final byte[] row
, int roffset
, short rlength
,
2869 final byte[] family
, int foffset
, byte flength
, final byte[] col
, int coffset
, int clength
) {
2870 return new FirstOnRowColCell(row
, roffset
, rlength
, family
, foffset
, flength
, col
, coffset
,
2874 public static Cell
createFirstOnRow(final byte[] row
) {
2875 return createFirstOnRow(row
, 0, (short) row
.length
);
2878 public static Cell
createFirstOnRowFamily(Cell cell
, byte[] fArray
, int foff
, int flen
) {
2879 if (cell
instanceof ByteBufferExtendedCell
) {
2880 return new FirstOnRowColByteBufferExtendedCell(
2881 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2882 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2883 ByteBuffer
.wrap(fArray
), foff
, (byte) flen
, HConstants
.EMPTY_BYTE_BUFFER
, 0, 0);
2885 return new FirstOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2886 fArray
, foff
, (byte) flen
, HConstants
.EMPTY_BYTE_ARRAY
, 0, 0);
2889 public static Cell
createFirstOnRowCol(final Cell cell
) {
2890 if (cell
instanceof ByteBufferExtendedCell
) {
2891 return new FirstOnRowColByteBufferExtendedCell(
2892 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2893 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2894 HConstants
.EMPTY_BYTE_BUFFER
, 0, (byte) 0,
2895 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2896 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength());
2898 return new FirstOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2899 HConstants
.EMPTY_BYTE_ARRAY
, 0, (byte) 0, cell
.getQualifierArray(),
2900 cell
.getQualifierOffset(), cell
.getQualifierLength());
2903 public static Cell
createFirstOnNextRow(final Cell cell
) {
2904 byte[] nextRow
= new byte[cell
.getRowLength() + 1];
2905 CellUtil
.copyRowTo(cell
, nextRow
, 0);
2906 nextRow
[nextRow
.length
- 1] = 0;// maybe not necessary
2907 return new FirstOnRowCell(nextRow
, 0, (short) nextRow
.length
);
2911 * Create a Cell that is smaller than all other possible Cells for the given Cell's rk:cf and
2917 * @return Last possible Cell on passed Cell's rk:cf and passed qualifier.
2919 public static Cell
createFirstOnRowCol(final Cell cell
, byte[] qArray
, int qoffest
, int qlength
) {
2920 if (cell
instanceof ByteBufferExtendedCell
) {
2921 return new FirstOnRowColByteBufferExtendedCell(
2922 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2923 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2924 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2925 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2926 ByteBuffer
.wrap(qArray
), qoffest
, qlength
);
2928 return new FirstOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2929 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(), qArray
, qoffest
,
2934 * Creates the first cell with the row/family/qualifier of this cell and the given timestamp. Uses
2935 * the "maximum" type that guarantees that the new cell is the lowest possible for this
2936 * combination of row, family, qualifier, and timestamp. This cell's own timestamp is ignored.
2937 * @param cell - cell
2940 public static Cell
createFirstOnRowColTS(Cell cell
, long ts
) {
2941 if (cell
instanceof ByteBufferExtendedCell
) {
2942 return new FirstOnRowColTSByteBufferExtendedCell(
2943 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2944 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2945 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2946 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2947 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2948 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength(), ts
);
2950 return new FirstOnRowColTSCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2951 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2952 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength(), ts
);
2956 * Create a Cell that is larger than all other possible Cells for the given Cell's row.
2958 * @return Last possible Cell on passed Cell's row.
2960 public static Cell
createLastOnRow(final Cell cell
) {
2961 if (cell
instanceof ByteBufferExtendedCell
) {
2962 return new LastOnRowByteBufferExtendedCell(((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2963 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength());
2965 return new LastOnRowCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
2968 public static Cell
createLastOnRow(final byte[] row
) {
2969 return new LastOnRowCell(row
, 0, (short) row
.length
);
2973 * Create a Cell that is larger than all other possible Cells for the given Cell's rk:cf:q. Used
2974 * in creating "fake keys" for the multi-column Bloom filter optimization to skip the row/column
2975 * we already know is not in the file.
2977 * @return Last possible Cell on passed Cell's rk:cf:q.
2979 public static Cell
createLastOnRowCol(final Cell cell
) {
2980 if (cell
instanceof ByteBufferExtendedCell
) {
2981 return new LastOnRowColByteBufferExtendedCell(
2982 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2983 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2984 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2985 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2986 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2987 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength());
2989 return new LastOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2990 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2991 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength());
2995 * Create a Delete Family Cell for the specified row and family that would be smaller than all
2996 * other possible Delete Family KeyValues that have the same row and family. Used for seeking.
2997 * @param row - row key (arbitrary byte array)
2998 * @param fam - family name
2999 * @return First Delete Family possible key on passed <code>row</code>.
3001 public static Cell
createFirstDeleteFamilyCellOnRow(final byte[] row
, final byte[] fam
) {
3002 return new FirstOnRowDeleteFamilyCell(row
, fam
);