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 java
.io
.IOException
;
21 import java
.io
.OutputStream
;
22 import java
.nio
.ByteBuffer
;
23 import org
.apache
.hadoop
.hbase
.util
.ByteBufferUtils
;
24 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
25 import org
.apache
.hadoop
.hbase
.util
.ClassSize
;
26 import org
.apache
.yetus
.audience
.InterfaceAudience
;
29 * This Cell is an implementation of {@link ByteBufferExtendedCell} where the data resides in
30 * off heap/ on heap ByteBuffer
32 @InterfaceAudience.Private
33 public class ByteBufferKeyValue
extends ByteBufferExtendedCell
{
35 protected final ByteBuffer buf
;
36 protected final int offset
;
37 protected final int length
;
38 private long seqId
= 0;
40 public static final int FIXED_OVERHEAD
= ClassSize
.OBJECT
+ ClassSize
.REFERENCE
41 + (2 * Bytes
.SIZEOF_INT
) + Bytes
.SIZEOF_LONG
;
43 public ByteBufferKeyValue(ByteBuffer buf
, int offset
, int length
, long seqId
) {
50 public ByteBufferKeyValue(ByteBuffer buf
, int offset
, int length
) {
56 public ByteBuffer
getBuffer() {
60 public int getOffset() {
65 public byte[] getRowArray() {
66 return CellUtil
.cloneRow(this);
70 public int getRowOffset() {
75 public short getRowLength() {
76 return ByteBufferUtils
.toShort(this.buf
, this.offset
+ KeyValue
.ROW_OFFSET
);
80 public byte[] getFamilyArray() {
81 return CellUtil
.cloneFamily(this);
85 public int getFamilyOffset() {
90 public byte getFamilyLength() {
91 return getFamilyLength(getFamilyLengthPosition());
94 int getFamilyLengthPosition() {
95 return getFamilyLengthPosition(getRowLength());
98 int getFamilyLengthPosition(int rowLength
) {
99 return this.offset
+ KeyValue
.ROW_KEY_OFFSET
+ rowLength
;
102 byte getFamilyLength(int famLenPos
) {
103 return ByteBufferUtils
.toByte(this.buf
, famLenPos
);
107 public byte[] getQualifierArray() {
108 return CellUtil
.cloneQualifier(this);
112 public int getQualifierOffset() {
117 public int getQualifierLength() {
118 return getQualifierLength(getKeyLength(), getRowLength(), getFamilyLength());
121 int getQualifierLength(int keyLength
, int rlength
, int flength
) {
122 return keyLength
- (int) KeyValue
.getKeyDataStructureSize(rlength
, flength
, 0);
126 public long getTimestamp() {
127 return getTimestamp(getKeyLength());
130 long getTimestamp(int keyLength
) {
131 int offset
= getTimestampOffset(keyLength
);
132 return ByteBufferUtils
.toLong(this.buf
, offset
);
136 return ByteBufferUtils
.toInt(this.buf
, this.offset
);
139 private int getTimestampOffset(int keyLen
) {
140 return this.offset
+ KeyValue
.ROW_OFFSET
+ keyLen
- KeyValue
.TIMESTAMP_TYPE_SIZE
;
144 public byte getTypeByte() {
145 return getTypeByte(getKeyLength());
148 byte getTypeByte(int keyLen
) {
149 return ByteBufferUtils
.toByte(this.buf
, this.offset
+ keyLen
- 1 + KeyValue
.ROW_OFFSET
);
153 public long getSequenceId() {
158 public void setSequenceId(long seqId
) {
163 public byte[] getValueArray() {
164 return CellUtil
.cloneValue(this);
168 public int getValueOffset() {
173 public int getValueLength() {
174 return ByteBufferUtils
.toInt(this.buf
, this.offset
+ Bytes
.SIZEOF_INT
);
178 public byte[] getTagsArray() {
179 return PrivateCellUtil
.cloneTags(this);
183 public int getTagsOffset() {
188 public int getTagsLength() {
189 int tagsLen
= this.length
- (getKeyLength() + getValueLength()
190 + KeyValue
.KEYVALUE_INFRASTRUCTURE_SIZE
);
192 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is
193 // added to denote the tags
195 tagsLen
-= KeyValue
.TAGS_LENGTH_SIZE
;
201 public ByteBuffer
getRowByteBuffer() {
206 public int getRowPosition() {
207 return this.offset
+ KeyValue
.ROW_KEY_OFFSET
;
211 public ByteBuffer
getFamilyByteBuffer() {
216 public int getFamilyPosition() {
217 return getFamilyPosition(getFamilyLengthPosition());
220 public int getFamilyPosition(int familyLengthPosition
) {
221 return familyLengthPosition
+ Bytes
.SIZEOF_BYTE
;
225 public ByteBuffer
getQualifierByteBuffer() {
230 public int getQualifierPosition() {
231 return getQualifierPosition(getFamilyPosition(), getFamilyLength());
234 int getQualifierPosition(int familyPosition
, int familyLength
) {
235 return familyPosition
+ familyLength
;
239 public ByteBuffer
getValueByteBuffer() {
244 public int getValuePosition() {
245 return this.offset
+ KeyValue
.ROW_OFFSET
+ getKeyLength();
249 public ByteBuffer
getTagsByteBuffer() {
254 public int getTagsPosition() {
255 int tagsLen
= getTagsLength();
257 return this.offset
+ this.length
;
259 return this.offset
+ this.length
- tagsLen
;
263 public long heapSize() {
264 if (this.buf
.hasArray()) {
265 return ClassSize
.align(FIXED_OVERHEAD
+ length
);
267 return ClassSize
.align(FIXED_OVERHEAD
) + this.getSerializedSize();
271 public int write(OutputStream out
, boolean withTags
) throws IOException
{
272 int length
= getSerializedSize(withTags
);
273 ByteBufferUtils
.copyBufferToStream(out
, this.buf
, this.offset
, length
);
278 public int getSerializedSize(boolean withTags
) {
282 return getKeyLength() + this.getValueLength() + KeyValue
.KEYVALUE_INFRASTRUCTURE_SIZE
;
286 public int getSerializedSize() {
291 public void write(ByteBuffer buf
, int offset
) {
292 ByteBufferUtils
.copyFromBufferToBuffer(this.buf
, buf
, this.offset
, offset
, this.length
);
296 public String
toString() {
297 return CellUtil
.toString(this, true);
301 public void setTimestamp(long ts
) throws IOException
{
302 ByteBufferUtils
.copyFromArrayToBuffer(this.buf
, this.getTimestampOffset(), Bytes
.toBytes(ts
), 0,
306 private int getTimestampOffset() {
307 return this.offset
+ KeyValue
.KEYVALUE_INFRASTRUCTURE_SIZE
308 + getKeyLength() - KeyValue
.TIMESTAMP_TYPE_SIZE
;
312 public void setTimestamp(byte[] ts
) throws IOException
{
313 ByteBufferUtils
.copyFromArrayToBuffer(this.buf
, this.getTimestampOffset(), ts
, 0,
318 public ExtendedCell
deepClone() {
319 byte[] copy
= new byte[this.length
];
320 ByteBufferUtils
.copyFromBufferToArray(copy
, this.buf
, this.offset
, 0, this.length
);
321 KeyValue kv
= new KeyValue(copy
, 0, copy
.length
);
322 kv
.setSequenceId(this.getSequenceId());
327 * Needed doing 'contains' on List. Only compares the key portion, not the value.
330 public boolean equals(Object other
) {
331 if (!(other
instanceof Cell
)) {
334 return CellUtil
.equals(this, (Cell
) other
);
338 * In line with {@link #equals(Object)}, only uses the key portion, not the value.
341 public int hashCode() {
342 return calculateHashForKey(this);
345 private int calculateHashForKey(ByteBufferExtendedCell cell
) {
346 int rowHash
= ByteBufferUtils
.hashCode(cell
.getRowByteBuffer(), cell
.getRowPosition(),
347 cell
.getRowLength());
348 int familyHash
= ByteBufferUtils
.hashCode(cell
.getFamilyByteBuffer(), cell
.getFamilyPosition(),
349 cell
.getFamilyLength());
350 int qualifierHash
= ByteBufferUtils
.hashCode(cell
.getQualifierByteBuffer(),
351 cell
.getQualifierPosition(), cell
.getQualifierLength());
353 int hash
= 31 * rowHash
+ familyHash
;
354 hash
= 31 * hash
+ qualifierHash
;
355 hash
= 31 * hash
+ (int) cell
.getTimestamp();
356 hash
= 31 * hash
+ cell
.getTypeByte();