HBASE-23892 SecureTestCluster should allow its subclasses to pass their Class referen...
[hbase.git] / hbase-common / src / main / java / org / apache / hadoop / hbase / ByteBufferKeyValue.java
blobcaf11c3253f528fd63204e78744ec1af2e36038b
1 /**
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;
28 import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
30 /**
31 * This Cell is an implementation of {@link ByteBufferExtendedCell} where the data resides in
32 * off heap/ on heap ByteBuffer
34 @InterfaceAudience.Private
35 public class ByteBufferKeyValue extends ByteBufferExtendedCell {
37 protected final ByteBuffer buf;
38 protected final int offset;
39 protected final int length;
40 private long seqId = 0;
42 public static final int FIXED_OVERHEAD = ClassSize.OBJECT + ClassSize.REFERENCE
43 + (2 * Bytes.SIZEOF_INT) + Bytes.SIZEOF_LONG;
45 public ByteBufferKeyValue(ByteBuffer buf, int offset, int length, long seqId) {
46 this.buf = buf;
47 this.offset = offset;
48 this.length = length;
49 this.seqId = seqId;
52 public ByteBufferKeyValue(ByteBuffer buf, int offset, int length) {
53 this.buf = buf;
54 this.offset = offset;
55 this.length = length;
58 @VisibleForTesting
59 public ByteBuffer getBuffer() {
60 return this.buf;
63 @VisibleForTesting
64 public int getOffset() {
65 return this.offset;
68 @Override
69 public byte[] getRowArray() {
70 return CellUtil.cloneRow(this);
73 @Override
74 public int getRowOffset() {
75 return 0;
78 @Override
79 public short getRowLength() {
80 return ByteBufferUtils.toShort(this.buf, this.offset + KeyValue.ROW_OFFSET);
83 @Override
84 public byte[] getFamilyArray() {
85 return CellUtil.cloneFamily(this);
88 @Override
89 public int getFamilyOffset() {
90 return 0;
93 @Override
94 public byte getFamilyLength() {
95 return getFamilyLength(getFamilyLengthPosition());
98 int getFamilyLengthPosition() {
99 return getFamilyLengthPosition(getRowLength());
102 int getFamilyLengthPosition(int rowLength) {
103 return this.offset + KeyValue.ROW_KEY_OFFSET + rowLength;
106 byte getFamilyLength(int famLenPos) {
107 return ByteBufferUtils.toByte(this.buf, famLenPos);
110 @Override
111 public byte[] getQualifierArray() {
112 return CellUtil.cloneQualifier(this);
115 @Override
116 public int getQualifierOffset() {
117 return 0;
120 @Override
121 public int getQualifierLength() {
122 return getQualifierLength(getKeyLength(), getRowLength(), getFamilyLength());
125 int getQualifierLength(int keyLength, int rlength, int flength) {
126 return keyLength - (int) KeyValue.getKeyDataStructureSize(rlength, flength, 0);
129 @Override
130 public long getTimestamp() {
131 return getTimestamp(getKeyLength());
134 long getTimestamp(int keyLength) {
135 int offset = getTimestampOffset(keyLength);
136 return ByteBufferUtils.toLong(this.buf, offset);
139 int getKeyLength() {
140 return ByteBufferUtils.toInt(this.buf, this.offset);
143 private int getTimestampOffset(int keyLen) {
144 return this.offset + KeyValue.ROW_OFFSET + keyLen - KeyValue.TIMESTAMP_TYPE_SIZE;
147 @Override
148 public byte getTypeByte() {
149 return getTypeByte(getKeyLength());
152 byte getTypeByte(int keyLen) {
153 return ByteBufferUtils.toByte(this.buf, this.offset + keyLen - 1 + KeyValue.ROW_OFFSET);
156 @Override
157 public long getSequenceId() {
158 return this.seqId;
161 @Override
162 public void setSequenceId(long seqId) {
163 this.seqId = seqId;
166 @Override
167 public byte[] getValueArray() {
168 return CellUtil.cloneValue(this);
171 @Override
172 public int getValueOffset() {
173 return 0;
176 @Override
177 public int getValueLength() {
178 return ByteBufferUtils.toInt(this.buf, this.offset + Bytes.SIZEOF_INT);
181 @Override
182 public byte[] getTagsArray() {
183 return PrivateCellUtil.cloneTags(this);
186 @Override
187 public int getTagsOffset() {
188 return 0;
191 @Override
192 public int getTagsLength() {
193 int tagsLen = this.length - (getKeyLength() + getValueLength()
194 + KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE);
195 if (tagsLen > 0) {
196 // There are some Tag bytes in the byte[]. So reduce 2 bytes which is
197 // added to denote the tags
198 // length
199 tagsLen -= KeyValue.TAGS_LENGTH_SIZE;
201 return tagsLen;
204 @Override
205 public ByteBuffer getRowByteBuffer() {
206 return this.buf;
209 @Override
210 public int getRowPosition() {
211 return this.offset + KeyValue.ROW_KEY_OFFSET;
214 @Override
215 public ByteBuffer getFamilyByteBuffer() {
216 return this.buf;
219 @Override
220 public int getFamilyPosition() {
221 return getFamilyPosition(getFamilyLengthPosition());
224 public int getFamilyPosition(int familyLengthPosition) {
225 return familyLengthPosition + Bytes.SIZEOF_BYTE;
228 @Override
229 public ByteBuffer getQualifierByteBuffer() {
230 return this.buf;
233 @Override
234 public int getQualifierPosition() {
235 return getQualifierPosition(getFamilyPosition(), getFamilyLength());
238 int getQualifierPosition(int familyPosition, int familyLength) {
239 return familyPosition + familyLength;
242 @Override
243 public ByteBuffer getValueByteBuffer() {
244 return this.buf;
247 @Override
248 public int getValuePosition() {
249 return this.offset + KeyValue.ROW_OFFSET + getKeyLength();
252 @Override
253 public ByteBuffer getTagsByteBuffer() {
254 return this.buf;
257 @Override
258 public int getTagsPosition() {
259 int tagsLen = getTagsLength();
260 if (tagsLen == 0) {
261 return this.offset + this.length;
263 return this.offset + this.length - tagsLen;
266 @Override
267 public long heapSize() {
268 if (this.buf.hasArray()) {
269 return ClassSize.align(FIXED_OVERHEAD + length);
271 return ClassSize.align(FIXED_OVERHEAD) + this.getSerializedSize();
274 @Override
275 public int write(OutputStream out, boolean withTags) throws IOException {
276 int length = getSerializedSize(withTags);
277 ByteBufferUtils.copyBufferToStream(out, this.buf, this.offset, length);
278 return length;
281 @Override
282 public int getSerializedSize(boolean withTags) {
283 if (withTags) {
284 return this.length;
286 return getKeyLength() + this.getValueLength() + KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE;
289 @Override
290 public int getSerializedSize() {
291 return this.length;
294 @Override
295 public void write(ByteBuffer buf, int offset) {
296 ByteBufferUtils.copyFromBufferToBuffer(this.buf, buf, this.offset, offset, this.length);
299 @Override
300 public String toString() {
301 return CellUtil.toString(this, true);
304 @Override
305 public void setTimestamp(long ts) throws IOException {
306 ByteBufferUtils.copyFromArrayToBuffer(this.buf, this.getTimestampOffset(), Bytes.toBytes(ts), 0,
307 Bytes.SIZEOF_LONG);
310 private int getTimestampOffset() {
311 return this.offset + KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE
312 + getKeyLength() - KeyValue.TIMESTAMP_TYPE_SIZE;
315 @Override
316 public void setTimestamp(byte[] ts) throws IOException {
317 ByteBufferUtils.copyFromArrayToBuffer(this.buf, this.getTimestampOffset(), ts, 0,
318 Bytes.SIZEOF_LONG);
321 @Override
322 public ExtendedCell deepClone() {
323 byte[] copy = new byte[this.length];
324 ByteBufferUtils.copyFromBufferToArray(copy, this.buf, this.offset, 0, this.length);
325 KeyValue kv = new KeyValue(copy, 0, copy.length);
326 kv.setSequenceId(this.getSequenceId());
327 return kv;
331 * Needed doing 'contains' on List. Only compares the key portion, not the value.
333 @Override
334 public boolean equals(Object other) {
335 if (!(other instanceof Cell)) {
336 return false;
338 return CellUtil.equals(this, (Cell) other);
342 * In line with {@link #equals(Object)}, only uses the key portion, not the value.
344 @Override
345 public int hashCode() {
346 return calculateHashForKey(this);
349 private int calculateHashForKey(ByteBufferExtendedCell cell) {
350 int rowHash = ByteBufferUtils.hashCode(cell.getRowByteBuffer(), cell.getRowPosition(),
351 cell.getRowLength());
352 int familyHash = ByteBufferUtils.hashCode(cell.getFamilyByteBuffer(), cell.getFamilyPosition(),
353 cell.getFamilyLength());
354 int qualifierHash = ByteBufferUtils.hashCode(cell.getQualifierByteBuffer(),
355 cell.getQualifierPosition(), cell.getQualifierLength());
357 int hash = 31 * rowHash + familyHash;
358 hash = 31 * hash + qualifierHash;
359 hash = 31 * hash + (int) cell.getTimestamp();
360 hash = 31 * hash + cell.getTypeByte();
361 return hash;