HBASE-23892 SecureTestCluster should allow its subclasses to pass their Class referen...
[hbase.git] / hbase-common / src / main / java / org / apache / hadoop / hbase / nio / SingleByteBuff.java
blob797bfdc1fff5652d926551e9d0a209d6ccf6eb57
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;
27 import org.apache.hadoop.hbase.io.ByteBuffAllocator.Recycler;
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.hadoop.hbase.util.UnsafeAvailChecker;
32 import org.apache.yetus.audience.InterfaceAudience;
34 import sun.nio.ch.DirectBuffer;
36 /**
37 * An implementation of ByteBuff where a single BB backs the BBI. This just acts as a wrapper over a
38 * normal BB - offheap or onheap
40 @InterfaceAudience.Private
41 public class SingleByteBuff extends ByteBuff {
43 private static final boolean UNSAFE_AVAIL = UnsafeAvailChecker.isAvailable();
44 private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
46 // Underlying BB
47 private final ByteBuffer buf;
49 // To access primitive values from underlying ByteBuffer using Unsafe
50 private long unsafeOffset;
51 private Object unsafeRef = null;
53 public SingleByteBuff(ByteBuffer buf) {
54 this(NONE, buf);
57 public SingleByteBuff(Recycler recycler, ByteBuffer buf) {
58 this(new RefCnt(recycler), buf);
61 SingleByteBuff(RefCnt refCnt, ByteBuffer buf) {
62 this.refCnt = refCnt;
63 this.buf = buf;
64 if (buf.hasArray()) {
65 this.unsafeOffset = UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset();
66 this.unsafeRef = buf.array();
67 } else {
68 this.unsafeOffset = ((DirectBuffer) buf).address();
72 @Override
73 public int position() {
74 checkRefCount();
75 return this.buf.position();
78 @Override
79 public SingleByteBuff position(int position) {
80 checkRefCount();
81 this.buf.position(position);
82 return this;
85 @Override
86 public SingleByteBuff skip(int len) {
87 checkRefCount();
88 this.buf.position(this.buf.position() + len);
89 return this;
92 @Override
93 public SingleByteBuff moveBack(int len) {
94 checkRefCount();
95 this.buf.position(this.buf.position() - len);
96 return this;
99 @Override
100 public int capacity() {
101 checkRefCount();
102 return this.buf.capacity();
105 @Override
106 public int limit() {
107 checkRefCount();
108 return this.buf.limit();
111 @Override
112 public SingleByteBuff limit(int limit) {
113 checkRefCount();
114 this.buf.limit(limit);
115 return this;
118 @Override
119 public SingleByteBuff rewind() {
120 checkRefCount();
121 this.buf.rewind();
122 return this;
125 @Override
126 public SingleByteBuff mark() {
127 checkRefCount();
128 this.buf.mark();
129 return this;
132 @Override
133 public ByteBuffer asSubByteBuffer(int length) {
134 checkRefCount();
135 // Just return the single BB that is available
136 return this.buf;
139 @Override
140 public void asSubByteBuffer(int offset, int length, ObjectIntPair<ByteBuffer> pair) {
141 checkRefCount();
142 // Just return the single BB that is available
143 pair.setFirst(this.buf);
144 pair.setSecond(offset);
147 @Override
148 public int remaining() {
149 checkRefCount();
150 return this.buf.remaining();
153 @Override
154 public boolean hasRemaining() {
155 checkRefCount();
156 return buf.hasRemaining();
159 @Override
160 public SingleByteBuff reset() {
161 checkRefCount();
162 this.buf.reset();
163 return this;
166 @Override
167 public SingleByteBuff slice() {
168 checkRefCount();
169 return new SingleByteBuff(this.refCnt, this.buf.slice());
172 @Override
173 public SingleByteBuff duplicate() {
174 checkRefCount();
175 return new SingleByteBuff(this.refCnt, this.buf.duplicate());
178 @Override
179 public byte get() {
180 checkRefCount();
181 return buf.get();
184 @Override
185 public byte get(int index) {
186 checkRefCount();
187 if (UNSAFE_AVAIL) {
188 return UnsafeAccess.toByte(this.unsafeRef, this.unsafeOffset + index);
190 return this.buf.get(index);
193 @Override
194 public byte getByteAfterPosition(int offset) {
195 checkRefCount();
196 return get(this.buf.position() + offset);
199 @Override
200 public SingleByteBuff put(byte b) {
201 checkRefCount();
202 this.buf.put(b);
203 return this;
206 @Override
207 public SingleByteBuff put(int index, byte b) {
208 checkRefCount();
209 buf.put(index, b);
210 return this;
213 @Override
214 public void get(byte[] dst, int offset, int length) {
215 checkRefCount();
216 ByteBufferUtils.copyFromBufferToArray(dst, buf, buf.position(), offset, length);
217 buf.position(buf.position() + length);
220 @Override
221 public void get(int sourceOffset, byte[] dst, int offset, int length) {
222 checkRefCount();
223 ByteBufferUtils.copyFromBufferToArray(dst, buf, sourceOffset, offset, length);
226 @Override
227 public void get(byte[] dst) {
228 get(dst, 0, dst.length);
231 @Override
232 public SingleByteBuff put(int offset, ByteBuff src, int srcOffset, int length) {
233 checkRefCount();
234 if (src instanceof SingleByteBuff) {
235 ByteBufferUtils.copyFromBufferToBuffer(((SingleByteBuff) src).buf, this.buf, srcOffset,
236 offset, length);
237 } else {
238 // TODO we can do some optimization here? Call to asSubByteBuffer might
239 // create a copy.
240 ObjectIntPair<ByteBuffer> pair = new ObjectIntPair<>();
241 src.asSubByteBuffer(srcOffset, length, pair);
242 if (pair.getFirst() != null) {
243 ByteBufferUtils.copyFromBufferToBuffer(pair.getFirst(), this.buf, pair.getSecond(), offset,
244 length);
247 return this;
250 @Override
251 public SingleByteBuff put(byte[] src, int offset, int length) {
252 checkRefCount();
253 ByteBufferUtils.copyFromArrayToBuffer(this.buf, src, offset, length);
254 return this;
257 @Override
258 public SingleByteBuff put(byte[] src) {
259 checkRefCount();
260 return put(src, 0, src.length);
263 @Override
264 public boolean hasArray() {
265 checkRefCount();
266 return this.buf.hasArray();
269 @Override
270 public byte[] array() {
271 checkRefCount();
272 return this.buf.array();
275 @Override
276 public int arrayOffset() {
277 checkRefCount();
278 return this.buf.arrayOffset();
281 @Override
282 public short getShort() {
283 checkRefCount();
284 return this.buf.getShort();
287 @Override
288 public short getShort(int index) {
289 checkRefCount();
290 if (UNSAFE_UNALIGNED) {
291 return UnsafeAccess.toShort(unsafeRef, unsafeOffset + index);
293 return this.buf.getShort(index);
296 @Override
297 public short getShortAfterPosition(int offset) {
298 checkRefCount();
299 return getShort(this.buf.position() + offset);
302 @Override
303 public int getInt() {
304 checkRefCount();
305 return this.buf.getInt();
308 @Override
309 public SingleByteBuff putInt(int value) {
310 checkRefCount();
311 ByteBufferUtils.putInt(this.buf, value);
312 return this;
315 @Override
316 public int getInt(int index) {
317 checkRefCount();
318 if (UNSAFE_UNALIGNED) {
319 return UnsafeAccess.toInt(unsafeRef, unsafeOffset + index);
321 return this.buf.getInt(index);
324 @Override
325 public int getIntAfterPosition(int offset) {
326 checkRefCount();
327 return getInt(this.buf.position() + offset);
330 @Override
331 public long getLong() {
332 checkRefCount();
333 return this.buf.getLong();
336 @Override
337 public SingleByteBuff putLong(long value) {
338 checkRefCount();
339 ByteBufferUtils.putLong(this.buf, value);
340 return this;
343 @Override
344 public long getLong(int index) {
345 checkRefCount();
346 if (UNSAFE_UNALIGNED) {
347 return UnsafeAccess.toLong(unsafeRef, unsafeOffset + index);
349 return this.buf.getLong(index);
352 @Override
353 public long getLongAfterPosition(int offset) {
354 checkRefCount();
355 return getLong(this.buf.position() + offset);
358 @Override
359 public byte[] toBytes(int offset, int length) {
360 checkRefCount();
361 byte[] output = new byte[length];
362 ByteBufferUtils.copyFromBufferToArray(output, buf, offset, 0, length);
363 return output;
366 @Override
367 public void get(ByteBuffer out, int sourceOffset, int length) {
368 checkRefCount();
369 ByteBufferUtils.copyFromBufferToBuffer(buf, out, sourceOffset, length);
372 @Override
373 public int read(ReadableByteChannel channel) throws IOException {
374 checkRefCount();
375 return read(channel, buf, 0, CHANNEL_READER);
378 @Override
379 public int read(FileChannel channel, long offset) throws IOException {
380 checkRefCount();
381 return read(channel, buf, offset, FILE_READER);
384 @Override
385 public int write(FileChannel channel, long offset) throws IOException {
386 checkRefCount();
387 int total = 0;
388 while(buf.hasRemaining()) {
389 int len = channel.write(buf, offset);
390 total += len;
391 offset += len;
393 return total;
396 @Override
397 public ByteBuffer[] nioByteBuffers() {
398 checkRefCount();
399 return new ByteBuffer[] { this.buf };
402 @Override
403 public boolean equals(Object obj) {
404 if (!(obj instanceof SingleByteBuff)) {
405 return false;
407 return this.buf.equals(((SingleByteBuff) obj).buf);
410 @Override
411 public int hashCode() {
412 return this.buf.hashCode();
415 @Override
416 public SingleByteBuff retain() {
417 refCnt.retain();
418 return this;