All Downloads are FREE. Search and download functionalities are using the official Maven repository.

alluxio.network.protocol.databuffer.RefCountedNioByteBuf Maven / Gradle / Ivy

/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in alluxio.shaded.client.com.liance with the License, which is
 * available at www.apache.alluxio.shaded.client.org.licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.network.protocol.databuffer;

import alluxio.Constants;

import alluxio.shaded.client.com.google.alluxio.shaded.client.com.on.base.Preconditions;
import alluxio.shaded.client.io.netty.buffer.AbstractReferenceCountedByteBuf;
import alluxio.shaded.client.io.netty.buffer.ByteBuf;
import alluxio.shaded.client.io.netty.buffer.ByteBufAllocator;
import alluxio.shaded.client.io.netty.buffer.Unpooled;

import java.alluxio.shaded.client.io.IOException;
import java.alluxio.shaded.client.io.InputStream;
import java.alluxio.shaded.client.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;

/**
 * Reference counted NIO {@link ByteBuffer} wrapped in Netty {@link ByteBuf}.
 * This allows ByteBuffers to be explicitly deallocated when the ref count goes down to zero.
 * 
* Implementations are expected to allocate a {@link ByteBuffer} in its constructor, and deallocate * it in {@link AbstractReferenceCountedByteBuf#deallocate()} which will be called when * the buffer's reference count reaches zero. */ abstract class RefCountedNioByteBuf extends AbstractReferenceCountedByteBuf { protected final ByteBuffer mDelegate; protected int mCapacity; /** * Creates a new reference counted ByteBuf with the provided NIO ByteBuffer as backing storage. * The initial reference count is 1. The reader and writer indices are both 0. * * @param buffer the NIO buffer used as storage * @param capacity the initial capacity * @param maxCapacity the max capacity, must not be greater than buffer.capacity() */ protected RefCountedNioByteBuf(ByteBuffer buffer, int capacity, int maxCapacity) { super(maxCapacity); Preconditions.checkArgument(capacity <= maxCapacity); Preconditions.checkArgument(maxCapacity <= buffer.capacity()); buffer.clear(); // enforce big endianness buffer.order(ByteOrder.BIG_ENDIAN); mDelegate = buffer; mCapacity = capacity; clear(); } @Override protected byte _getByte(int index) { return mDelegate.get(index); } @Override protected short _getShort(int index) { return mDelegate.getShort(index); } @Override protected short _getShortLE(int index) { return Short.reverseBytes(_getShort(index)); } @Override protected int _getUnsignedMedium(int index) { byte first = _getByte(index); byte second = _getByte(index + 1); byte third = _getByte(index + 2); return (Byte.toUnsignedInt(first) << 16) | (Byte.toUnsignedInt(second) << 8) | Byte.toUnsignedInt(third); } @Override protected int _getUnsignedMediumLE(int index) { byte first = _getByte(index); byte second = _getByte(index + 1); byte third = _getByte(index + 2); return (Byte.toUnsignedInt(third) << 16) | (Byte.toUnsignedInt(second) << 8) | Byte.toUnsignedInt(first); } @Override protected int _getInt(int index) { return mDelegate.getInt(index); } @Override protected int _getIntLE(int index) { return Integer.reverseBytes(_getInt(index)); } @Override protected long _getLong(int index) { return mDelegate.getLong(index); } @Override protected long _getLongLE(int index) { return Long.reverseBytes(_getLong(index)); } @Override protected void _setByte(int index, int value) { mDelegate.put(index, (byte) value); } @Override protected void _setShort(int index, int value) { mDelegate.putShort(index, (short) value); } @Override protected void _setShortLE(int index, int value) { mDelegate.putShort(index, Short.reverseBytes((short) value)); } @Override protected void _setMedium(int index, int value) { byte first = (byte) ((value & 0x00ff0000) >> 16); byte second = (byte) ((value & 0x0000ff00) >> 8); byte third = (byte) (value & 0x000000ff); _setByte(index, first); _setByte(index + 1, second); _setByte(index + 2, third); } @Override protected void _setMediumLE(int index, int value) { byte first = (byte) ((value & 0x00ff0000) >> 16); byte second = (byte) ((value & 0x0000ff00) >> 8); byte third = (byte) (value & 0x000000ff); _setByte(index, third); _setByte(index + 1, second); _setByte(index + 2, first); } @Override protected void _setInt(int index, int value) { mDelegate.putInt(index, value); } @Override protected void _setIntLE(int index, int value) { mDelegate.putInt(index, Integer.reverseBytes(value)); } @Override protected void _setLong(int index, long value) { mDelegate.putLong(index, value); } @Override protected void _setLongLE(int index, long value) { mDelegate.putLong(index, Long.reverseBytes(value)); } @Override public int capacity() { return mCapacity; } @Override public ByteBuf capacity(int newCapacity) { Preconditions.checkArgument(newCapacity >= 0 && newCapacity <= maxCapacity(), "invalid new capacity %s, max capacity is %s", newCapacity, maxCapacity()); ensureAccessible(); mCapacity = newCapacity; return this; } @Override public ByteBufAllocator alloc() { // we are not associated with a ByteBuf allocator, as the wrapped ByteBuffer is not allocated // from any ByteBuf allocator // returning the default allocator, which will be used to allocate a new buffer // when ByteBuf.readBytes(int) is called return ByteBufAllocator.DEFAULT; } @Override public ByteOrder order() { assert mDelegate.order() == ByteOrder.BIG_ENDIAN; return ByteOrder.BIG_ENDIAN; } @Override public ByteBuf unwrap() { return null; } @Override public boolean isDirect() { return mDelegate.isDirect(); } @Override public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { ensureIndexInBounds(index, capacity(), dstIndex, dst.capacity(), length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); dst.setBytes(dstIndex, dup); return this; } @Override public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { ensureIndexInBounds(index, capacity(), dstIndex, dst.length, length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); dup.get(dst, dstIndex, length); return this; } @Override public ByteBuf getBytes(int index, ByteBuffer dst) { ensureIndexInBounds(index, capacity(), dst.position(), dst.capacity(), dst.remaining()); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + dst.remaining()); dst.put(dup); return this; } @Override public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { ensureIndexInBounds(index, capacity(), 0, Integer.MAX_VALUE, length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); if (dup.hasArray()) { byte[] byteArray = dup.array(); int arrayOffset = dup.arrayOffset(); out.write(byteArray, arrayOffset + index, length); } else { byte[] chunk = new byte[Math.min(length, 4 * Constants.KB)]; while (dup.remaining() > 0) { int transferLength = Math.min(chunk.length, dup.remaining()); dup.get(chunk, 0, transferLength); out.write(chunk, 0, transferLength); } } return this; } @Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { ensureIndexInBounds(index, capacity(), 0, Integer.MAX_VALUE, length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); return out.write(dup); } @Override public int getBytes(int index, FileChannel out, long position, int length) throws IOException { ensureIndexInBounds(index, capacity(), position, Long.MAX_VALUE, length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); return out.write(dup, position); } @Override public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { ensureIndexInBounds(srcIndex, src.capacity(), index, capacity(), length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index).limit(index + length); src.getBytes(srcIndex, dup); return this; } @Override public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { ensureIndexInBounds(srcIndex, src.length, index, capacity(), length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); dup.put(src, srcIndex, length); return this; } @Override public ByteBuf setBytes(int index, ByteBuffer src) { ensureIndexInBounds(src.position(), src.limit(), index, capacity(), src.remaining()); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + src.remaining()); dup.put(src); return this; } @Override public int setBytes(int index, InputStream in, int length) throws IOException { ensureIndexInBounds(0, Integer.MAX_VALUE, index, capacity(), length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); if (dup.hasArray()) { byte[] bufferArray = dup.array(); int arrayOffset = dup.arrayOffset(); return in.read(bufferArray, arrayOffset + index, length); } else { byte[] chunk = new byte[Math.min(length, 4 * Constants.KB)]; while (dup.remaining() > 0) { int transferLength = Math.min(chunk.length, dup.remaining()); int read = in.read(chunk, 0, transferLength); if (read < 0) { if (dup.position() == index) { // eof when not a single byte has been read so far, signal this to the caller return -1; } break; } dup.put(chunk, 0, read); } return dup.position() - index; } } @Override public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { ensureIndexInBounds(0, Integer.MAX_VALUE, index, capacity(), length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); return in.read(dup); } @Override public int setBytes(int index, FileChannel in, long position, int length) throws IOException { ensureIndexInBounds(position, in.size(), index, capacity(), length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); return in.read(dup, position); } @Override public ByteBuf copy(int index, int length) { ensureIndexInBounds(index, capacity(), 0, Long.MAX_VALUE, length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); return Unpooled.copiedBuffer(dup); } @Override public int nioBufferCount() { return 1; } @Override public ByteBuffer nioBuffer(int index, int length) { ensureIndexInBounds(index, capacity(), 0, Integer.MAX_VALUE, length); ByteBuffer dup = mDelegate.duplicate(); dup.position(index); dup.limit(index + length); return dup.slice(); } @Override public ByteBuffer internalNioBuffer(int index, int length) { ensureIndexInBounds(index, capacity(), 0, Integer.MAX_VALUE, length); return (ByteBuffer) mDelegate.duplicate().clear().position(index).limit(index + length); } @Override public ByteBuffer[] nioBuffers(int index, int length) { ByteBuffer[] buffers = new ByteBuffer[1]; buffers[0] = nioBuffer(index, length); return buffers; } @Override public boolean hasArray() { return mDelegate.hasArray(); } @Override public byte[] array() { ensureAccessible(); return mDelegate.array(); } @Override public int arrayOffset() { return mDelegate.arrayOffset(); } @Override public boolean hasMemoryAddress() { return false; } @Override public long memoryAddress() { throw new UnsupportedOperationException("memoryAddress()"); } private void ensureIndexInBounds( long index, long srcCapacity, long dstIndex, long dstCapacity, int length) { ensureAccessible(); if (srcCapacity < 0 || dstCapacity < 0 || length < 0) { throw new IndexOutOfBoundsException( String.format("negative capacity or length: srcCapacity %d, dstCapacity %d, length %d", srcCapacity, dstCapacity, length)); } if (index < 0 || index > srcCapacity) { throw new IndexOutOfBoundsException( String.format("invalid index %d, srcCapacity %d", index, srcCapacity)); } if (index + length < 0 || index + length > srcCapacity) { throw new IndexOutOfBoundsException( String.format("index %d + length %d exceeds srcCapacity %d", index, length, srcCapacity)); } if (dstIndex < 0 || dstIndex > dstCapacity) { throw new IndexOutOfBoundsException( String.format("invalid dstIndex %d, dstCapacity %d", dstIndex, dstCapacity)); } if (dstIndex + length < 0 || dstIndex + length > dstCapacity) { throw new IndexOutOfBoundsException( String.format("dstIndex %d + length %d exceeds dstCapacity %d", dstIndex, length, srcCapacity)); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy