HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-common / src / main / java / org / apache / hadoop / hbase / nio / SingleByteBuff.java
blob46c86a3f20b6c6600a1467ec643d8fafe5d9176b
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.nio;
20 import static org.apache.hadoop.hbase.io.ByteBuffAllocator.NONE;
22 import java.io.IOException;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.FileChannel;
25 import java.nio.channels.ReadableByteChannel;
26 import org.apache.hadoop.hbase.io.ByteBuffAllocator.Recycler;
27 import org.apache.hadoop.hbase.unsafe.HBasePlatformDependent;
28 import org.apache.hadoop.hbase.util.ByteBufferUtils;
29 import org.apache.hadoop.hbase.util.ObjectIntPair;
30 import org.apache.hadoop.hbase.util.UnsafeAccess;
31 import org.apache.yetus.audience.InterfaceAudience;
33 /**
34 * An implementation of ByteBuff where a single BB backs the BBI. This just acts as a wrapper over a
35 * normal BB - offheap or onheap
37 @InterfaceAudience.Private
38 public class SingleByteBuff extends ByteBuff {
40 private static final boolean UNSAFE_AVAIL = HBasePlatformDependent.isUnsafeAvailable();
41 private static final boolean UNSAFE_UNALIGNED = HBasePlatformDependent.unaligned();
43 // Underlying BB
44 private final ByteBuffer buf;
46 // To access primitive values from underlying ByteBuffer using Unsafe
47 private long unsafeOffset;
48 private Object unsafeRef = null;
50 public SingleByteBuff(ByteBuffer buf) {
51 this(NONE, buf);
54 public SingleByteBuff(Recycler recycler, ByteBuffer buf) {
55 this(new RefCnt(recycler), buf);
58 SingleByteBuff(RefCnt refCnt, ByteBuffer buf) {
59 this.refCnt = refCnt;
60 this.buf = buf;
61 if (buf.hasArray()) {
62 this.unsafeOffset = UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset();
63 this.unsafeRef = buf.array();
64 } else {
65 this.unsafeOffset = UnsafeAccess.directBufferAddress(buf);
69 @Override
70 public int position() {
71 checkRefCount();
72 return this.buf.position();
75 @Override
76 public SingleByteBuff position(int position) {
77 checkRefCount();
78 this.buf.position(position);
79 return this;
82 @Override
83 public SingleByteBuff skip(int len) {
84 checkRefCount();
85 this.buf.position(this.buf.position() + len);
86 return this;
89 @Override
90 public SingleByteBuff moveBack(int len) {
91 checkRefCount();
92 this.buf.position(this.buf.position() - len);
93 return this;
96 @Override
97 public int capacity() {
98 checkRefCount();
99 return this.buf.capacity();
102 @Override
103 public int limit() {
104 checkRefCount();
105 return this.buf.limit();
108 @Override
109 public SingleByteBuff limit(int limit) {
110 checkRefCount();
111 this.buf.limit(limit);
112 return this;
115 @Override
116 public SingleByteBuff rewind() {
117 checkRefCount();
118 this.buf.rewind();
119 return this;
122 @Override
123 public SingleByteBuff mark() {
124 checkRefCount();
125 this.buf.mark();
126 return this;
129 @Override
130 public ByteBuffer asSubByteBuffer(int length) {
131 checkRefCount();
132 // Just return the single BB that is available
133 return this.buf;
136 @Override
137 public void asSubByteBuffer(int offset, int length, ObjectIntPair<ByteBuffer> pair) {
138 checkRefCount();
139 // Just return the single BB that is available
140 pair.setFirst(this.buf);
141 pair.setSecond(offset);
144 @Override
145 public int remaining() {
146 checkRefCount();
147 return this.buf.remaining();
150 @Override
151 public boolean hasRemaining() {
152 checkRefCount();
153 return buf.hasRemaining();
156 @Override
157 public SingleByteBuff reset() {
158 checkRefCount();
159 this.buf.reset();
160 return this;
163 @Override
164 public SingleByteBuff slice() {
165 checkRefCount();
166 return new SingleByteBuff(this.refCnt, this.buf.slice());
169 @Override
170 public SingleByteBuff duplicate() {
171 checkRefCount();
172 return new SingleByteBuff(this.refCnt, this.buf.duplicate());
175 @Override
176 public byte get() {
177 checkRefCount();
178 return buf.get();
181 @Override
182 public byte get(int index) {
183 checkRefCount();
184 if (UNSAFE_AVAIL) {
185 return UnsafeAccess.toByte(this.unsafeRef, this.unsafeOffset + index);
187 return this.buf.get(index);
190 @Override
191 public byte getByteAfterPosition(int offset) {
192 checkRefCount();
193 return get(this.buf.position() + offset);
196 @Override
197 public SingleByteBuff put(byte b) {
198 checkRefCount();
199 this.buf.put(b);
200 return this;
203 @Override
204 public SingleByteBuff put(int index, byte b) {
205 checkRefCount();
206 buf.put(index, b);
207 return this;
210 @Override
211 public void get(byte[] dst, int offset, int length) {
212 checkRefCount();
213 ByteBufferUtils.copyFromBufferToArray(dst, buf, buf.position(), offset, length);
214 buf.position(buf.position() + length);
217 @Override
218 public void get(int sourceOffset, byte[] dst, int offset, int length) {
219 checkRefCount();
220 ByteBufferUtils.copyFromBufferToArray(dst, buf, sourceOffset, offset, length);
223 @Override
224 public void get(byte[] dst) {
225 get(dst, 0, dst.length);
228 @Override
229 public SingleByteBuff put(int offset, ByteBuff src, int srcOffset, int length) {
230 checkRefCount();
231 if (src instanceof SingleByteBuff) {
232 ByteBufferUtils.copyFromBufferToBuffer(((SingleByteBuff) src).buf, this.buf, srcOffset,
233 offset, length);
234 } else {
235 // TODO we can do some optimization here? Call to asSubByteBuffer might
236 // create a copy.
237 ObjectIntPair<ByteBuffer> pair = new ObjectIntPair<>();
238 src.asSubByteBuffer(srcOffset, length, pair);
239 if (pair.getFirst() != null) {
240 ByteBufferUtils.copyFromBufferToBuffer(pair.getFirst(), this.buf, pair.getSecond(), offset,
241 length);
244 return this;
247 @Override
248 public SingleByteBuff put(byte[] src, int offset, int length) {
249 checkRefCount();
250 ByteBufferUtils.copyFromArrayToBuffer(this.buf, src, offset, length);
251 return this;
254 @Override
255 public SingleByteBuff put(byte[] src) {
256 checkRefCount();
257 return put(src, 0, src.length);
260 @Override
261 public boolean hasArray() {
262 checkRefCount();
263 return this.buf.hasArray();
266 @Override
267 public byte[] array() {
268 checkRefCount();
269 return this.buf.array();
272 @Override
273 public int arrayOffset() {
274 checkRefCount();
275 return this.buf.arrayOffset();
278 @Override
279 public short getShort() {
280 checkRefCount();
281 return this.buf.getShort();
284 @Override
285 public short getShort(int index) {
286 checkRefCount();
287 if (UNSAFE_UNALIGNED) {
288 return UnsafeAccess.toShort(unsafeRef, unsafeOffset + index);
290 return this.buf.getShort(index);
293 @Override
294 public short getShortAfterPosition(int offset) {
295 checkRefCount();
296 return getShort(this.buf.position() + offset);
299 @Override
300 public int getInt() {
301 checkRefCount();
302 return this.buf.getInt();
305 @Override
306 public SingleByteBuff putInt(int value) {
307 checkRefCount();
308 ByteBufferUtils.putInt(this.buf, value);
309 return this;
312 @Override
313 public int getInt(int index) {
314 checkRefCount();
315 if (UNSAFE_UNALIGNED) {
316 return UnsafeAccess.toInt(unsafeRef, unsafeOffset + index);
318 return this.buf.getInt(index);
321 @Override
322 public int getIntAfterPosition(int offset) {
323 checkRefCount();
324 return getInt(this.buf.position() + offset);
327 @Override
328 public long getLong() {
329 checkRefCount();
330 return this.buf.getLong();
333 @Override
334 public SingleByteBuff putLong(long value) {
335 checkRefCount();
336 ByteBufferUtils.putLong(this.buf, value);
337 return this;
340 @Override
341 public long getLong(int index) {
342 checkRefCount();
343 if (UNSAFE_UNALIGNED) {
344 return UnsafeAccess.toLong(unsafeRef, unsafeOffset + index);
346 return this.buf.getLong(index);
349 @Override
350 public long getLongAfterPosition(int offset) {
351 checkRefCount();
352 return getLong(this.buf.position() + offset);
355 @Override
356 public byte[] toBytes(int offset, int length) {
357 checkRefCount();
358 byte[] output = new byte[length];
359 ByteBufferUtils.copyFromBufferToArray(output, buf, offset, 0, length);
360 return output;
363 @Override
364 public void get(ByteBuffer out, int sourceOffset, int length) {
365 checkRefCount();
366 ByteBufferUtils.copyFromBufferToBuffer(buf, out, sourceOffset, length);
369 @Override
370 public int read(ReadableByteChannel channel) throws IOException {
371 checkRefCount();
372 return read(channel, buf, 0, CHANNEL_READER);
375 @Override
376 public int read(FileChannel channel, long offset) throws IOException {
377 checkRefCount();
378 return read(channel, buf, offset, FILE_READER);
381 @Override
382 public int write(FileChannel channel, long offset) throws IOException {
383 checkRefCount();
384 int total = 0;
385 while(buf.hasRemaining()) {
386 int len = channel.write(buf, offset);
387 total += len;
388 offset += len;
390 return total;
393 @Override
394 public ByteBuffer[] nioByteBuffers() {
395 checkRefCount();
396 return new ByteBuffer[] { this.buf };
399 @Override
400 public boolean equals(Object obj) {
401 if (!(obj instanceof SingleByteBuff)) {
402 return false;
404 return this.buf.equals(((SingleByteBuff) obj).buf);
407 @Override
408 public int hashCode() {
409 return this.buf.hashCode();
412 @Override
413 public SingleByteBuff retain() {
414 refCnt.retain();
415 return this;