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
;
43 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.annotations
.VisibleForTesting
;
46 * Utility methods helpful slinging {@link Cell} instances. It has more powerful and
47 * rich set of APIs than those in {@link CellUtil} for internal usage.
49 @InterfaceAudience.Private
50 public final class PrivateCellUtil
{
53 * Private constructor to keep this class from being instantiated.
55 private PrivateCellUtil() {
58 /******************* ByteRange *******************************/
60 public static ByteRange
fillRowRange(Cell cell
, ByteRange range
) {
61 return range
.set(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
64 public static ByteRange
fillFamilyRange(Cell cell
, ByteRange range
) {
65 return range
.set(cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength());
68 public static ByteRange
fillQualifierRange(Cell cell
, ByteRange range
) {
69 return range
.set(cell
.getQualifierArray(), cell
.getQualifierOffset(),
70 cell
.getQualifierLength());
73 public static ByteRange
fillValueRange(Cell cell
, ByteRange range
) {
74 return range
.set(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
77 public static ByteRange
fillTagRange(Cell cell
, ByteRange range
) {
78 return range
.set(cell
.getTagsArray(), cell
.getTagsOffset(), cell
.getTagsLength());
81 /********************* misc *************************************/
83 public static byte getRowByte(Cell cell
, int index
) {
84 if (cell
instanceof ByteBufferExtendedCell
) {
85 return ((ByteBufferExtendedCell
) cell
).getRowByteBuffer()
86 .get(((ByteBufferExtendedCell
) cell
).getRowPosition() + index
);
88 return cell
.getRowArray()[cell
.getRowOffset() + index
];
91 public static byte getQualifierByte(Cell cell
, int index
) {
92 if (cell
instanceof ByteBufferExtendedCell
) {
93 return ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer()
94 .get(((ByteBufferExtendedCell
) cell
).getQualifierPosition() + index
);
96 return cell
.getQualifierArray()[cell
.getQualifierOffset() + index
];
99 public static ByteBuffer
getValueBufferShallowCopy(Cell cell
) {
101 ByteBuffer
.wrap(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
106 * @return A new cell which is having the extra tags also added to it.
108 public static Cell
createCell(Cell cell
, List
<Tag
> tags
) {
109 return createCell(cell
, TagUtil
.fromList(tags
));
113 * @return A new cell which is having the extra tags also added to it.
115 public static Cell
createCell(Cell cell
, byte[] tags
) {
116 if (cell
instanceof ByteBufferExtendedCell
) {
117 return new TagRewriteByteBufferExtendedCell((ByteBufferExtendedCell
) cell
, tags
);
119 return new TagRewriteCell(cell
, tags
);
122 public static Cell
createCell(Cell cell
, byte[] value
, byte[] tags
) {
123 if (cell
instanceof ByteBufferExtendedCell
) {
124 return new ValueAndTagRewriteByteBufferExtendedCell((ByteBufferExtendedCell
) cell
,
127 return new ValueAndTagRewriteCell(cell
, value
, tags
);
131 * This can be used when a Cell has to change with addition/removal of one or more tags. This is
132 * an efficient way to do so in which only the tags bytes part need to recreated and copied. All
133 * other parts, refer to the original Cell.
135 static class TagRewriteCell
implements ExtendedCell
{
137 protected byte[] tags
;
138 private static final int HEAP_SIZE_OVERHEAD
= ClassSize
.OBJECT
+ 2 * ClassSize
.REFERENCE
;
141 * @param cell The original Cell which it rewrites
142 * @param tags the tags bytes. The array suppose to contain the tags bytes alone.
144 public TagRewriteCell(Cell cell
, byte[] tags
) {
145 assert cell
instanceof ExtendedCell
;
149 // tag offset will be treated as 0 and length this.tags.length
150 if (this.cell
instanceof TagRewriteCell
) {
151 // Cleaning the ref so that the byte[] can be GCed
152 ((TagRewriteCell
) this.cell
).tags
= null;
157 public byte[] getRowArray() {
158 return cell
.getRowArray();
162 public int getRowOffset() {
163 return cell
.getRowOffset();
167 public short getRowLength() {
168 return cell
.getRowLength();
172 public byte[] getFamilyArray() {
173 return cell
.getFamilyArray();
177 public int getFamilyOffset() {
178 return cell
.getFamilyOffset();
182 public byte getFamilyLength() {
183 return cell
.getFamilyLength();
187 public byte[] getQualifierArray() {
188 return cell
.getQualifierArray();
192 public int getQualifierOffset() {
193 return cell
.getQualifierOffset();
197 public int getQualifierLength() {
198 return cell
.getQualifierLength();
202 public long getTimestamp() {
203 return cell
.getTimestamp();
207 public byte getTypeByte() {
208 return cell
.getTypeByte();
212 public long getSequenceId() {
213 return cell
.getSequenceId();
217 public byte[] getValueArray() {
218 return cell
.getValueArray();
222 public int getValueOffset() {
223 return cell
.getValueOffset();
227 public int getValueLength() {
228 return cell
.getValueLength();
232 public byte[] getTagsArray() {
237 public int getTagsOffset() {
242 public int getTagsLength() {
243 if (null == this.tags
) {
244 // Nulled out tags array optimization in constructor
247 return this.tags
.length
;
251 public long heapSize() {
252 long sum
= HEAP_SIZE_OVERHEAD
+ cell
.heapSize();
253 if (this.tags
!= null) {
254 sum
+= ClassSize
.sizeOf(this.tags
);
260 public void setTimestamp(long ts
) throws IOException
{
261 // The incoming cell is supposed to be ExtendedCell type.
262 PrivateCellUtil
.setTimestamp(cell
, ts
);
266 public void setTimestamp(byte[] ts
) throws IOException
{
267 // The incoming cell is supposed to be ExtendedCell type.
268 PrivateCellUtil
.setTimestamp(cell
, ts
);
272 public void setSequenceId(long seqId
) throws IOException
{
273 // The incoming cell is supposed to be ExtendedCell type.
274 PrivateCellUtil
.setSequenceId(cell
, seqId
);
278 public int write(OutputStream out
, boolean withTags
) throws IOException
{
279 int len
= ((ExtendedCell
) this.cell
).write(out
, false);
280 if (withTags
&& this.tags
!= null) {
281 // Write the tagsLength 2 bytes
282 out
.write((byte) (0xff & (this.tags
.length
>> 8)));
283 out
.write((byte) (0xff & this.tags
.length
));
284 out
.write(this.tags
);
285 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
291 public int getSerializedSize(boolean withTags
) {
292 int len
= ((ExtendedCell
) this.cell
).getSerializedSize(false);
293 if (withTags
&& this.tags
!= null) {
294 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
300 public void write(ByteBuffer buf
, int offset
) {
301 offset
= KeyValueUtil
.appendTo(this.cell
, buf
, offset
, false);
302 int tagsLen
= this.tags
== null ?
0 : this.tags
.length
;
304 offset
= ByteBufferUtils
.putAsShort(buf
, offset
, tagsLen
);
305 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, this.tags
, 0, tagsLen
);
310 public ExtendedCell
deepClone() {
311 Cell clonedBaseCell
= ((ExtendedCell
) this.cell
).deepClone();
312 return new TagRewriteCell(clonedBaseCell
, this.tags
);
316 static class TagRewriteByteBufferExtendedCell
extends ByteBufferExtendedCell
{
318 protected ByteBufferExtendedCell cell
;
319 protected byte[] tags
;
320 private static final int HEAP_SIZE_OVERHEAD
= ClassSize
.OBJECT
+ 2 * ClassSize
.REFERENCE
;
323 * @param cell The original ByteBufferExtendedCell which it rewrites
324 * @param tags the tags bytes. The array suppose to contain the tags bytes alone.
326 public TagRewriteByteBufferExtendedCell(ByteBufferExtendedCell cell
, byte[] tags
) {
330 // tag offset will be treated as 0 and length this.tags.length
331 if (this.cell
instanceof TagRewriteByteBufferExtendedCell
) {
332 // Cleaning the ref so that the byte[] can be GCed
333 ((TagRewriteByteBufferExtendedCell
) this.cell
).tags
= null;
338 public byte[] getRowArray() {
339 return this.cell
.getRowArray();
343 public int getRowOffset() {
344 return this.cell
.getRowOffset();
348 public short getRowLength() {
349 return this.cell
.getRowLength();
353 public byte[] getFamilyArray() {
354 return this.cell
.getFamilyArray();
358 public int getFamilyOffset() {
359 return this.cell
.getFamilyOffset();
363 public byte getFamilyLength() {
364 return this.cell
.getFamilyLength();
368 public byte[] getQualifierArray() {
369 return this.cell
.getQualifierArray();
373 public int getQualifierOffset() {
374 return this.cell
.getQualifierOffset();
378 public int getQualifierLength() {
379 return this.cell
.getQualifierLength();
383 public long getTimestamp() {
384 return this.cell
.getTimestamp();
388 public byte getTypeByte() {
389 return this.cell
.getTypeByte();
393 public long getSequenceId() {
394 return this.cell
.getSequenceId();
398 public byte[] getValueArray() {
399 return this.cell
.getValueArray();
403 public int getValueOffset() {
404 return this.cell
.getValueOffset();
408 public int getValueLength() {
409 return this.cell
.getValueLength();
413 public byte[] getTagsArray() {
418 public int getTagsOffset() {
423 public int getTagsLength() {
424 if (null == this.tags
) {
425 // Nulled out tags array optimization in constructor
428 return this.tags
.length
;
432 public void setSequenceId(long seqId
) throws IOException
{
433 PrivateCellUtil
.setSequenceId(this.cell
, seqId
);
437 public void setTimestamp(long ts
) throws IOException
{
438 PrivateCellUtil
.setTimestamp(this.cell
, ts
);
442 public void setTimestamp(byte[] ts
) throws IOException
{
443 PrivateCellUtil
.setTimestamp(this.cell
, ts
);
447 public long heapSize() {
448 long sum
= HEAP_SIZE_OVERHEAD
+ cell
.heapSize();
449 // this.tags is on heap byte[]
450 if (this.tags
!= null) {
451 sum
+= ClassSize
.sizeOf(this.tags
);
457 public int write(OutputStream out
, boolean withTags
) throws IOException
{
458 int len
= ((ExtendedCell
) this.cell
).write(out
, false);
459 if (withTags
&& this.tags
!= null) {
460 // Write the tagsLength 2 bytes
461 out
.write((byte) (0xff & (this.tags
.length
>> 8)));
462 out
.write((byte) (0xff & this.tags
.length
));
463 out
.write(this.tags
);
464 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
470 public int getSerializedSize(boolean withTags
) {
471 int len
= ((ExtendedCell
) this.cell
).getSerializedSize(false);
472 if (withTags
&& this.tags
!= null) {
473 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ this.tags
.length
;
479 public void write(ByteBuffer buf
, int offset
) {
480 offset
= KeyValueUtil
.appendTo(this.cell
, buf
, offset
, false);
481 int tagsLen
= this.tags
== null ?
0 : this.tags
.length
;
483 offset
= ByteBufferUtils
.putAsShort(buf
, offset
, tagsLen
);
484 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, this.tags
, 0, tagsLen
);
489 public ExtendedCell
deepClone() {
490 Cell clonedBaseCell
= ((ExtendedCell
) this.cell
).deepClone();
491 if (clonedBaseCell
instanceof ByteBufferExtendedCell
) {
492 return new TagRewriteByteBufferExtendedCell((ByteBufferExtendedCell
) clonedBaseCell
,
495 return new TagRewriteCell(clonedBaseCell
, this.tags
);
499 public ByteBuffer
getRowByteBuffer() {
500 return this.cell
.getRowByteBuffer();
504 public int getRowPosition() {
505 return this.cell
.getRowPosition();
509 public ByteBuffer
getFamilyByteBuffer() {
510 return this.cell
.getFamilyByteBuffer();
514 public int getFamilyPosition() {
515 return this.cell
.getFamilyPosition();
519 public ByteBuffer
getQualifierByteBuffer() {
520 return this.cell
.getQualifierByteBuffer();
524 public int getQualifierPosition() {
525 return this.cell
.getQualifierPosition();
529 public ByteBuffer
getValueByteBuffer() {
530 return this.cell
.getValueByteBuffer();
534 public int getValuePosition() {
535 return this.cell
.getValuePosition();
539 public ByteBuffer
getTagsByteBuffer() {
540 return this.tags
== null ? HConstants
.EMPTY_BYTE_BUFFER
: ByteBuffer
.wrap(this.tags
);
544 public int getTagsPosition() {
549 static class ValueAndTagRewriteCell
extends TagRewriteCell
{
551 protected byte[] value
;
553 public ValueAndTagRewriteCell(Cell cell
, byte[] value
, byte[] tags
) {
559 public byte[] getValueArray() {
564 public int getValueOffset() {
569 public int getValueLength() {
570 return this.value
== null ?
0 : this.value
.length
;
574 public long heapSize() {
575 long sum
= ClassSize
.REFERENCE
+ super.heapSize();
576 if (this.value
!= null) {
577 sum
+= ClassSize
.sizeOf(this.value
);
583 public int write(OutputStream out
, boolean withTags
) throws IOException
{
584 return write(out
, withTags
, this.cell
, this.value
, this.tags
);
588 * Made into a static method so as to reuse the logic within
589 * ValueAndTagRewriteByteBufferExtendedCell
591 static int write(OutputStream out
, boolean withTags
, Cell cell
, byte[] value
, byte[] tags
)
593 int valLen
= value
== null ?
0 : value
.length
;
594 ByteBufferUtils
.putInt(out
, KeyValueUtil
.keyLength(cell
));// Key length
595 ByteBufferUtils
.putInt(out
, valLen
);// Value length
596 int len
= 2 * Bytes
.SIZEOF_INT
;
597 len
+= writeFlatKey(cell
, out
);// Key
599 out
.write(value
);// Value
602 if (withTags
&& tags
!= null) {
603 // Write the tagsLength 2 bytes
604 out
.write((byte) (0xff & (tags
.length
>> 8)));
605 out
.write((byte) (0xff & tags
.length
));
607 len
+= KeyValue
.TAGS_LENGTH_SIZE
+ tags
.length
;
613 public int getSerializedSize(boolean withTags
) {
614 return super.getSerializedSize(withTags
) - this.cell
.getValueLength() + this.value
.length
;
618 public void write(ByteBuffer buf
, int offset
) {
619 write(buf
, offset
, this.cell
, this.value
, this.tags
);
623 * Made into a static method so as to reuse the logic
624 * within ValueAndTagRewriteByteBufferExtendedCell
626 static void write(ByteBuffer buf
, int offset
, Cell cell
, byte[] value
, byte[] tags
) {
627 offset
= ByteBufferUtils
.putInt(buf
, offset
, KeyValueUtil
.keyLength(cell
));// Key length
628 offset
= ByteBufferUtils
.putInt(buf
, offset
, value
.length
);// Value length
629 offset
= KeyValueUtil
.appendKeyTo(cell
, buf
, offset
);
630 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, value
, 0, value
.length
);
631 offset
+= value
.length
;
632 int tagsLen
= tags
== null ?
0 : tags
.length
;
634 offset
= ByteBufferUtils
.putAsShort(buf
, offset
, tagsLen
);
635 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, tags
, 0, tagsLen
);
640 public ExtendedCell
deepClone() {
641 Cell clonedBaseCell
= ((ExtendedCell
) this.cell
).deepClone();
642 return new ValueAndTagRewriteCell(clonedBaseCell
, this.value
, this.tags
);
646 static class ValueAndTagRewriteByteBufferExtendedCell
extends TagRewriteByteBufferExtendedCell
{
648 protected byte[] value
;
650 public ValueAndTagRewriteByteBufferExtendedCell(ByteBufferExtendedCell cell
,
651 byte[] value
, byte[] tags
) {
657 public byte[] getValueArray() {
662 public int getValueOffset() {
667 public int getValueLength() {
668 return this.value
== null ?
0 : this.value
.length
;
672 public ByteBuffer
getValueByteBuffer() {
673 return ByteBuffer
.wrap(this.value
);
677 public int getValuePosition() {
682 public long heapSize() {
683 long sum
= ClassSize
.REFERENCE
+ super.heapSize();
684 if (this.value
!= null) {
685 sum
+= ClassSize
.sizeOf(this.value
);
691 public int write(OutputStream out
, boolean withTags
) throws IOException
{
692 return ValueAndTagRewriteCell
.write(out
, withTags
, this.cell
, this.value
, this.tags
);
696 public int getSerializedSize(boolean withTags
) {
697 return super.getSerializedSize(withTags
) - this.cell
.getValueLength() + this.value
.length
;
701 public void write(ByteBuffer buf
, int offset
) {
702 ValueAndTagRewriteCell
.write(buf
, offset
, this.cell
, this.value
, this.tags
);
706 public ExtendedCell
deepClone() {
707 Cell clonedBaseCell
= this.cell
.deepClone();
708 if (clonedBaseCell
instanceof ByteBufferExtendedCell
) {
709 return new ValueAndTagRewriteByteBufferExtendedCell(
710 (ByteBufferExtendedCell
) clonedBaseCell
, this.value
, this.tags
);
712 return new ValueAndTagRewriteCell(clonedBaseCell
, this.value
, this.tags
);
716 public static boolean matchingRows(final Cell left
, final byte[] buf
, final int offset
,
718 if (left
instanceof ByteBufferExtendedCell
) {
719 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getRowByteBuffer(),
720 ((ByteBufferExtendedCell
) left
).getRowPosition(), left
.getRowLength(),
721 buf
, offset
, length
);
723 return Bytes
.equals(left
.getRowArray(), left
.getRowOffset(), left
.getRowLength(), buf
, offset
,
727 public static boolean matchingFamily(final Cell left
, final byte[] buf
, final int offset
,
729 if (left
instanceof ByteBufferExtendedCell
) {
730 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getFamilyByteBuffer(),
731 ((ByteBufferExtendedCell
) left
).getFamilyPosition(), left
.getFamilyLength(),
732 buf
, offset
, length
);
734 return Bytes
.equals(left
.getFamilyArray(), left
.getFamilyOffset(), left
.getFamilyLength(), buf
,
739 * Finds if the qualifier part of the cell and the KV serialized byte[] are equal
740 * @param left the cell with which we need to match the qualifier
741 * @param buf the serialized keyvalue format byte[]
742 * @param offset the offset of the qualifier in the byte[]
743 * @param length the length of the qualifier in the byte[]
744 * @return true if the qualifier matches, false otherwise
746 public static boolean matchingQualifier(final Cell left
, final byte[] buf
, final int offset
,
749 return left
.getQualifierLength() == 0;
751 if (left
instanceof ByteBufferExtendedCell
) {
752 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getQualifierByteBuffer(),
753 ((ByteBufferExtendedCell
) left
).getQualifierPosition(), left
.getQualifierLength(),
754 buf
, offset
, length
);
756 return Bytes
.equals(left
.getQualifierArray(), left
.getQualifierOffset(),
757 left
.getQualifierLength(), buf
, offset
, length
);
761 * Finds if the start of the qualifier part of the Cell matches <code>buf</code>
762 * @param left the cell with which we need to match the qualifier
763 * @param startsWith the serialized keyvalue format byte[]
764 * @return true if the qualifier have same staring characters, false otherwise
766 public static boolean qualifierStartsWith(final Cell left
, final byte[] startsWith
) {
767 if (startsWith
== null || startsWith
.length
== 0) {
768 throw new IllegalArgumentException("Cannot pass an empty startsWith");
770 if (left
.getQualifierLength() < startsWith
.length
) {
773 if (left
instanceof ByteBufferExtendedCell
) {
774 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getQualifierByteBuffer(),
775 ((ByteBufferExtendedCell
) left
).getQualifierPosition(), startsWith
.length
,
776 startsWith
, 0, startsWith
.length
);
778 return Bytes
.equals(left
.getQualifierArray(), left
.getQualifierOffset(),
779 startsWith
.length
, startsWith
, 0, startsWith
.length
);
782 public static boolean matchingColumn(final Cell left
, final byte[] fam
, final int foffset
,
783 final int flength
, final byte[] qual
, final int qoffset
, final int qlength
) {
784 if (!matchingFamily(left
, fam
, foffset
, flength
)) {
787 return matchingQualifier(left
, qual
, qoffset
, qlength
);
790 public static boolean matchingValue(final Cell left
, final Cell right
, int lvlength
,
792 if (left
instanceof ByteBufferExtendedCell
&& right
instanceof ByteBufferExtendedCell
) {
793 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getValueByteBuffer(),
794 ((ByteBufferExtendedCell
) left
).getValuePosition(), lvlength
,
795 ((ByteBufferExtendedCell
) right
).getValueByteBuffer(),
796 ((ByteBufferExtendedCell
) right
).getValuePosition(), rvlength
);
798 if (left
instanceof ByteBufferExtendedCell
) {
799 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) left
).getValueByteBuffer(),
800 ((ByteBufferExtendedCell
) left
).getValuePosition(), lvlength
, right
.getValueArray(),
801 right
.getValueOffset(), rvlength
);
803 if (right
instanceof ByteBufferExtendedCell
) {
804 return ByteBufferUtils
.equals(((ByteBufferExtendedCell
) right
).getValueByteBuffer(),
805 ((ByteBufferExtendedCell
) right
).getValuePosition(), rvlength
, left
.getValueArray(),
806 left
.getValueOffset(), lvlength
);
809 .equals(left
.getValueArray(), left
.getValueOffset(), lvlength
, right
.getValueArray(),
810 right
.getValueOffset(), rvlength
);
813 public static boolean matchingType(Cell a
, Cell b
) {
814 return a
.getTypeByte() == b
.getTypeByte();
818 * @return True if a delete type, a {@link KeyValue.Type#Delete} or a {KeyValue.Type#DeleteFamily}
819 * or a {@link KeyValue.Type#DeleteColumn} KeyValue type.
821 public static boolean isDelete(final byte type
) {
822 return KeyValue
.Type
.Delete
.getCode() <= type
&& type
<= KeyValue
.Type
.DeleteFamily
.getCode();
826 * @return True if this cell is a {@link KeyValue.Type#Delete} type.
828 public static boolean isDeleteType(Cell cell
) {
829 return cell
.getTypeByte() == KeyValue
.Type
.Delete
.getCode();
832 public static boolean isDeleteFamily(final Cell cell
) {
833 return cell
.getTypeByte() == KeyValue
.Type
.DeleteFamily
.getCode();
836 public static boolean isDeleteFamilyVersion(final Cell cell
) {
837 return cell
.getTypeByte() == KeyValue
.Type
.DeleteFamilyVersion
.getCode();
840 public static boolean isDeleteColumns(final Cell cell
) {
841 return cell
.getTypeByte() == KeyValue
.Type
.DeleteColumn
.getCode();
844 public static boolean isDeleteColumnVersion(final Cell cell
) {
845 return cell
.getTypeByte() == KeyValue
.Type
.Delete
.getCode();
849 * @return True if this cell is a delete family or column type.
851 public static boolean isDeleteColumnOrFamily(Cell cell
) {
852 int t
= cell
.getTypeByte();
853 return t
== KeyValue
.Type
.DeleteColumn
.getCode() || t
== KeyValue
.Type
.DeleteFamily
.getCode();
856 public static byte[] cloneTags(Cell cell
) {
857 byte[] output
= new byte[cell
.getTagsLength()];
858 copyTagsTo(cell
, output
, 0);
863 * Copies the tags info into the tag portion of the cell
866 * @param destinationOffset
867 * @return position after tags
869 public static int copyTagsTo(Cell cell
, byte[] destination
, int destinationOffset
) {
870 int tlen
= cell
.getTagsLength();
871 if (cell
instanceof ByteBufferExtendedCell
) {
873 .copyFromBufferToArray(destination
, ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
874 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), destinationOffset
, tlen
);
877 .arraycopy(cell
.getTagsArray(), cell
.getTagsOffset(), destination
, destinationOffset
, tlen
);
879 return destinationOffset
+ tlen
;
883 * Copies the tags info into the tag portion of the cell
886 * @param destinationOffset
887 * @return the position after tags
889 public static int copyTagsTo(Cell cell
, ByteBuffer destination
, int destinationOffset
) {
890 int tlen
= cell
.getTagsLength();
891 if (cell
instanceof ByteBufferExtendedCell
) {
892 ByteBufferUtils
.copyFromBufferToBuffer(((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
893 destination
, ((ByteBufferExtendedCell
) cell
).getTagsPosition(), destinationOffset
, tlen
);
895 ByteBufferUtils
.copyFromArrayToBuffer(destination
, destinationOffset
, cell
.getTagsArray(),
896 cell
.getTagsOffset(), tlen
);
898 return destinationOffset
+ tlen
;
902 * @param cell The Cell
903 * @return Tags in the given Cell as a List
905 public static List
<Tag
> getTags(Cell cell
) {
906 List
<Tag
> tags
= new ArrayList
<>();
907 Iterator
<Tag
> tagsItr
= tagsIterator(cell
);
908 while (tagsItr
.hasNext()) {
909 tags
.add(tagsItr
.next());
915 * Retrieve Cell's first tag, matching the passed in type
916 * @param cell The Cell
917 * @param type Type of the Tag to retrieve
918 * @return null if there is no tag of the passed in tag type
920 public static Optional
<Tag
> getTag(Cell cell
, byte type
) {
921 boolean bufferBacked
= cell
instanceof ByteBufferExtendedCell
;
922 int length
= cell
.getTagsLength();
924 bufferBacked ?
((ByteBufferExtendedCell
) cell
).getTagsPosition() : cell
.getTagsOffset();
926 while (pos
< offset
+ length
) {
929 ByteBuffer tagsBuffer
= ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer();
930 tagLen
= ByteBufferUtils
.readAsInt(tagsBuffer
, pos
, TAG_LENGTH_SIZE
);
931 if (ByteBufferUtils
.toByte(tagsBuffer
, pos
+ TAG_LENGTH_SIZE
) == type
) {
932 return Optional
.of(new ByteBufferTag(tagsBuffer
, pos
, tagLen
+ TAG_LENGTH_SIZE
));
935 tagLen
= Bytes
.readAsInt(cell
.getTagsArray(), pos
, TAG_LENGTH_SIZE
);
936 if (cell
.getTagsArray()[pos
+ TAG_LENGTH_SIZE
] == type
) {
938 .of(new ArrayBackedTag(cell
.getTagsArray(), pos
, tagLen
+ TAG_LENGTH_SIZE
));
941 pos
+= TAG_LENGTH_SIZE
+ tagLen
;
943 return Optional
.empty();
947 * Util method to iterate through the tags in the given cell.
948 * @param cell The Cell over which tags iterator is needed.
949 * @return iterator for the tags
951 public static Iterator
<Tag
> tagsIterator(final Cell cell
) {
952 final int tagsLength
= cell
.getTagsLength();
953 // Save an object allocation where we can
954 if (tagsLength
== 0) {
955 return TagUtil
.EMPTY_TAGS_ITR
;
957 if (cell
instanceof ByteBufferExtendedCell
) {
958 return tagsIterator(((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
959 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), tagsLength
);
962 return new Iterator
<Tag
>() {
963 private int offset
= cell
.getTagsOffset();
964 private int pos
= offset
;
965 private int endOffset
= offset
+ cell
.getTagsLength() - 1;
968 public boolean hasNext() {
969 return this.pos
< endOffset
;
975 byte[] tags
= cell
.getTagsArray();
976 int curTagLen
= Bytes
.readAsInt(tags
, this.pos
, Tag
.TAG_LENGTH_SIZE
);
977 Tag tag
= new ArrayBackedTag(tags
, pos
, curTagLen
+ TAG_LENGTH_SIZE
);
978 this.pos
+= Bytes
.SIZEOF_SHORT
+ curTagLen
;
985 public void remove() {
986 throw new UnsupportedOperationException();
991 public static Iterator
<Tag
> tagsIterator(final ByteBuffer tags
, final int offset
,
993 return new Iterator
<Tag
>() {
994 private int pos
= offset
;
995 private int endOffset
= offset
+ length
- 1;
998 public boolean hasNext() {
999 return this.pos
< endOffset
;
1005 int curTagLen
= ByteBufferUtils
.readAsInt(tags
, this.pos
, Tag
.TAG_LENGTH_SIZE
);
1006 Tag tag
= new ByteBufferTag(tags
, pos
, curTagLen
+ Tag
.TAG_LENGTH_SIZE
);
1007 this.pos
+= Bytes
.SIZEOF_SHORT
+ curTagLen
;
1014 public void remove() {
1015 throw new UnsupportedOperationException();
1021 * Returns true if the first range start1...end1 overlaps with the second range start2...end2,
1022 * assuming the byte arrays represent row keys
1024 public static boolean overlappingKeys(final byte[] start1
, final byte[] end1
, final byte[] start2
,
1025 final byte[] end2
) {
1026 return (end2
.length
== 0 || start1
.length
== 0 || Bytes
.compareTo(start1
, end2
) < 0)
1027 && (end1
.length
== 0 || start2
.length
== 0 || Bytes
.compareTo(start2
, end1
) < 0);
1031 * Write rowkey excluding the common part.
1034 * @param commonPrefix
1036 * @throws IOException
1038 public static void writeRowKeyExcludingCommon(Cell cell
, short rLen
, int commonPrefix
,
1039 DataOutputStream out
) throws IOException
{
1040 if (commonPrefix
== 0) {
1041 out
.writeShort(rLen
);
1042 } else if (commonPrefix
== 1) {
1043 out
.writeByte((byte) rLen
);
1046 commonPrefix
-= KeyValue
.ROW_LENGTH_SIZE
;
1048 if (rLen
> commonPrefix
) {
1049 writeRowSkippingBytes(out
, cell
, rLen
, commonPrefix
);
1054 * Writes the row from the given cell to the output stream excluding the common prefix
1055 * @param out The dataoutputstream to which the data has to be written
1056 * @param cell The cell whose contents has to be written
1057 * @param rlength the row length
1058 * @throws IOException
1060 public static void writeRowSkippingBytes(DataOutputStream out
, Cell cell
, short rlength
,
1061 int commonPrefix
) throws IOException
{
1062 if (cell
instanceof ByteBufferExtendedCell
) {
1064 .copyBufferToStream((DataOutput
) out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
1065 ((ByteBufferExtendedCell
) cell
).getRowPosition() + commonPrefix
,
1066 rlength
- commonPrefix
);
1068 out
.write(cell
.getRowArray(), cell
.getRowOffset() + commonPrefix
, rlength
- commonPrefix
);
1073 * Find length of common prefix in keys of the cells, considering key as byte[] if serialized in
1074 * {@link KeyValue}. The key format is <2 bytes rk len><rk><1 byte cf
1075 * len><cf><qualifier><8 bytes timestamp><1 byte type>
1076 * @param c1 the cell
1077 * @param c2 the cell
1078 * @param bypassFamilyCheck when true assume the family bytes same in both cells. Pass it as true
1079 * when dealing with Cells in same CF so as to avoid some checks
1080 * @param withTsType when true check timestamp and type bytes also.
1081 * @return length of common prefix
1083 public static int findCommonPrefixInFlatKey(Cell c1
, Cell c2
, boolean bypassFamilyCheck
,
1084 boolean withTsType
) {
1085 // Compare the 2 bytes in RK length part
1086 short rLen1
= c1
.getRowLength();
1087 short rLen2
= c2
.getRowLength();
1088 int commonPrefix
= KeyValue
.ROW_LENGTH_SIZE
;
1089 if (rLen1
!= rLen2
) {
1090 // early out when the RK length itself is not matching
1091 return ByteBufferUtils
1092 .findCommonPrefix(Bytes
.toBytes(rLen1
), 0, KeyValue
.ROW_LENGTH_SIZE
, Bytes
.toBytes(rLen2
),
1093 0, KeyValue
.ROW_LENGTH_SIZE
);
1096 int rkCommonPrefix
= 0;
1097 if (c1
instanceof ByteBufferExtendedCell
&& c2
instanceof ByteBufferExtendedCell
) {
1098 rkCommonPrefix
= ByteBufferUtils
1099 .findCommonPrefix(((ByteBufferExtendedCell
) c1
).getRowByteBuffer(),
1100 ((ByteBufferExtendedCell
) c1
).getRowPosition(), rLen1
,
1101 ((ByteBufferExtendedCell
) c2
).getRowByteBuffer(),
1102 ((ByteBufferExtendedCell
) c2
).getRowPosition(), rLen2
);
1104 // There cannot be a case where one cell is BBCell and other is KeyValue. This flow comes
1106 // in flush or compactions. In flushes both cells are KV and in case of compaction it will be
1109 rkCommonPrefix
= ByteBufferUtils
1110 .findCommonPrefix(c1
.getRowArray(), c1
.getRowOffset(), rLen1
, c2
.getRowArray(),
1111 c2
.getRowOffset(), rLen2
);
1113 commonPrefix
+= rkCommonPrefix
;
1114 if (rkCommonPrefix
!= rLen1
) {
1115 // Early out when RK is not fully matching.
1116 return commonPrefix
;
1118 // Compare 1 byte CF length part
1119 byte fLen1
= c1
.getFamilyLength();
1120 if (bypassFamilyCheck
) {
1121 // This flag will be true when caller is sure that the family will be same for both the cells
1122 // Just make commonPrefix to increment by the family part
1123 commonPrefix
+= KeyValue
.FAMILY_LENGTH_SIZE
+ fLen1
;
1125 byte fLen2
= c2
.getFamilyLength();
1126 if (fLen1
!= fLen2
) {
1127 // early out when the CF length itself is not matching
1128 return commonPrefix
;
1130 // CF lengths are same so there is one more byte common in key part
1131 commonPrefix
+= KeyValue
.FAMILY_LENGTH_SIZE
;
1132 // Compare the CF names
1134 if (c1
instanceof ByteBufferExtendedCell
&& c2
instanceof ByteBufferExtendedCell
) {
1135 fCommonPrefix
= ByteBufferUtils
1136 .findCommonPrefix(((ByteBufferExtendedCell
) c1
).getFamilyByteBuffer(),
1137 ((ByteBufferExtendedCell
) c1
).getFamilyPosition(), fLen1
,
1138 ((ByteBufferExtendedCell
) c2
).getFamilyByteBuffer(),
1139 ((ByteBufferExtendedCell
) c2
).getFamilyPosition(), fLen2
);
1141 fCommonPrefix
= ByteBufferUtils
1142 .findCommonPrefix(c1
.getFamilyArray(), c1
.getFamilyOffset(), fLen1
, c2
.getFamilyArray(),
1143 c2
.getFamilyOffset(), fLen2
);
1145 commonPrefix
+= fCommonPrefix
;
1146 if (fCommonPrefix
!= fLen1
) {
1147 return commonPrefix
;
1150 // Compare the Qualifiers
1151 int qLen1
= c1
.getQualifierLength();
1152 int qLen2
= c2
.getQualifierLength();
1154 if (c1
instanceof ByteBufferExtendedCell
&& c2
instanceof ByteBufferExtendedCell
) {
1155 qCommon
= ByteBufferUtils
1156 .findCommonPrefix(((ByteBufferExtendedCell
) c1
).getQualifierByteBuffer(),
1157 ((ByteBufferExtendedCell
) c1
).getQualifierPosition(), qLen1
,
1158 ((ByteBufferExtendedCell
) c2
).getQualifierByteBuffer(),
1159 ((ByteBufferExtendedCell
) c2
).getQualifierPosition(), qLen2
);
1161 qCommon
= ByteBufferUtils
1162 .findCommonPrefix(c1
.getQualifierArray(), c1
.getQualifierOffset(), qLen1
,
1163 c2
.getQualifierArray(), c2
.getQualifierOffset(), qLen2
);
1165 commonPrefix
+= qCommon
;
1166 if (!withTsType
|| Math
.max(qLen1
, qLen2
) != qCommon
) {
1167 return commonPrefix
;
1169 // Compare the timestamp parts
1170 int tsCommonPrefix
= ByteBufferUtils
1171 .findCommonPrefix(Bytes
.toBytes(c1
.getTimestamp()), 0, KeyValue
.TIMESTAMP_SIZE
,
1172 Bytes
.toBytes(c2
.getTimestamp()), 0, KeyValue
.TIMESTAMP_SIZE
);
1173 commonPrefix
+= tsCommonPrefix
;
1174 if (tsCommonPrefix
!= KeyValue
.TIMESTAMP_SIZE
) {
1175 return commonPrefix
;
1178 if (c1
.getTypeByte() == c2
.getTypeByte()) {
1179 commonPrefix
+= KeyValue
.TYPE_SIZE
;
1181 return commonPrefix
;
1185 * Used to compare two cells based on the column hint provided. This is specifically used when we
1186 * need to optimize the seeks based on the next indexed key. This is an advanced usage API
1187 * specifically needed for some optimizations.
1188 * @param nextIndexedCell the next indexed cell
1189 * @param currentCell the cell to be compared
1190 * @param foff the family offset of the currentCell
1191 * @param flen the family length of the currentCell
1192 * @param colHint the column hint provided - could be null
1193 * @param coff the offset of the column hint if provided, if not offset of the currentCell's
1195 * @param clen the length of the column hint if provided, if not length of the currentCell's
1197 * @param ts the timestamp to be seeked
1198 * @param type the type to be seeked
1199 * @return an int based on the given column hint TODO : To be moved out of here because this is a
1200 * special API used in scan optimization.
1202 // compare a key against row/fam/qual/ts/type
1203 public static final int compareKeyBasedOnColHint(CellComparator comparator
, Cell nextIndexedCell
,
1204 Cell currentCell
, int foff
, int flen
, byte[] colHint
, int coff
, int clen
, long ts
,
1206 int compare
= comparator
.compareRows(nextIndexedCell
, currentCell
);
1210 // If the column is not specified, the "minimum" key type appears the
1211 // latest in the sorted order, regardless of the timestamp. This is used
1212 // for specifying the last key/value in a given row, because there is no
1213 // "lexicographically last column" (it would be infinitely long). The
1214 // "maximum" key type does not need this behavior.
1215 if (nextIndexedCell
.getFamilyLength() + nextIndexedCell
.getQualifierLength() == 0
1216 && nextIndexedCell
.getTypeByte() == KeyValue
.Type
.Minimum
.getCode()) {
1217 // left is "bigger", i.e. it appears later in the sorted order
1220 if (flen
+ clen
== 0 && type
== KeyValue
.Type
.Minimum
.getCode()) {
1224 compare
= comparator
.compareFamilies(nextIndexedCell
, currentCell
);
1228 if (colHint
== null) {
1229 compare
= comparator
.compareQualifiers(nextIndexedCell
, currentCell
);
1231 compare
= CellUtil
.compareQualifiers(nextIndexedCell
, colHint
, coff
, clen
);
1236 // Next compare timestamps.
1237 compare
= comparator
.compareTimestamps(nextIndexedCell
.getTimestamp(), ts
);
1242 // Compare types. Let the delete types sort ahead of puts; i.e. types
1243 // of higher numbers sort before those of lesser numbers. Maximum (255)
1244 // appears ahead of everything, and minimum (0) appears after
1246 return (0xff & type
) - (0xff & nextIndexedCell
.getTypeByte());
1250 * Compares only the key portion of a cell. It does not include the sequence id/mvcc of the cell
1253 * @return an int greater than 0 if left > than right lesser than 0 if left < than right
1254 * equal to 0 if left is equal to right
1256 public static final int compareKeyIgnoresMvcc(CellComparator comparator
, Cell left
, Cell right
) {
1257 return ((CellComparatorImpl
) comparator
).compare(left
, right
, true);
1261 * Compare cell's row against given comparator
1262 * @param cell the cell to use for comparison
1263 * @param comparator the {@link CellComparator} to use for comparison
1264 * @return result comparing cell's row
1266 public static int compareRow(Cell cell
, ByteArrayComparable comparator
) {
1267 if (cell
instanceof ByteBufferExtendedCell
) {
1268 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
1269 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength());
1271 return comparator
.compareTo(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
1275 * Compare cell's column family against given comparator
1276 * @param cell the cell to use for comparison
1277 * @param comparator the {@link CellComparator} to use for comparison
1278 * @return result comparing cell's column family
1280 public static int compareFamily(Cell cell
, ByteArrayComparable comparator
) {
1281 if (cell
instanceof ByteBufferExtendedCell
) {
1282 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
1283 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength());
1285 return comparator
.compareTo(cell
.getFamilyArray(), cell
.getFamilyOffset(),
1286 cell
.getFamilyLength());
1290 * Compare cell's qualifier against given comparator
1291 * @param cell the cell to use for comparison
1292 * @param comparator the {@link CellComparator} to use for comparison
1293 * @return result comparing cell's qualifier
1295 public static int compareQualifier(Cell cell
, ByteArrayComparable comparator
) {
1296 if (cell
instanceof ByteBufferExtendedCell
) {
1297 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
1298 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength());
1300 return comparator
.compareTo(cell
.getQualifierArray(), cell
.getQualifierOffset(),
1301 cell
.getQualifierLength());
1304 public static Cell
.Type
toType(byte type
) {
1305 KeyValue
.Type codeToType
= KeyValue
.Type
.codeToType(type
);
1306 switch (codeToType
) {
1307 case Put
: return Cell
.Type
.Put
;
1308 case Delete
: return Cell
.Type
.Delete
;
1309 case DeleteColumn
: return Cell
.Type
.DeleteColumn
;
1310 case DeleteFamily
: return Cell
.Type
.DeleteFamily
;
1311 case DeleteFamilyVersion
: return Cell
.Type
.DeleteFamilyVersion
;
1312 default: throw new UnsupportedOperationException("Invalid type of cell "+type
);
1316 public static KeyValue
.Type
toTypeByte(Cell
.Type type
) {
1318 case Put
: return KeyValue
.Type
.Put
;
1319 case Delete
: return KeyValue
.Type
.Delete
;
1320 case DeleteColumn
: return KeyValue
.Type
.DeleteColumn
;
1321 case DeleteFamilyVersion
: return KeyValue
.Type
.DeleteFamilyVersion
;
1322 case DeleteFamily
: return KeyValue
.Type
.DeleteFamily
;
1323 default: throw new UnsupportedOperationException("Unsupported data type:" + type
);
1328 * Compare cell's value against given comparator
1329 * @param cell the cell to use for comparison
1330 * @param comparator the {@link CellComparator} to use for comparison
1331 * @return result comparing cell's value
1333 public static int compareValue(Cell cell
, ByteArrayComparable comparator
) {
1334 if (cell
instanceof ByteBufferExtendedCell
) {
1335 return comparator
.compareTo(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
1336 ((ByteBufferExtendedCell
) cell
).getValuePosition(), cell
.getValueLength());
1338 return comparator
.compareTo(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
1342 * These cells are used in reseeks/seeks to improve the read performance. They are not real cells
1343 * that are returned back to the clients
1345 private static abstract class EmptyCell
implements ExtendedCell
{
1348 public void setSequenceId(long seqId
) {
1349 // Fake cells don't need seqId, so leaving it as a noop.
1353 public void setTimestamp(long ts
) {
1354 // Fake cells can't be changed timestamp, so leaving it as a noop.
1358 public void setTimestamp(byte[] ts
) {
1359 // Fake cells can't be changed timestamp, so leaving it as a noop.
1363 public byte[] getRowArray() {
1364 return EMPTY_BYTE_ARRAY
;
1368 public int getRowOffset() {
1373 public short getRowLength() {
1378 public byte[] getFamilyArray() {
1379 return EMPTY_BYTE_ARRAY
;
1383 public int getFamilyOffset() {
1388 public byte getFamilyLength() {
1393 public byte[] getQualifierArray() {
1394 return EMPTY_BYTE_ARRAY
;
1398 public int getQualifierOffset() {
1403 public int getQualifierLength() {
1408 public long getSequenceId() {
1413 public byte[] getValueArray() {
1414 return EMPTY_BYTE_ARRAY
;
1418 public int getValueOffset() {
1423 public int getValueLength() {
1428 public byte[] getTagsArray() {
1429 return EMPTY_BYTE_ARRAY
;
1433 public int getTagsOffset() {
1438 public int getTagsLength() {
1444 * These cells are used in reseeks/seeks to improve the read performance. They are not real cells
1445 * that are returned back to the clients
1447 private static abstract class EmptyByteBufferExtendedCell
extends ByteBufferExtendedCell
{
1450 public void setSequenceId(long seqId
) {
1451 // Fake cells don't need seqId, so leaving it as a noop.
1455 public void setTimestamp(long ts
) {
1456 // Fake cells can't be changed timestamp, so leaving it as a noop.
1460 public void setTimestamp(byte[] ts
) {
1461 // Fake cells can't be changed timestamp, so leaving it as a noop.
1465 public byte[] getRowArray() {
1466 return CellUtil
.cloneRow(this);
1470 public int getRowOffset() {
1475 public short getRowLength() {
1480 public byte[] getFamilyArray() {
1481 return CellUtil
.cloneFamily(this);
1485 public int getFamilyOffset() {
1490 public byte getFamilyLength() {
1495 public byte[] getQualifierArray() {
1496 return CellUtil
.cloneQualifier(this);
1500 public int getQualifierOffset() {
1505 public int getQualifierLength() {
1510 public long getSequenceId() {
1515 public byte[] getValueArray() {
1516 return CellUtil
.cloneValue(this);
1520 public int getValueOffset() {
1525 public int getValueLength() {
1530 public byte[] getTagsArray() {
1531 return PrivateCellUtil
.cloneTags(this);
1535 public int getTagsOffset() {
1540 public int getTagsLength() {
1545 public ByteBuffer
getRowByteBuffer() {
1546 return HConstants
.EMPTY_BYTE_BUFFER
;
1550 public int getRowPosition() {
1555 public ByteBuffer
getFamilyByteBuffer() {
1556 return HConstants
.EMPTY_BYTE_BUFFER
;
1560 public int getFamilyPosition() {
1565 public ByteBuffer
getQualifierByteBuffer() {
1566 return HConstants
.EMPTY_BYTE_BUFFER
;
1570 public int getQualifierPosition() {
1575 public ByteBuffer
getTagsByteBuffer() {
1576 return HConstants
.EMPTY_BYTE_BUFFER
;
1580 public int getTagsPosition() {
1585 public ByteBuffer
getValueByteBuffer() {
1586 return HConstants
.EMPTY_BYTE_BUFFER
;
1590 public int getValuePosition() {
1595 private static class FirstOnRowCell
extends EmptyCell
{
1596 private static final int FIXED_HEAPSIZE
=
1597 ClassSize
.OBJECT
// object
1598 + ClassSize
.REFERENCE
// row array
1599 + Bytes
.SIZEOF_INT
// row offset
1600 + Bytes
.SIZEOF_SHORT
; // row length
1601 private final byte[] rowArray
;
1602 private final int roffset
;
1603 private final short rlength
;
1605 public FirstOnRowCell(final byte[] row
, int roffset
, short rlength
) {
1606 this.rowArray
= row
;
1607 this.roffset
= roffset
;
1608 this.rlength
= rlength
;
1612 public long heapSize() {
1613 return ClassSize
.align(FIXED_HEAPSIZE
)
1615 + (rlength
== 0 ? ClassSize
.sizeOfByteArray(rlength
) : rlength
);
1619 public byte[] getRowArray() {
1620 return this.rowArray
;
1624 public int getRowOffset() {
1625 return this.roffset
;
1629 public short getRowLength() {
1630 return this.rlength
;
1634 public long getTimestamp() {
1635 return HConstants
.LATEST_TIMESTAMP
;
1639 public byte getTypeByte() {
1640 return KeyValue
.Type
.Maximum
.getCode();
1644 public Type
getType() {
1645 throw new UnsupportedOperationException();
1649 private static class FirstOnRowByteBufferExtendedCell
extends EmptyByteBufferExtendedCell
{
1650 private static final int FIXED_OVERHEAD
=
1651 ClassSize
.OBJECT
// object
1652 + ClassSize
.REFERENCE
// row buffer
1653 + Bytes
.SIZEOF_INT
// row offset
1654 + Bytes
.SIZEOF_SHORT
; // row length
1655 private final ByteBuffer rowBuff
;
1656 private final int roffset
;
1657 private final short rlength
;
1659 public FirstOnRowByteBufferExtendedCell(final ByteBuffer row
, int roffset
, short rlength
) {
1661 this.roffset
= roffset
;
1662 this.rlength
= rlength
;
1666 public long heapSize() {
1667 if (this.rowBuff
.hasArray()) {
1668 return ClassSize
.align(FIXED_OVERHEAD
+ rlength
);
1670 return ClassSize
.align(FIXED_OVERHEAD
);
1674 public ByteBuffer
getRowByteBuffer() {
1675 return this.rowBuff
;
1679 public int getRowPosition() {
1680 return this.roffset
;
1684 public short getRowLength() {
1685 return this.rlength
;
1689 public long getTimestamp() {
1690 return HConstants
.LATEST_TIMESTAMP
;
1694 public byte getTypeByte() {
1695 return KeyValue
.Type
.Maximum
.getCode();
1699 public Type
getType() {
1700 throw new UnsupportedOperationException();
1704 private static class LastOnRowByteBufferExtendedCell
extends EmptyByteBufferExtendedCell
{
1705 private static final int FIXED_OVERHEAD
=
1706 ClassSize
.OBJECT
// object
1707 + ClassSize
.REFERENCE
// rowBuff
1708 + Bytes
.SIZEOF_INT
// roffset
1709 + Bytes
.SIZEOF_SHORT
; // rlength
1710 private final ByteBuffer rowBuff
;
1711 private final int roffset
;
1712 private final short rlength
;
1714 public LastOnRowByteBufferExtendedCell(final ByteBuffer row
, int roffset
, short rlength
) {
1716 this.roffset
= roffset
;
1717 this.rlength
= rlength
;
1721 public long heapSize() {
1722 if (this.rowBuff
.hasArray()) {
1723 return ClassSize
.align(FIXED_OVERHEAD
+ rlength
);
1725 return ClassSize
.align(FIXED_OVERHEAD
);
1729 public ByteBuffer
getRowByteBuffer() {
1730 return this.rowBuff
;
1734 public int getRowPosition() {
1735 return this.roffset
;
1739 public short getRowLength() {
1740 return this.rlength
;
1744 public long getTimestamp() {
1745 return HConstants
.OLDEST_TIMESTAMP
;
1749 public byte getTypeByte() {
1750 return KeyValue
.Type
.Minimum
.getCode();
1754 public Type
getType() {
1755 throw new UnsupportedOperationException();
1759 private static class FirstOnRowColByteBufferExtendedCell
1760 extends FirstOnRowByteBufferExtendedCell
{
1761 private static final int FIXED_OVERHEAD
=
1762 FirstOnRowByteBufferExtendedCell
.FIXED_OVERHEAD
1763 + ClassSize
.REFERENCE
* 2 // family buffer and column buffer
1764 + Bytes
.SIZEOF_INT
* 3 // famOffset, colOffset, colLength
1765 + Bytes
.SIZEOF_BYTE
; // famLength
1766 private final ByteBuffer famBuff
;
1767 private final int famOffset
;
1768 private final byte famLength
;
1769 private final ByteBuffer colBuff
;
1770 private final int colOffset
;
1771 private final int colLength
;
1773 public FirstOnRowColByteBufferExtendedCell(final ByteBuffer row
, int roffset
, short rlength
,
1774 final ByteBuffer famBuff
, final int famOffset
, final byte famLength
, final ByteBuffer col
,
1775 final int colOffset
, final int colLength
) {
1776 super(row
, roffset
, rlength
);
1777 this.famBuff
= famBuff
;
1778 this.famOffset
= famOffset
;
1779 this.famLength
= famLength
;
1781 this.colOffset
= colOffset
;
1782 this.colLength
= colLength
;
1786 public long heapSize() {
1787 if (famBuff
.hasArray() && colBuff
.hasArray()) {
1788 return ClassSize
.align(FIXED_OVERHEAD
+ famLength
+ colLength
);
1789 } else if (famBuff
.hasArray()) {
1790 return ClassSize
.align(FIXED_OVERHEAD
+ famLength
);
1791 } else if (colBuff
.hasArray()) {
1792 return ClassSize
.align(FIXED_OVERHEAD
+ colLength
);
1794 return ClassSize
.align(FIXED_OVERHEAD
);
1799 public ByteBuffer
getFamilyByteBuffer() {
1800 return this.famBuff
;
1804 public int getFamilyPosition() {
1805 return this.famOffset
;
1809 public byte getFamilyLength() {
1814 public ByteBuffer
getQualifierByteBuffer() {
1815 return this.colBuff
;
1819 public int getQualifierPosition() {
1820 return this.colOffset
;
1824 public int getQualifierLength() {
1825 return this.colLength
;
1829 private static class FirstOnRowColCell
extends FirstOnRowCell
{
1830 private static final long FIXED_HEAPSIZE
=
1831 FirstOnRowCell
.FIXED_HEAPSIZE
1832 + Bytes
.SIZEOF_BYTE
// flength
1833 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
1834 + ClassSize
.REFERENCE
* 2; // fArray, qArray
1835 private final byte[] fArray
;
1836 private final int foffset
;
1837 private final byte flength
;
1838 private final byte[] qArray
;
1839 private final int qoffset
;
1840 private final int qlength
;
1842 public FirstOnRowColCell(byte[] rArray
, int roffset
, short rlength
, byte[] fArray
, int foffset
,
1843 byte flength
, byte[] qArray
, int qoffset
, int qlength
) {
1844 super(rArray
, roffset
, rlength
);
1845 this.fArray
= fArray
;
1846 this.foffset
= foffset
;
1847 this.flength
= flength
;
1848 this.qArray
= qArray
;
1849 this.qoffset
= qoffset
;
1850 this.qlength
= qlength
;
1854 public long heapSize() {
1855 return ClassSize
.align(FIXED_HEAPSIZE
)
1857 + (flength
== 0 ? ClassSize
.sizeOfByteArray(flength
) : flength
)
1858 + (qlength
== 0 ? ClassSize
.sizeOfByteArray(qlength
) : qlength
);
1862 public byte[] getFamilyArray() {
1867 public int getFamilyOffset() {
1868 return this.foffset
;
1872 public byte getFamilyLength() {
1873 return this.flength
;
1877 public byte[] getQualifierArray() {
1882 public int getQualifierOffset() {
1883 return this.qoffset
;
1887 public int getQualifierLength() {
1888 return this.qlength
;
1892 private static class FirstOnRowColTSCell
extends FirstOnRowColCell
{
1893 private static final long FIXED_HEAPSIZE
=
1894 FirstOnRowColCell
.FIXED_HEAPSIZE
1895 + Bytes
.SIZEOF_LONG
; // ts
1898 public FirstOnRowColTSCell(byte[] rArray
, int roffset
, short rlength
, byte[] fArray
,
1899 int foffset
, byte flength
, byte[] qArray
, int qoffset
, int qlength
, long ts
) {
1900 super(rArray
, roffset
, rlength
, fArray
, foffset
, flength
, qArray
, qoffset
, qlength
);
1905 public long getTimestamp() {
1910 public long heapSize() {
1911 return ClassSize
.align(FIXED_HEAPSIZE
);
1915 private static class FirstOnRowColTSByteBufferExtendedCell
1916 extends FirstOnRowColByteBufferExtendedCell
{
1917 private static final int FIXED_OVERHEAD
=
1918 FirstOnRowColByteBufferExtendedCell
.FIXED_OVERHEAD
1919 + Bytes
.SIZEOF_LONG
; // ts
1922 public FirstOnRowColTSByteBufferExtendedCell(ByteBuffer rBuffer
, int roffset
, short rlength
,
1923 ByteBuffer fBuffer
, int foffset
, byte flength
, ByteBuffer qBuffer
, int qoffset
, int qlength
,
1925 super(rBuffer
, roffset
, rlength
, fBuffer
, foffset
, flength
, qBuffer
, qoffset
, qlength
);
1930 public long getTimestamp() {
1935 public long heapSize() {
1936 return ClassSize
.align(FIXED_OVERHEAD
+ super.heapSize());
1940 private static class LastOnRowCell
extends EmptyCell
{
1941 private static final int FIXED_OVERHEAD
=
1942 ClassSize
.OBJECT
// object
1943 + ClassSize
.REFERENCE
// row array
1944 + Bytes
.SIZEOF_INT
// row offset
1945 + Bytes
.SIZEOF_SHORT
; // row length
1946 private final byte[] rowArray
;
1947 private final int roffset
;
1948 private final short rlength
;
1950 public LastOnRowCell(byte[] row
, int roffset
, short rlength
) {
1951 this.rowArray
= row
;
1952 this.roffset
= roffset
;
1953 this.rlength
= rlength
;
1957 public long heapSize() {
1958 return ClassSize
.align(FIXED_OVERHEAD
)
1960 + (rlength
== 0 ? ClassSize
.sizeOfByteArray(rlength
) : rlength
);
1964 public byte[] getRowArray() {
1965 return this.rowArray
;
1969 public int getRowOffset() {
1970 return this.roffset
;
1974 public short getRowLength() {
1975 return this.rlength
;
1979 public long getTimestamp() {
1980 return HConstants
.OLDEST_TIMESTAMP
;
1984 public byte getTypeByte() {
1985 return KeyValue
.Type
.Minimum
.getCode();
1989 public Type
getType() {
1990 throw new UnsupportedOperationException();
1994 private static class LastOnRowColCell
extends LastOnRowCell
{
1995 private static final long FIXED_OVERHEAD
= LastOnRowCell
.FIXED_OVERHEAD
1996 + ClassSize
.REFERENCE
* 2 // fArray and qArray
1997 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
1998 + Bytes
.SIZEOF_BYTE
; // flength
1999 private final byte[] fArray
;
2000 private final int foffset
;
2001 private final byte flength
;
2002 private final byte[] qArray
;
2003 private final int qoffset
;
2004 private final int qlength
;
2006 public LastOnRowColCell(byte[] rArray
, int roffset
, short rlength
, byte[] fArray
, int foffset
,
2007 byte flength
, byte[] qArray
, int qoffset
, int qlength
) {
2008 super(rArray
, roffset
, rlength
);
2009 this.fArray
= fArray
;
2010 this.foffset
= foffset
;
2011 this.flength
= flength
;
2012 this.qArray
= qArray
;
2013 this.qoffset
= qoffset
;
2014 this.qlength
= qlength
;
2018 public long heapSize() {
2019 return ClassSize
.align(FIXED_OVERHEAD
)
2021 + (flength
== 0 ? ClassSize
.sizeOfByteArray(flength
) : flength
)
2022 + (qlength
== 0 ? ClassSize
.sizeOfByteArray(qlength
) : qlength
);
2026 public byte[] getFamilyArray() {
2031 public int getFamilyOffset() {
2032 return this.foffset
;
2036 public byte getFamilyLength() {
2037 return this.flength
;
2041 public byte[] getQualifierArray() {
2046 public int getQualifierOffset() {
2047 return this.qoffset
;
2051 public int getQualifierLength() {
2052 return this.qlength
;
2056 private static class LastOnRowColByteBufferExtendedCell
extends LastOnRowByteBufferExtendedCell
{
2057 private static final int FIXED_OVERHEAD
=
2058 LastOnRowByteBufferExtendedCell
.FIXED_OVERHEAD
2059 + ClassSize
.REFERENCE
* 2 // fBuffer and qBuffer
2060 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
2061 + Bytes
.SIZEOF_BYTE
; // flength
2062 private final ByteBuffer fBuffer
;
2063 private final int foffset
;
2064 private final byte flength
;
2065 private final ByteBuffer qBuffer
;
2066 private final int qoffset
;
2067 private final int qlength
;
2069 public LastOnRowColByteBufferExtendedCell(ByteBuffer rBuffer
, int roffset
, short rlength
,
2070 ByteBuffer fBuffer
, int foffset
, byte flength
, ByteBuffer qBuffer
, int qoffset
,
2072 super(rBuffer
, roffset
, rlength
);
2073 this.fBuffer
= fBuffer
;
2074 this.foffset
= foffset
;
2075 this.flength
= flength
;
2076 this.qBuffer
= qBuffer
;
2077 this.qoffset
= qoffset
;
2078 this.qlength
= qlength
;
2082 public long heapSize() {
2083 if (fBuffer
.hasArray() && qBuffer
.hasArray()) {
2084 return ClassSize
.align(FIXED_OVERHEAD
+ flength
+ qlength
);
2085 } else if (fBuffer
.hasArray()) {
2086 return ClassSize
.align(FIXED_OVERHEAD
+ flength
);
2087 } else if (qBuffer
.hasArray()) {
2088 return ClassSize
.align(FIXED_OVERHEAD
+ qlength
);
2090 return ClassSize
.align(FIXED_OVERHEAD
);
2095 public ByteBuffer
getFamilyByteBuffer() {
2096 return this.fBuffer
;
2100 public int getFamilyPosition() {
2101 return this.foffset
;
2105 public byte getFamilyLength() {
2106 return this.flength
;
2110 public ByteBuffer
getQualifierByteBuffer() {
2111 return this.qBuffer
;
2115 public int getQualifierPosition() {
2116 return this.qoffset
;
2120 public int getQualifierLength() {
2121 return this.qlength
;
2125 private static class FirstOnRowDeleteFamilyCell
extends EmptyCell
{
2126 private static final int FIXED_OVERHEAD
=
2127 ClassSize
.OBJECT
// object
2128 + ClassSize
.REFERENCE
* 2 // fBuffer and qBuffer
2129 + Bytes
.SIZEOF_INT
* 3 // foffset, qoffset, qlength
2130 + Bytes
.SIZEOF_BYTE
; // flength
2131 private final byte[] row
;
2132 private final byte[] fam
;
2134 public FirstOnRowDeleteFamilyCell(byte[] row
, byte[] fam
) {
2140 public long heapSize() {
2141 return ClassSize
.align(FIXED_OVERHEAD
)
2143 + (getRowLength() == 0 ? ClassSize
.sizeOfByteArray(getRowLength()) : getRowLength())
2144 + (getFamilyLength() == 0 ?
2145 ClassSize
.sizeOfByteArray(getFamilyLength()) : getFamilyLength());
2149 public byte[] getRowArray() {
2154 public short getRowLength() {
2155 return (short) this.row
.length
;
2159 public byte[] getFamilyArray() {
2164 public byte getFamilyLength() {
2165 return (byte) this.fam
.length
;
2169 public long getTimestamp() {
2170 return HConstants
.LATEST_TIMESTAMP
;
2174 public byte getTypeByte() {
2175 return KeyValue
.Type
.DeleteFamily
.getCode();
2179 public Type
getType() {
2180 return Type
.DeleteFamily
;
2185 * Writes the Cell's key part as it would have serialized in a KeyValue. The format is <2 bytes
2186 * rk len><rk><1 byte cf len><cf><qualifier><8 bytes
2187 * timestamp><1 byte type>
2190 * @throws IOException
2192 public static void writeFlatKey(Cell cell
, DataOutput out
) throws IOException
{
2193 short rowLen
= cell
.getRowLength();
2194 byte fLen
= cell
.getFamilyLength();
2195 int qLen
= cell
.getQualifierLength();
2196 // Using just one if/else loop instead of every time checking before writing every
2197 // component of cell
2198 if (cell
instanceof ByteBufferExtendedCell
) {
2199 out
.writeShort(rowLen
);
2200 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2201 ((ByteBufferExtendedCell
) cell
).getRowPosition(), rowLen
);
2202 out
.writeByte(fLen
);
2203 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2204 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), fLen
);
2206 .copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2207 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), qLen
);
2209 out
.writeShort(rowLen
);
2210 out
.write(cell
.getRowArray(), cell
.getRowOffset(), rowLen
);
2211 out
.writeByte(fLen
);
2212 out
.write(cell
.getFamilyArray(), cell
.getFamilyOffset(), fLen
);
2213 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset(), qLen
);
2215 out
.writeLong(cell
.getTimestamp());
2216 out
.writeByte(cell
.getTypeByte());
2220 * Deep clones the given cell if the cell supports deep cloning
2221 * @param cell the cell to be cloned
2222 * @return the cloned cell
2223 * @throws CloneNotSupportedException
2225 public static Cell
deepClone(Cell cell
) throws CloneNotSupportedException
{
2226 if (cell
instanceof ExtendedCell
) {
2227 return ((ExtendedCell
) cell
).deepClone();
2229 throw new CloneNotSupportedException();
2233 * Writes the cell to the given OutputStream
2234 * @param cell the cell to be written
2235 * @param out the outputstream
2236 * @param withTags if tags are to be written or not
2237 * @return the total bytes written
2238 * @throws IOException
2240 public static int writeCell(Cell cell
, OutputStream out
, boolean withTags
) throws IOException
{
2241 if (cell
instanceof ExtendedCell
) {
2242 return ((ExtendedCell
) cell
).write(out
, withTags
);
2244 ByteBufferUtils
.putInt(out
, estimatedSerializedSizeOfKey(cell
));
2245 ByteBufferUtils
.putInt(out
, cell
.getValueLength());
2246 writeFlatKey(cell
, out
);
2247 writeValue(out
, cell
, cell
.getValueLength());
2248 int tagsLength
= cell
.getTagsLength();
2250 byte[] len
= new byte[Bytes
.SIZEOF_SHORT
];
2251 Bytes
.putAsShort(len
, 0, tagsLength
);
2253 if (tagsLength
> 0) {
2254 writeTags(out
, cell
, tagsLength
);
2257 int lenWritten
= (2 * Bytes
.SIZEOF_INT
) + estimatedSerializedSizeOfKey(cell
)
2258 + cell
.getValueLength();
2260 lenWritten
+= Bytes
.SIZEOF_SHORT
+ tagsLength
;
2267 * Writes a cell to the buffer at the given offset
2268 * @param cell the cell to be written
2269 * @param buf the buffer to which the cell has to be wrriten
2270 * @param offset the offset at which the cell should be written
2272 public static void writeCellToBuffer(Cell cell
, ByteBuffer buf
, int offset
) {
2273 if (cell
instanceof ExtendedCell
) {
2274 ((ExtendedCell
) cell
).write(buf
, offset
);
2277 byte[] bytes
= KeyValueUtil
.copyToNewByteArray(cell
);
2278 ByteBufferUtils
.copyFromArrayToBuffer(buf
, offset
, bytes
, 0, bytes
.length
);
2282 public static int writeFlatKey(Cell cell
, OutputStream out
) throws IOException
{
2283 short rowLen
= cell
.getRowLength();
2284 byte fLen
= cell
.getFamilyLength();
2285 int qLen
= cell
.getQualifierLength();
2286 // Using just one if/else loop instead of every time checking before writing every
2287 // component of cell
2288 if (cell
instanceof ByteBufferExtendedCell
) {
2289 StreamUtils
.writeShort(out
, rowLen
);
2290 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2291 ((ByteBufferExtendedCell
) cell
).getRowPosition(), rowLen
);
2293 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2294 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), fLen
);
2296 .copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2297 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), qLen
);
2299 StreamUtils
.writeShort(out
, rowLen
);
2300 out
.write(cell
.getRowArray(), cell
.getRowOffset(), rowLen
);
2302 out
.write(cell
.getFamilyArray(), cell
.getFamilyOffset(), fLen
);
2303 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset(), qLen
);
2305 StreamUtils
.writeLong(out
, cell
.getTimestamp());
2306 out
.write(cell
.getTypeByte());
2307 return Bytes
.SIZEOF_SHORT
+ rowLen
+ Bytes
.SIZEOF_BYTE
+ fLen
+ qLen
+ Bytes
.SIZEOF_LONG
2308 + Bytes
.SIZEOF_BYTE
;
2312 * Sets the given seqId to the cell. Marked as audience Private as of 1.2.0. Setting a Cell
2313 * sequenceid is an internal implementation detail not for general public use.
2316 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2318 public static void setSequenceId(Cell cell
, long seqId
) throws IOException
{
2319 if (cell
instanceof ExtendedCell
) {
2320 ((ExtendedCell
) cell
).setSequenceId(seqId
);
2322 throw new IOException(new UnsupportedOperationException(
2323 "Cell is not of type " + ExtendedCell
.class.getName()));
2328 * Sets the given timestamp to the cell.
2331 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2333 public static void setTimestamp(Cell cell
, long ts
) throws IOException
{
2334 if (cell
instanceof ExtendedCell
) {
2335 ((ExtendedCell
) cell
).setTimestamp(ts
);
2337 throw new IOException(new UnsupportedOperationException(
2338 "Cell is not of type " + ExtendedCell
.class.getName()));
2343 * Sets the given timestamp to the cell.
2345 * @param ts buffer containing the timestamp value
2346 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2348 public static void setTimestamp(Cell cell
, byte[] ts
) throws IOException
{
2349 if (cell
instanceof ExtendedCell
) {
2350 ((ExtendedCell
) cell
).setTimestamp(ts
);
2352 throw new IOException(new UnsupportedOperationException(
2353 "Cell is not of type " + ExtendedCell
.class.getName()));
2358 * Sets the given timestamp to the cell iff current timestamp is
2359 * {@link HConstants#LATEST_TIMESTAMP}.
2362 * @return True if cell timestamp is modified.
2363 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2365 public static boolean updateLatestStamp(Cell cell
, long ts
) throws IOException
{
2366 if (cell
.getTimestamp() == HConstants
.LATEST_TIMESTAMP
) {
2367 setTimestamp(cell
, ts
);
2374 * Sets the given timestamp to the cell iff current timestamp is
2375 * {@link HConstants#LATEST_TIMESTAMP}.
2377 * @param ts buffer containing the timestamp value
2378 * @return True if cell timestamp is modified.
2379 * @throws IOException when the passed cell is not of type {@link ExtendedCell}
2381 public static boolean updateLatestStamp(Cell cell
, byte[] ts
) throws IOException
{
2382 if (cell
.getTimestamp() == HConstants
.LATEST_TIMESTAMP
) {
2383 setTimestamp(cell
, ts
);
2390 * Writes the row from the given cell to the output stream
2391 * @param out The outputstream to which the data has to be written
2392 * @param cell The cell whose contents has to be written
2393 * @param rlength the row length
2394 * @throws IOException
2396 public static void writeRow(OutputStream out
, Cell cell
, short rlength
) throws IOException
{
2397 if (cell
instanceof ByteBufferExtendedCell
) {
2398 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2399 ((ByteBufferExtendedCell
) cell
).getRowPosition(), rlength
);
2401 out
.write(cell
.getRowArray(), cell
.getRowOffset(), rlength
);
2406 * Writes the family from the given cell to the output stream
2407 * @param out The outputstream to which the data has to be written
2408 * @param cell The cell whose contents has to be written
2409 * @param flength the family length
2410 * @throws IOException
2412 public static void writeFamily(OutputStream out
, Cell cell
, byte flength
) throws IOException
{
2413 if (cell
instanceof ByteBufferExtendedCell
) {
2414 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2415 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), flength
);
2417 out
.write(cell
.getFamilyArray(), cell
.getFamilyOffset(), flength
);
2422 * Writes the qualifier from the given cell to the output stream
2423 * @param out The outputstream to which the data has to be written
2424 * @param cell The cell whose contents has to be written
2425 * @param qlength the qualifier length
2426 * @throws IOException
2428 public static void writeQualifier(OutputStream out
, Cell cell
, int qlength
) throws IOException
{
2429 if (cell
instanceof ByteBufferExtendedCell
) {
2431 .copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2432 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), qlength
);
2434 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset(), qlength
);
2439 * Writes the qualifier from the given cell to the output stream excluding the common prefix
2440 * @param out The dataoutputstream to which the data has to be written
2441 * @param cell The cell whose contents has to be written
2442 * @param qlength the qualifier length
2443 * @throws IOException
2445 public static void writeQualifierSkippingBytes(DataOutputStream out
, Cell cell
, int qlength
,
2446 int commonPrefix
) throws IOException
{
2447 if (cell
instanceof ByteBufferExtendedCell
) {
2448 ByteBufferUtils
.copyBufferToStream((DataOutput
) out
,
2449 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2450 ((ByteBufferExtendedCell
) cell
).getQualifierPosition() + commonPrefix
,
2451 qlength
- commonPrefix
);
2453 out
.write(cell
.getQualifierArray(), cell
.getQualifierOffset() + commonPrefix
,
2454 qlength
- commonPrefix
);
2459 * Writes the value from the given cell to the output stream
2460 * @param out The outputstream to which the data has to be written
2461 * @param cell The cell whose contents has to be written
2462 * @param vlength the value length
2463 * @throws IOException
2465 public static void writeValue(OutputStream out
, Cell cell
, int vlength
) throws IOException
{
2466 if (cell
instanceof ByteBufferExtendedCell
) {
2467 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2468 ((ByteBufferExtendedCell
) cell
).getValuePosition(), vlength
);
2470 out
.write(cell
.getValueArray(), cell
.getValueOffset(), vlength
);
2475 * Writes the tag from the given cell to the output stream
2476 * @param out The outputstream to which the data has to be written
2477 * @param cell The cell whose contents has to be written
2478 * @param tagsLength the tag length
2479 * @throws IOException
2481 public static void writeTags(OutputStream out
, Cell cell
, int tagsLength
) throws IOException
{
2482 if (cell
instanceof ByteBufferExtendedCell
) {
2483 ByteBufferUtils
.copyBufferToStream(out
, ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
2484 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), tagsLength
);
2486 out
.write(cell
.getTagsArray(), cell
.getTagsOffset(), tagsLength
);
2491 * special case for Cell.equals
2493 public static boolean equalsIgnoreMvccVersion(Cell a
, Cell b
) {
2495 boolean res
= CellUtil
.matchingRows(a
, b
);
2496 if (!res
) return res
;
2499 res
= CellUtil
.matchingColumn(a
, b
);
2500 if (!res
) return res
;
2502 // timestamp: later sorts first
2503 if (!CellUtil
.matchingTimestamp(a
, b
)) return false;
2506 int c
= (0xff & b
.getTypeByte()) - (0xff & a
.getTypeByte());
2507 if (c
!= 0) return false;
2512 * Converts the rowkey bytes of the given cell into an int value
2514 * @return rowkey as int
2516 public static int getRowAsInt(Cell cell
) {
2517 if (cell
instanceof ByteBufferExtendedCell
) {
2518 return ByteBufferUtils
.toInt(((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2519 ((ByteBufferExtendedCell
) cell
).getRowPosition());
2521 return Bytes
.toInt(cell
.getRowArray(), cell
.getRowOffset());
2525 * Converts the value bytes of the given cell into a long value
2527 * @return value as long
2529 public static long getValueAsLong(Cell cell
) {
2530 if (cell
instanceof ByteBufferExtendedCell
) {
2531 return ByteBufferUtils
.toLong(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2532 ((ByteBufferExtendedCell
) cell
).getValuePosition());
2534 return Bytes
.toLong(cell
.getValueArray(), cell
.getValueOffset());
2538 * Converts the value bytes of the given cell into a int value
2540 * @return value as int
2542 public static int getValueAsInt(Cell cell
) {
2543 if (cell
instanceof ByteBufferExtendedCell
) {
2544 return ByteBufferUtils
.toInt(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2545 ((ByteBufferExtendedCell
) cell
).getValuePosition());
2547 return Bytes
.toInt(cell
.getValueArray(), cell
.getValueOffset());
2551 * Converts the value bytes of the given cell into a double value
2553 * @return value as double
2555 public static double getValueAsDouble(Cell cell
) {
2556 if (cell
instanceof ByteBufferExtendedCell
) {
2557 return ByteBufferUtils
.toDouble(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2558 ((ByteBufferExtendedCell
) cell
).getValuePosition());
2560 return Bytes
.toDouble(cell
.getValueArray(), cell
.getValueOffset());
2564 * Converts the value bytes of the given cell into a BigDecimal
2566 * @return value as BigDecimal
2568 public static BigDecimal
getValueAsBigDecimal(Cell cell
) {
2569 if (cell
instanceof ByteBufferExtendedCell
) {
2570 return ByteBufferUtils
.toBigDecimal(((ByteBufferExtendedCell
) cell
).getValueByteBuffer(),
2571 ((ByteBufferExtendedCell
) cell
).getValuePosition(), cell
.getValueLength());
2573 return Bytes
.toBigDecimal(cell
.getValueArray(), cell
.getValueOffset(), cell
.getValueLength());
2577 * Compresses the tags to the given outputstream using the TagcompressionContext
2578 * @param out the outputstream to which the compression should happen
2579 * @param cell the cell which has tags
2580 * @param tagCompressionContext the TagCompressionContext
2581 * @throws IOException can throw IOException if the compression encounters issue
2583 public static void compressTags(OutputStream out
, Cell cell
,
2584 TagCompressionContext tagCompressionContext
) throws IOException
{
2585 if (cell
instanceof ByteBufferExtendedCell
) {
2586 tagCompressionContext
.compressTags(out
, ((ByteBufferExtendedCell
) cell
).getTagsByteBuffer(),
2587 ((ByteBufferExtendedCell
) cell
).getTagsPosition(), cell
.getTagsLength());
2589 tagCompressionContext
.compressTags(out
, cell
.getTagsArray(), cell
.getTagsOffset(),
2590 cell
.getTagsLength());
2594 public static void compressRow(OutputStream out
, Cell cell
, Dictionary dict
) throws IOException
{
2595 if (cell
instanceof ByteBufferExtendedCell
) {
2596 Dictionary
.write(out
, ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2597 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(), dict
);
2599 Dictionary
.write(out
, cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(), dict
);
2603 public static void compressFamily(OutputStream out
, Cell cell
, Dictionary dict
)
2604 throws IOException
{
2605 if (cell
instanceof ByteBufferExtendedCell
) {
2606 Dictionary
.write(out
, ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2607 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(), dict
);
2609 Dictionary
.write(out
, cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2614 public static void compressQualifier(OutputStream out
, Cell cell
, Dictionary dict
)
2615 throws IOException
{
2616 if (cell
instanceof ByteBufferExtendedCell
) {
2617 Dictionary
.write(out
, ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2618 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength(), dict
);
2620 Dictionary
.write(out
, cell
.getQualifierArray(), cell
.getQualifierOffset(),
2621 cell
.getQualifierLength(), dict
);
2626 * Used when a cell needs to be compared with a key byte[] such as cases of finding the index from
2627 * the index block, bloom keys from the bloom blocks This byte[] is expected to be serialized in
2628 * the KeyValue serialization format If the KeyValue (Cell's) serialization format changes this
2629 * method cannot be used.
2630 * @param comparator the {@link CellComparator} to use for comparison
2631 * @param left the cell to be compared
2632 * @param key the serialized key part of a KeyValue
2633 * @param offset the offset in the key byte[]
2634 * @param length the length of the key byte[]
2635 * @return an int greater than 0 if left is greater than right lesser than 0 if left is lesser
2636 * than right equal to 0 if left is equal to right
2639 public static final int compare(CellComparator comparator
, Cell left
, byte[] key
, int offset
,
2642 short rrowlength
= Bytes
.toShort(key
, offset
);
2643 int c
= comparator
.compareRows(left
, key
, offset
+ Bytes
.SIZEOF_SHORT
, rrowlength
);
2644 if (c
!= 0) return c
;
2646 // Compare the rest of the two KVs without making any assumptions about
2647 // the common prefix. This function will not compare rows anyway, so we
2648 // don't need to tell it that the common prefix includes the row.
2649 return compareWithoutRow(comparator
, left
, key
, offset
, length
, rrowlength
);
2653 * Compare columnFamily, qualifier, timestamp, and key type (everything except the row). This
2654 * method is used both in the normal comparator and the "same-prefix" comparator. Note that we are
2655 * assuming that row portions of both KVs have already been parsed and found identical, and we
2656 * don't validate that assumption here.
2657 * @param comparator the {@link CellComparator} to use for comparison
2658 * @param left the cell to be compared
2659 * @param right the serialized key part of a key-value
2660 * @param roffset the offset in the key byte[]
2661 * @param rlength the length of the key byte[]
2662 * @param rowlength the row length
2663 * @return greater than 0 if left cell is bigger, less than 0 if right cell is bigger, 0 if both
2666 static final int compareWithoutRow(CellComparator comparator
, Cell left
, byte[] right
,
2667 int roffset
, int rlength
, short rowlength
) {
2669 * KeyValue Format and commonLength:
2670 * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
2671 * ------------------|-------commonLength--------|--------------
2673 int commonLength
= KeyValue
.ROW_LENGTH_SIZE
+ KeyValue
.FAMILY_LENGTH_SIZE
+ rowlength
;
2675 // commonLength + TIMESTAMP_TYPE_SIZE
2676 int commonLengthWithTSAndType
= KeyValue
.TIMESTAMP_TYPE_SIZE
+ commonLength
;
2677 // ColumnFamily + Qualifier length.
2678 int lcolumnlength
= left
.getFamilyLength() + left
.getQualifierLength();
2679 int rcolumnlength
= rlength
- commonLengthWithTSAndType
;
2681 byte ltype
= left
.getTypeByte();
2682 byte rtype
= right
[roffset
+ (rlength
- 1)];
2684 // If the column is not specified, the "minimum" key type appears the
2685 // latest in the sorted order, regardless of the timestamp. This is used
2686 // for specifying the last key/value in a given row, because there is no
2687 // "lexicographically last column" (it would be infinitely long). The
2688 // "maximum" key type does not need this behavior.
2689 if (lcolumnlength
== 0 && ltype
== KeyValue
.Type
.Minimum
.getCode()) {
2690 // left is "bigger", i.e. it appears later in the sorted order
2693 if (rcolumnlength
== 0 && rtype
== KeyValue
.Type
.Minimum
.getCode()) {
2697 int rfamilyoffset
= commonLength
+ roffset
;
2699 // Column family length.
2700 int lfamilylength
= left
.getFamilyLength();
2701 int rfamilylength
= right
[rfamilyoffset
- 1];
2702 // If left family size is not equal to right family size, we need not
2703 // compare the qualifiers.
2704 boolean sameFamilySize
= (lfamilylength
== rfamilylength
);
2705 if (!sameFamilySize
) {
2706 // comparing column family is enough.
2707 return CellUtil
.compareFamilies(left
, right
, rfamilyoffset
, rfamilylength
);
2709 // Compare family & qualifier together.
2710 // Families are same. Compare on qualifiers.
2711 int comparison
= CellUtil
.compareColumns(left
, right
, rfamilyoffset
, rfamilylength
,
2712 rfamilyoffset
+ rfamilylength
, (rcolumnlength
- rfamilylength
));
2713 if (comparison
!= 0) {
2718 // Next compare timestamps.
2719 long rtimestamp
= Bytes
.toLong(right
, roffset
+ (rlength
- KeyValue
.TIMESTAMP_TYPE_SIZE
));
2720 int compare
= comparator
.compareTimestamps(left
.getTimestamp(), rtimestamp
);
2725 // Compare types. Let the delete types sort ahead of puts; i.e. types
2726 // of higher numbers sort before those of lesser numbers. Maximum (255)
2727 // appears ahead of everything, and minimum (0) appears after
2729 return (0xff & rtype
) - (0xff & ltype
);
2733 * @return An new cell is located following input cell. If both of type and timestamp are minimum,
2734 * the input cell will be returned directly.
2736 public static Cell
createNextOnRowCol(Cell cell
) {
2737 long ts
= cell
.getTimestamp();
2738 byte type
= cell
.getTypeByte();
2739 if (type
!= KeyValue
.Type
.Minimum
.getCode()) {
2740 type
= KeyValue
.Type
.values()[KeyValue
.Type
.codeToType(type
).ordinal() - 1].getCode();
2741 } else if (ts
!= HConstants
.OLDEST_TIMESTAMP
) {
2743 type
= KeyValue
.Type
.Maximum
.getCode();
2747 return createNextOnRowCol(cell
, ts
, type
);
2750 static Cell
createNextOnRowCol(Cell cell
, long ts
, byte type
) {
2751 if (cell
instanceof ByteBufferExtendedCell
) {
2752 return new LastOnRowColByteBufferExtendedCell(
2753 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2754 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2755 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2756 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2757 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2758 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength()) {
2760 public long getTimestamp() {
2765 public byte getTypeByte() {
2770 return new LastOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2771 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2772 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength()) {
2774 public long getTimestamp() {
2779 public byte getTypeByte() {
2786 * Estimate based on keyvalue's serialization format in the RPC layer. Note that there is an extra
2787 * SIZEOF_INT added to the size here that indicates the actual length of the cell for cases where
2788 * cell's are serialized in a contiguous format (For eg in RPCs).
2790 * @return Estimate of the <code>cell</code> size in bytes plus an extra SIZEOF_INT indicating the
2791 * actual cell length.
2793 public static int estimatedSerializedSizeOf(final Cell cell
) {
2794 return cell
.getSerializedSize() + Bytes
.SIZEOF_INT
;
2798 * Calculates the serialized key size. We always serialize in the KeyValue's serialization format.
2799 * @param cell the cell for which the key size has to be calculated.
2800 * @return the key size
2802 public static int estimatedSerializedSizeOfKey(final Cell cell
) {
2803 if (cell
instanceof KeyValue
) return ((KeyValue
) cell
).getKeyLength();
2804 return cell
.getRowLength() + cell
.getFamilyLength() + cell
.getQualifierLength()
2805 + KeyValue
.KEY_INFRASTRUCTURE_SIZE
;
2809 * This method exists just to encapsulate how we serialize keys. To be replaced by a factory that
2810 * we query to figure what the Cell implementation is and then, what serialization engine to use
2811 * and further, how to serialize the key for inclusion in hfile index. TODO.
2813 * @return The key portion of the Cell serialized in the old-school KeyValue way or null if passed
2814 * a null <code>cell</code>
2816 public static byte[] getCellKeySerializedAsKeyValueKey(final Cell cell
) {
2817 if (cell
== null) return null;
2818 byte[] b
= new byte[KeyValueUtil
.keyLength(cell
)];
2819 KeyValueUtil
.appendKeyTo(cell
, b
, 0);
2824 * Create a Cell that is smaller than all other possible Cells for the given Cell's row.
2826 * @return First possible Cell on passed Cell's row.
2828 public static Cell
createFirstOnRow(final Cell cell
) {
2829 if (cell
instanceof ByteBufferExtendedCell
) {
2830 return new FirstOnRowByteBufferExtendedCell(
2831 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2832 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength());
2834 return new FirstOnRowCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
2837 public static Cell
createFirstOnRow(final byte[] row
, int roffset
, short rlength
) {
2838 return new FirstOnRowCell(row
, roffset
, rlength
);
2841 public static Cell
createFirstOnRow(final byte[] row
, final byte[] family
, final byte[] col
) {
2842 return createFirstOnRow(row
, 0, (short) row
.length
, family
, 0, (byte) family
.length
, col
, 0,
2846 public static Cell
createFirstOnRow(final byte[] row
, int roffset
, short rlength
,
2847 final byte[] family
, int foffset
, byte flength
, final byte[] col
, int coffset
, int clength
) {
2848 return new FirstOnRowColCell(row
, roffset
, rlength
, family
, foffset
, flength
, col
, coffset
,
2852 public static Cell
createFirstOnRow(final byte[] row
) {
2853 return createFirstOnRow(row
, 0, (short) row
.length
);
2856 public static Cell
createFirstOnRowFamily(Cell cell
, byte[] fArray
, int foff
, int flen
) {
2857 if (cell
instanceof ByteBufferExtendedCell
) {
2858 return new FirstOnRowColByteBufferExtendedCell(
2859 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2860 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2861 ByteBuffer
.wrap(fArray
), foff
, (byte) flen
, HConstants
.EMPTY_BYTE_BUFFER
, 0, 0);
2863 return new FirstOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2864 fArray
, foff
, (byte) flen
, HConstants
.EMPTY_BYTE_ARRAY
, 0, 0);
2867 public static Cell
createFirstOnRowCol(final Cell cell
) {
2868 if (cell
instanceof ByteBufferExtendedCell
) {
2869 return new FirstOnRowColByteBufferExtendedCell(
2870 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2871 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2872 HConstants
.EMPTY_BYTE_BUFFER
, 0, (byte) 0,
2873 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2874 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength());
2876 return new FirstOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2877 HConstants
.EMPTY_BYTE_ARRAY
, 0, (byte) 0, cell
.getQualifierArray(),
2878 cell
.getQualifierOffset(), cell
.getQualifierLength());
2881 public static Cell
createFirstOnNextRow(final Cell cell
) {
2882 byte[] nextRow
= new byte[cell
.getRowLength() + 1];
2883 CellUtil
.copyRowTo(cell
, nextRow
, 0);
2884 nextRow
[nextRow
.length
- 1] = 0;// maybe not necessary
2885 return new FirstOnRowCell(nextRow
, 0, (short) nextRow
.length
);
2889 * Create a Cell that is smaller than all other possible Cells for the given Cell's rk:cf and
2895 * @return Last possible Cell on passed Cell's rk:cf and passed qualifier.
2897 public static Cell
createFirstOnRowCol(final Cell cell
, byte[] qArray
, int qoffest
, int qlength
) {
2898 if (cell
instanceof ByteBufferExtendedCell
) {
2899 return new FirstOnRowColByteBufferExtendedCell(
2900 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2901 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2902 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2903 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2904 ByteBuffer
.wrap(qArray
), qoffest
, qlength
);
2906 return new FirstOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2907 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(), qArray
, qoffest
,
2912 * Creates the first cell with the row/family/qualifier of this cell and the given timestamp. Uses
2913 * the "maximum" type that guarantees that the new cell is the lowest possible for this
2914 * combination of row, family, qualifier, and timestamp. This cell's own timestamp is ignored.
2915 * @param cell - cell
2918 public static Cell
createFirstOnRowColTS(Cell cell
, long ts
) {
2919 if (cell
instanceof ByteBufferExtendedCell
) {
2920 return new FirstOnRowColTSByteBufferExtendedCell(
2921 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2922 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2923 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2924 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2925 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2926 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength(), ts
);
2928 return new FirstOnRowColTSCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2929 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2930 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength(), ts
);
2934 * Create a Cell that is larger than all other possible Cells for the given Cell's row.
2936 * @return Last possible Cell on passed Cell's row.
2938 public static Cell
createLastOnRow(final Cell cell
) {
2939 if (cell
instanceof ByteBufferExtendedCell
) {
2940 return new LastOnRowByteBufferExtendedCell(((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2941 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength());
2943 return new LastOnRowCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength());
2946 public static Cell
createLastOnRow(final byte[] row
) {
2947 return new LastOnRowCell(row
, 0, (short) row
.length
);
2951 * Create a Cell that is larger than all other possible Cells for the given Cell's rk:cf:q. Used
2952 * in creating "fake keys" for the multi-column Bloom filter optimization to skip the row/column
2953 * we already know is not in the file.
2955 * @return Last possible Cell on passed Cell's rk:cf:q.
2957 public static Cell
createLastOnRowCol(final Cell cell
) {
2958 if (cell
instanceof ByteBufferExtendedCell
) {
2959 return new LastOnRowColByteBufferExtendedCell(
2960 ((ByteBufferExtendedCell
) cell
).getRowByteBuffer(),
2961 ((ByteBufferExtendedCell
) cell
).getRowPosition(), cell
.getRowLength(),
2962 ((ByteBufferExtendedCell
) cell
).getFamilyByteBuffer(),
2963 ((ByteBufferExtendedCell
) cell
).getFamilyPosition(), cell
.getFamilyLength(),
2964 ((ByteBufferExtendedCell
) cell
).getQualifierByteBuffer(),
2965 ((ByteBufferExtendedCell
) cell
).getQualifierPosition(), cell
.getQualifierLength());
2967 return new LastOnRowColCell(cell
.getRowArray(), cell
.getRowOffset(), cell
.getRowLength(),
2968 cell
.getFamilyArray(), cell
.getFamilyOffset(), cell
.getFamilyLength(),
2969 cell
.getQualifierArray(), cell
.getQualifierOffset(), cell
.getQualifierLength());
2973 * Create a Delete Family Cell for the specified row and family that would be smaller than all
2974 * other possible Delete Family KeyValues that have the same row and family. Used for seeking.
2975 * @param row - row key (arbitrary byte array)
2976 * @param fam - family name
2977 * @return First Delete Family possible key on passed <code>row</code>.
2979 public static Cell
createFirstDeleteFamilyCellOnRow(final byte[] row
, final byte[] fam
) {
2980 return new FirstOnRowDeleteFamilyCell(row
, fam
);