ByteBufAllocator API w/ ByteBuf perf improvements
This commit introduces a new API for ByteBuf allocation which fixes issue #643 along with refactoring of ByteBuf for simplicity and better performance. (see #62) A user can configure the ByteBufAllocator of a Channel via ChannelOption.ALLOCATOR or ChannelConfig.get/setAllocator(). The default allocator is currently UnpooledByteBufAllocator.HEAP_BY_DEFAULT. To allocate a buffer, do not use Unpooled anymore. do the following: ctx.alloc().buffer(...); // allocator chooses the buffer type. ctx.alloc().heapBuffer(...); ctx.alloc().directBuffer(...); To deallocate a buffer, use the unsafe free() operation: ((UnsafeByteBuf) buf).free(); The following is the list of the relevant changes: - Add ChannelInboundHandler.freeInboundBuffer() and ChannelOutboundHandler.freeOutboundBuffer() to let a user free the buffer he or she allocated. ChannelHandler adapter classes implement is already, so most users won't need to call free() by themselves. freeIn/OutboundBuffer() methods are invoked when a Channel is closed and deregistered. - All ByteBuf by contract must implement UnsafeByteBuf. To access an unsafe operation: ((UnsafeByteBuf) buf).internalNioBuffer() - Replace WrappedByteBuf and ByteBuf.Unsafe with UnsafeByteBuf to simplify overall class hierarchy and to avoid unnecesary instantiation of Unsafe instances on an unsafe operation. - Remove buffer reference counting which is confusing - Instantiate SwappedByteBuf lazily to avoid instantiation cost - Rename ChannelFutureFactory to ChannelPropertyAccess and move common methods between Channel and ChannelHandlerContext there. Also made it package-private to hide it from a user. - Remove unused unsafe operations such as newBuffer() - Add DetectionUtil.canFreeDirectBuffer() so that an allocator decides which buffer type to use safely
This commit is contained in:
parent
2adebc4c54
commit
81e2db10fa
@ -28,36 +28,24 @@ import java.nio.charset.Charset;
|
|||||||
/**
|
/**
|
||||||
* A skeletal implementation of a buffer.
|
* A skeletal implementation of a buffer.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractByteBuf implements ByteBuf {
|
public abstract class AbstractByteBuf implements UnsafeByteBuf {
|
||||||
|
|
||||||
private final SwappedByteBuf swappedBuf;
|
|
||||||
private final ByteOrder order;
|
|
||||||
private final int maxCapacity;
|
|
||||||
|
|
||||||
private int readerIndex;
|
private int readerIndex;
|
||||||
private int writerIndex;
|
private int writerIndex;
|
||||||
private int markedReaderIndex;
|
private int markedReaderIndex;
|
||||||
private int markedWriterIndex;
|
private int markedWriterIndex;
|
||||||
|
|
||||||
int refCnt = 1;
|
private final int maxCapacity;
|
||||||
|
|
||||||
protected AbstractByteBuf(ByteOrder endianness, int maxCapacity) {
|
private SwappedByteBuf swappedBuf;
|
||||||
if (endianness == null) {
|
|
||||||
throw new NullPointerException("endianness");
|
protected AbstractByteBuf(int maxCapacity) {
|
||||||
}
|
|
||||||
if (maxCapacity < 0) {
|
if (maxCapacity < 0) {
|
||||||
throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)");
|
throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)");
|
||||||
}
|
}
|
||||||
order = endianness;
|
|
||||||
swappedBuf = new SwappedByteBuf(this);
|
|
||||||
this.maxCapacity = maxCapacity;
|
this.maxCapacity = maxCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPooled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelBufType type() {
|
public ChannelBufType type() {
|
||||||
return ChannelBufType.BYTE;
|
return ChannelBufType.BYTE;
|
||||||
@ -266,19 +254,19 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
|||||||
return Math.min(newCapacity, maxCapacity);
|
return Math.min(newCapacity, maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final ByteOrder order() {
|
|
||||||
return order;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf order(ByteOrder endianness) {
|
public ByteBuf order(ByteOrder endianness) {
|
||||||
if (endianness == null) {
|
if (endianness == null) {
|
||||||
throw new NullPointerException("endianness");
|
throw new NullPointerException("endianness");
|
||||||
}
|
}
|
||||||
if (endianness == order()) {
|
if (endianness == order() || capacity() == 0) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwappedByteBuf swappedBuf = this.swappedBuf;
|
||||||
|
if (swappedBuf == null) {
|
||||||
|
this.swappedBuf = swappedBuf = new SwappedByteBuf(this);
|
||||||
|
}
|
||||||
return swappedBuf;
|
return swappedBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +509,9 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
|||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return Unpooled.EMPTY_BUFFER;
|
return Unpooled.EMPTY_BUFFER;
|
||||||
}
|
}
|
||||||
ByteBuf buf = unsafe().newBuffer(length);
|
|
||||||
|
// Use an unpooled heap buffer because there's no way to mandate a user to free the returned buffer.
|
||||||
|
ByteBuf buf = Unpooled.buffer(length, maxCapacity);
|
||||||
buf.writeBytes(this, readerIndex, length);
|
buf.writeBytes(this, readerIndex, length);
|
||||||
readerIndex += length;
|
readerIndex += length;
|
||||||
return buf;
|
return buf;
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
|
||||||
|
|
||||||
|
private final boolean directByDefault;
|
||||||
|
private final ByteBuf emptyBuf;
|
||||||
|
|
||||||
|
protected AbstractByteBufAllocator() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractByteBufAllocator(boolean directByDefault) {
|
||||||
|
this.directByDefault = directByDefault;
|
||||||
|
emptyBuf = new UnpooledHeapByteBuf(this, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf buffer() {
|
||||||
|
if (directByDefault) {
|
||||||
|
return directBuffer();
|
||||||
|
}
|
||||||
|
return heapBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf buffer(int initialCapacity) {
|
||||||
|
if (directByDefault) {
|
||||||
|
return directBuffer(initialCapacity);
|
||||||
|
}
|
||||||
|
return heapBuffer(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf buffer(int initialCapacity, int maxCapacity) {
|
||||||
|
if (directByDefault) {
|
||||||
|
return directBuffer(initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
return heapBuffer(initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf heapBuffer() {
|
||||||
|
return heapBuffer(256, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf heapBuffer(int initialCapacity) {
|
||||||
|
return buffer(initialCapacity, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {
|
||||||
|
if (initialCapacity == 0 && maxCapacity == 0) {
|
||||||
|
return emptyBuf;
|
||||||
|
}
|
||||||
|
return newHeapBuffer(initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf directBuffer() {
|
||||||
|
return directBuffer(256, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf directBuffer(int initialCapacity) {
|
||||||
|
return directBuffer(initialCapacity, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
|
||||||
|
if (initialCapacity == 0 && maxCapacity == 0) {
|
||||||
|
return emptyBuf;
|
||||||
|
}
|
||||||
|
return newDirectBuffer(initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);
|
||||||
|
protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);
|
||||||
|
}
|
@ -1,263 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 The Netty Project
|
|
||||||
*
|
|
||||||
* The Netty Project licenses this file to you under the Apache License,
|
|
||||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package io.netty.buffer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract base class for WrappedByteBuf implementations.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractWrappedByteBuf extends AbstractByteBuf implements WrappedByteBuf {
|
|
||||||
|
|
||||||
protected AbstractWrappedByteBuf(ByteOrder endianness, int maxCapacity) {
|
|
||||||
super(endianness, maxCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf capacity(int newCapacity) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf discardReadBytes() {
|
|
||||||
return (WrappedByteBuf) super.discardReadBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readerIndex(int readerIndex) {
|
|
||||||
return (WrappedByteBuf) super.readerIndex(readerIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writerIndex(int writerIndex) {
|
|
||||||
return (WrappedByteBuf) super.writerIndex(writerIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setIndex(int readerIndex, int writerIndex) {
|
|
||||||
return (WrappedByteBuf) super.setIndex(readerIndex, writerIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf clear() {
|
|
||||||
return (WrappedByteBuf) super.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf markReaderIndex() {
|
|
||||||
return (WrappedByteBuf) super.markReaderIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf resetReaderIndex() {
|
|
||||||
return (WrappedByteBuf) super.resetReaderIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf markWriterIndex() {
|
|
||||||
return (WrappedByteBuf) super.markWriterIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf resetWriterIndex() {
|
|
||||||
return (WrappedByteBuf) super.resetWriterIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf ensureWritableBytes(int minWritableBytes) {
|
|
||||||
return (WrappedByteBuf) super.ensureWritableBytes(minWritableBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst) {
|
|
||||||
return (WrappedByteBuf) super.getBytes(index, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int length) {
|
|
||||||
return (WrappedByteBuf) super.getBytes(index, dst, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf getBytes(int index, byte[] dst) {
|
|
||||||
return (WrappedByteBuf) super.getBytes(index, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setBoolean(int index, boolean value) {
|
|
||||||
return (WrappedByteBuf) super.setBoolean(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setChar(int index, int value) {
|
|
||||||
return (WrappedByteBuf) super.setChar(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setFloat(int index, float value) {
|
|
||||||
return (WrappedByteBuf) super.setFloat(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setDouble(int index, double value) {
|
|
||||||
return (WrappedByteBuf) super.setDouble(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src) {
|
|
||||||
return (WrappedByteBuf) super.setBytes(index, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int length) {
|
|
||||||
return (WrappedByteBuf) super.setBytes(index, src, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setBytes(int index, byte[] src) {
|
|
||||||
return (WrappedByteBuf) super.setBytes(index, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf setZero(int index, int length) {
|
|
||||||
return (WrappedByteBuf) super.setZero(index, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(ByteBuf dst) {
|
|
||||||
return (WrappedByteBuf) super.readBytes(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(ByteBuf dst, int length) {
|
|
||||||
return (WrappedByteBuf) super.readBytes(dst, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
|
|
||||||
return (WrappedByteBuf) super.readBytes(dst, dstIndex, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(byte[] dst) {
|
|
||||||
return (WrappedByteBuf) super.readBytes(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
|
||||||
return (WrappedByteBuf) super.readBytes(dst, dstIndex, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(ByteBuffer dst) {
|
|
||||||
return (WrappedByteBuf) super.readBytes(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf readBytes(OutputStream out, int length) throws IOException {
|
|
||||||
return (WrappedByteBuf) super.readBytes(out, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf skipBytes(int length) {
|
|
||||||
return (WrappedByteBuf) super.skipBytes(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBoolean(boolean value) {
|
|
||||||
return (WrappedByteBuf) super.writeBoolean(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeByte(int value) {
|
|
||||||
return (WrappedByteBuf) super.writeByte(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeShort(int value) {
|
|
||||||
return (WrappedByteBuf) super.writeShort(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeMedium(int value) {
|
|
||||||
return (WrappedByteBuf) super.writeMedium(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeInt(int value) {
|
|
||||||
return (WrappedByteBuf) super.writeInt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeLong(long value) {
|
|
||||||
return (WrappedByteBuf) super.writeLong(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeChar(int value) {
|
|
||||||
return (WrappedByteBuf) super.writeChar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeFloat(float value) {
|
|
||||||
return (WrappedByteBuf) super.writeFloat(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeDouble(double value) {
|
|
||||||
return (WrappedByteBuf) super.writeDouble(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBytes(ByteBuf src) {
|
|
||||||
return (WrappedByteBuf) super.writeBytes(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBytes(ByteBuf src, int length) {
|
|
||||||
return (WrappedByteBuf) super.writeBytes(src, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
|
|
||||||
return (WrappedByteBuf) super.writeBytes(src, srcIndex, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBytes(byte[] src) {
|
|
||||||
return (WrappedByteBuf) super.writeBytes(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBytes(byte[] src, int srcIndex, int length) {
|
|
||||||
return (WrappedByteBuf) super.writeBytes(src, srcIndex, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeBytes(ByteBuffer src) {
|
|
||||||
return (WrappedByteBuf) super.writeBytes(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WrappedByteBuf writeZero(int length) {
|
|
||||||
return (WrappedByteBuf) super.writeZero(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -251,6 +251,11 @@ public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
|
|||||||
*/
|
*/
|
||||||
int maxCapacity();
|
int maxCapacity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ByteBufAllocator} which created this buffer.
|
||||||
|
*/
|
||||||
|
ByteBufAllocator alloc();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a>
|
* Returns the <a href="http://en.wikipedia.org/wiki/Endianness">endianness</a>
|
||||||
* of this buffer.
|
* of this buffer.
|
||||||
@ -1831,53 +1836,4 @@ public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
String toString();
|
String toString();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an object that exposes unsafe expert-only operations which can lead to unspecified
|
|
||||||
* behavior.
|
|
||||||
*/
|
|
||||||
Unsafe unsafe();
|
|
||||||
|
|
||||||
interface Unsafe {
|
|
||||||
/**
|
|
||||||
* Returns the internal NIO buffer that is reused for I/O.
|
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer
|
|
||||||
*/
|
|
||||||
ByteBuffer nioBuffer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the internal NIO buffer array that is reused for I/O.
|
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer array
|
|
||||||
*/
|
|
||||||
ByteBuffer[] nioBuffers();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new buffer whose type is identical to the callee.
|
|
||||||
*
|
|
||||||
* @param initialCapacity the initial capacity of the new buffer
|
|
||||||
*/
|
|
||||||
ByteBuf newBuffer(int initialCapacity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard
|
|
||||||
* some, all, or none of read bytes depending on its internal implementation to reduce
|
|
||||||
* overall memory bandwidth consumption at the cost of potentially additional memory
|
|
||||||
* consumption.
|
|
||||||
*/
|
|
||||||
void discardSomeReadBytes();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increases the reference count of the buffer.
|
|
||||||
*/
|
|
||||||
void acquire();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decreases the reference count of the buffer. If decreased to 0, the internal memory
|
|
||||||
* block of the buffer will be deallocated. The result of accessing a freed buffer is
|
|
||||||
* unspecified and can even cause JVM crash.
|
|
||||||
*/
|
|
||||||
void release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
37
buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java
Normal file
37
buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public interface ByteBufAllocator {
|
||||||
|
|
||||||
|
ByteBuf buffer();
|
||||||
|
ByteBuf buffer(int initialCapacity);
|
||||||
|
ByteBuf buffer(int initialCapacity, int maxCapacity);
|
||||||
|
ByteBuf heapBuffer();
|
||||||
|
ByteBuf heapBuffer(int initialCapacity);
|
||||||
|
ByteBuf heapBuffer(int initialCapacity, int maxCapacity);
|
||||||
|
ByteBuf directBuffer();
|
||||||
|
ByteBuf directBuffer(int initialCapacity);
|
||||||
|
ByteBuf directBuffer(int initialCapacity, int maxCapacity);
|
||||||
|
ByteBuf ioBuffer();
|
||||||
|
|
||||||
|
void shutdown();
|
||||||
|
boolean isShutdown();
|
||||||
|
boolean isTerminated();
|
||||||
|
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
|
||||||
|
}
|
@ -20,10 +20,4 @@ public interface ChannelBuf {
|
|||||||
* The ChannelBufType which will be handled by the ChannelBuf implementation
|
* The ChannelBufType which will be handled by the ChannelBuf implementation
|
||||||
*/
|
*/
|
||||||
ChannelBufType type();
|
ChannelBufType type();
|
||||||
|
|
||||||
/**
|
|
||||||
* Return {@code true} if the ChannelBuf is pooled.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
boolean isPooled();
|
|
||||||
}
|
}
|
||||||
|
@ -39,26 +39,36 @@ import java.util.ListIterator;
|
|||||||
*/
|
*/
|
||||||
public class DefaultCompositeByteBuf extends AbstractByteBuf implements CompositeByteBuf {
|
public class DefaultCompositeByteBuf extends AbstractByteBuf implements CompositeByteBuf {
|
||||||
|
|
||||||
|
private static final ByteBuffer[] EMPTY_NIOBUFFERS = new ByteBuffer[0];
|
||||||
|
|
||||||
|
private final ByteBufAllocator alloc;
|
||||||
private final List<Component> components = new ArrayList<Component>();
|
private final List<Component> components = new ArrayList<Component>();
|
||||||
private final int maxNumComponents;
|
private final int maxNumComponents;
|
||||||
private final Unsafe unsafe = new CompositeUnsafe();
|
|
||||||
|
|
||||||
private Component lastAccessed;
|
private Component lastAccessed;
|
||||||
private int lastAccessedId;
|
private int lastAccessedId;
|
||||||
|
private boolean freed;
|
||||||
|
|
||||||
public DefaultCompositeByteBuf(int maxNumComponents) {
|
public DefaultCompositeByteBuf(ByteBufAllocator alloc, int maxNumComponents) {
|
||||||
super(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE);
|
super(Integer.MAX_VALUE);
|
||||||
|
if (alloc == null) {
|
||||||
|
throw new NullPointerException("alloc");
|
||||||
|
}
|
||||||
|
this.alloc = alloc;
|
||||||
this.maxNumComponents = maxNumComponents;
|
this.maxNumComponents = maxNumComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultCompositeByteBuf(int maxNumComponents, ByteBuf... buffers) {
|
public DefaultCompositeByteBuf(ByteBufAllocator alloc, int maxNumComponents, ByteBuf... buffers) {
|
||||||
super(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE);
|
super(Integer.MAX_VALUE);
|
||||||
|
if (alloc == null) {
|
||||||
|
throw new NullPointerException("alloc");
|
||||||
|
}
|
||||||
if (maxNumComponents < 2) {
|
if (maxNumComponents < 2) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
|
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.alloc = alloc;
|
||||||
this.maxNumComponents = maxNumComponents;
|
this.maxNumComponents = maxNumComponents;
|
||||||
|
|
||||||
addComponents0(0, buffers);
|
addComponents0(0, buffers);
|
||||||
@ -66,14 +76,17 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
setIndex(0, capacity());
|
setIndex(0, capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultCompositeByteBuf(int maxNumComponents, Iterable<ByteBuf> buffers) {
|
public DefaultCompositeByteBuf(ByteBufAllocator alloc, int maxNumComponents, Iterable<ByteBuf> buffers) {
|
||||||
super(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE);
|
super(Integer.MAX_VALUE);
|
||||||
|
if (alloc == null) {
|
||||||
|
throw new NullPointerException("alloc");
|
||||||
|
}
|
||||||
if (maxNumComponents < 2) {
|
if (maxNumComponents < 2) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
|
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.alloc = alloc;
|
||||||
this.maxNumComponents = maxNumComponents;
|
this.maxNumComponents = maxNumComponents;
|
||||||
addComponents0(0, buffers);
|
addComponents0(0, buffers);
|
||||||
consolidateIfNeeded();
|
consolidateIfNeeded();
|
||||||
@ -83,7 +96,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeByteBuf addComponent(ByteBuf buffer) {
|
public CompositeByteBuf addComponent(ByteBuf buffer) {
|
||||||
addComponent0(components.size(), buffer);
|
addComponent0(components.size(), buffer, false);
|
||||||
consolidateIfNeeded();
|
consolidateIfNeeded();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -104,12 +117,12 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
|
public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
|
||||||
addComponent0(cIndex, buffer);
|
addComponent0(cIndex, buffer, false);
|
||||||
consolidateIfNeeded();
|
consolidateIfNeeded();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addComponent0(int cIndex, ByteBuf buffer) {
|
private int addComponent0(int cIndex, ByteBuf buffer, boolean addedBySelf) {
|
||||||
checkComponentIndex(cIndex);
|
checkComponentIndex(cIndex);
|
||||||
|
|
||||||
if (buffer == null) {
|
if (buffer == null) {
|
||||||
@ -128,7 +141,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No need to consolidate - just add a component to the list.
|
// No need to consolidate - just add a component to the list.
|
||||||
Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice());
|
Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice(), addedBySelf);
|
||||||
if (cIndex == components.size()) {
|
if (cIndex == components.size()) {
|
||||||
components.add(c);
|
components.add(c);
|
||||||
if (cIndex == 0) {
|
if (cIndex == 0) {
|
||||||
@ -177,7 +190,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (b.readable()) {
|
if (b.readable()) {
|
||||||
cIndex = addComponent0(cIndex, b) + 1;
|
cIndex = addComponent0(cIndex, b, false) + 1;
|
||||||
int size = components.size();
|
int size = components.size();
|
||||||
if (cIndex > size) {
|
if (cIndex > size) {
|
||||||
cIndex = size;
|
cIndex = size;
|
||||||
@ -246,16 +259,17 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
if (numComponents > maxNumComponents) {
|
if (numComponents > maxNumComponents) {
|
||||||
final int capacity = components.get(numComponents - 1).endOffset;
|
final int capacity = components.get(numComponents - 1).endOffset;
|
||||||
|
|
||||||
ByteBuf consolidated = components.get(numComponents - 1).buf.unsafe().newBuffer(capacity);
|
ByteBuf consolidated = alloc().buffer(capacity);
|
||||||
|
|
||||||
// We're not using foreach to avoid creating an iterator.
|
// We're not using foreach to avoid creating an iterator.
|
||||||
// noinspection ForLoopReplaceableByForEach
|
// noinspection ForLoopReplaceableByForEach
|
||||||
for (int i = 0; i < numComponents; i ++) {
|
for (int i = 0; i < numComponents; i ++) {
|
||||||
ByteBuf b = components.get(i).buf;
|
Component c = components.get(i);
|
||||||
|
UnsafeByteBuf b = c.buf;
|
||||||
consolidated.writeBytes(b);
|
consolidated.writeBytes(b);
|
||||||
b.unsafe().release();
|
c.freeIfNecessary();
|
||||||
}
|
}
|
||||||
Component c = new Component(consolidated);
|
Component c = new Component(consolidated, true);
|
||||||
c.endOffset = c.length;
|
c.endOffset = c.length;
|
||||||
components.clear();
|
components.clear();
|
||||||
components.add(c);
|
components.add(c);
|
||||||
@ -263,6 +277,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkComponentIndex(int cIndex) {
|
private void checkComponentIndex(int cIndex) {
|
||||||
|
assert !freed;
|
||||||
if (cIndex < 0 || cIndex > components.size()) {
|
if (cIndex < 0 || cIndex > components.size()) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"cIndex: %d (expected: >= 0 && <= numComponents(%d))",
|
"cIndex: %d (expected: >= 0 && <= numComponents(%d))",
|
||||||
@ -271,6 +286,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkComponentIndex(int cIndex, int numComponents) {
|
private void checkComponentIndex(int cIndex, int numComponents) {
|
||||||
|
assert !freed;
|
||||||
if (cIndex < 0 || cIndex + numComponents > components.size()) {
|
if (cIndex < 0 || cIndex + numComponents > components.size()) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"cIndex: %d, numComponents: %d " +
|
"cIndex: %d, numComponents: %d " +
|
||||||
@ -317,6 +333,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ByteBuf> iterator() {
|
public Iterator<ByteBuf> iterator() {
|
||||||
|
assert !freed;
|
||||||
List<ByteBuf> list = new ArrayList<ByteBuf>(components.size());
|
List<ByteBuf> list = new ArrayList<ByteBuf>(components.size());
|
||||||
for (Component c: components) {
|
for (Component c: components) {
|
||||||
list.add(c.buf);
|
list.add(c.buf);
|
||||||
@ -413,6 +430,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeByteBuf capacity(int newCapacity) {
|
public CompositeByteBuf capacity(int newCapacity) {
|
||||||
|
assert !freed;
|
||||||
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
||||||
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
||||||
}
|
}
|
||||||
@ -422,13 +440,15 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
final int paddingLength = newCapacity - oldCapacity;
|
final int paddingLength = newCapacity - oldCapacity;
|
||||||
ByteBuf padding;
|
ByteBuf padding;
|
||||||
if (components.isEmpty()) {
|
if (components.isEmpty()) {
|
||||||
padding = new HeapByteBuf(paddingLength, paddingLength);
|
padding = alloc().buffer(paddingLength, paddingLength);
|
||||||
|
padding.setIndex(0, paddingLength);
|
||||||
|
addComponent0(0, padding, true);
|
||||||
} else {
|
} else {
|
||||||
Component last = components.get(components.size() - 1);
|
padding = alloc().buffer(paddingLength);
|
||||||
padding = last.buf.unsafe().newBuffer(paddingLength);
|
padding.setIndex(0, paddingLength);
|
||||||
|
addComponent0(components.size(), padding, true);
|
||||||
|
consolidateIfNeeded();
|
||||||
}
|
}
|
||||||
padding.setIndex(0, paddingLength);
|
|
||||||
addComponent(padding);
|
|
||||||
} else if (newCapacity < oldCapacity) {
|
} else if (newCapacity < oldCapacity) {
|
||||||
int bytesToTrim = oldCapacity - newCapacity;
|
int bytesToTrim = oldCapacity - newCapacity;
|
||||||
for (ListIterator<Component> i = components.listIterator(components.size()); i.hasPrevious();) {
|
for (ListIterator<Component> i = components.listIterator(components.size()); i.hasPrevious();) {
|
||||||
@ -440,10 +460,9 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace the last component with the trimmed slice.
|
// Replace the last component with the trimmed slice.
|
||||||
Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim));
|
Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim), c.allocatedBySelf);
|
||||||
newC.offset = c.offset;
|
newC.offset = c.offset;
|
||||||
newC.endOffset = newC.offset + newC.length;
|
newC.endOffset = newC.offset + newC.length;
|
||||||
c.buf.unsafe().release();
|
|
||||||
i.set(newC);
|
i.set(newC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -457,6 +476,16 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return ByteOrder.BIG_ENDIAN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int numComponents() {
|
public int numComponents() {
|
||||||
return components.size();
|
return components.size();
|
||||||
@ -469,6 +498,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int toComponentIndex(int offset) {
|
public int toComponentIndex(int offset) {
|
||||||
|
assert !freed;
|
||||||
if (offset < 0 || offset >= capacity()) {
|
if (offset < 0 || offset >= capacity()) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
|
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
|
||||||
@ -941,7 +971,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
+ (index + length) + ", maximum is " + capacity());
|
+ (index + length) + ", maximum is " + capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuf dst = unsafe().newBuffer(length);
|
ByteBuf dst = Unpooled.buffer(length);
|
||||||
copyTo(index, length, componentId, dst);
|
copyTo(index, length, componentId, dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -977,6 +1007,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component findComponent(int offset) {
|
private Component findComponent(int offset) {
|
||||||
|
assert !freed;
|
||||||
if (offset < 0 || offset >= capacity()) {
|
if (offset < 0 || offset >= capacity()) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
|
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
|
||||||
@ -1033,6 +1064,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ByteBuffer copiedNioBuffer(int index, int length) {
|
private ByteBuffer copiedNioBuffer(int index, int length) {
|
||||||
|
assert !freed;
|
||||||
if (components.size() == 1) {
|
if (components.size() == 1) {
|
||||||
return toNioBuffer(components.get(0).buf, index, length);
|
return toNioBuffer(components.get(0).buf, index, length);
|
||||||
}
|
}
|
||||||
@ -1061,7 +1093,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
throw new IndexOutOfBoundsException("index must be >= 0");
|
throw new IndexOutOfBoundsException("index must be >= 0");
|
||||||
}
|
}
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return new ByteBuffer[0];
|
return EMPTY_NIOBUFFERS;
|
||||||
}
|
}
|
||||||
int componentId = toComponentIndex(index);
|
int componentId = toComponentIndex(index);
|
||||||
|
|
||||||
@ -1092,6 +1124,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeByteBuf consolidate() {
|
public CompositeByteBuf consolidate() {
|
||||||
|
assert !freed;
|
||||||
final int numComponents = numComponents();
|
final int numComponents = numComponents();
|
||||||
if (numComponents <= 1) {
|
if (numComponents <= 1) {
|
||||||
return this;
|
return this;
|
||||||
@ -1099,16 +1132,17 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
final Component last = components.get(numComponents - 1);
|
final Component last = components.get(numComponents - 1);
|
||||||
final int capacity = last.endOffset;
|
final int capacity = last.endOffset;
|
||||||
final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity);
|
final ByteBuf consolidated = alloc().buffer(capacity);
|
||||||
|
|
||||||
for (int i = 0; i < numComponents; i ++) {
|
for (int i = 0; i < numComponents; i ++) {
|
||||||
ByteBuf b = components.get(i).buf;
|
Component c = components.get(i);
|
||||||
|
UnsafeByteBuf b = c.buf;
|
||||||
consolidated.writeBytes(b);
|
consolidated.writeBytes(b);
|
||||||
b.unsafe().release();
|
c.freeIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
components.clear();
|
components.clear();
|
||||||
components.add(new Component(consolidated));
|
components.add(new Component(consolidated, true));
|
||||||
updateComponentOffsets(0);
|
updateComponentOffsets(0);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -1123,22 +1157,24 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
final int endCIndex = cIndex + numComponents;
|
final int endCIndex = cIndex + numComponents;
|
||||||
final Component last = components.get(endCIndex - 1);
|
final Component last = components.get(endCIndex - 1);
|
||||||
final int capacity = last.endOffset - components.get(cIndex).offset;
|
final int capacity = last.endOffset - components.get(cIndex).offset;
|
||||||
final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity);
|
final ByteBuf consolidated = alloc().buffer(capacity);
|
||||||
|
|
||||||
for (int i = cIndex; i < endCIndex; i ++) {
|
for (int i = cIndex; i < endCIndex; i ++) {
|
||||||
ByteBuf b = components.get(i).buf;
|
Component c = components.get(i);
|
||||||
|
ByteBuf b = c.buf;
|
||||||
consolidated.writeBytes(b);
|
consolidated.writeBytes(b);
|
||||||
b.unsafe().release();
|
c.freeIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
components.subList(cIndex + 1, endCIndex).clear();
|
components.subList(cIndex + 1, endCIndex).clear();
|
||||||
components.set(cIndex, new Component(consolidated));
|
components.set(cIndex, new Component(consolidated, true));
|
||||||
updateComponentOffsets(cIndex);
|
updateComponentOffsets(cIndex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeByteBuf discardReadComponents() {
|
public CompositeByteBuf discardReadComponents() {
|
||||||
|
assert !freed;
|
||||||
final int readerIndex = readerIndex();
|
final int readerIndex = readerIndex();
|
||||||
if (readerIndex == 0) {
|
if (readerIndex == 0) {
|
||||||
return this;
|
return this;
|
||||||
@ -1148,7 +1184,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
int writerIndex = writerIndex();
|
int writerIndex = writerIndex();
|
||||||
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
||||||
for (Component c: components) {
|
for (Component c: components) {
|
||||||
c.buf.unsafe().release();
|
c.freeIfNecessary();
|
||||||
}
|
}
|
||||||
components.clear();
|
components.clear();
|
||||||
setIndex(0, 0);
|
setIndex(0, 0);
|
||||||
@ -1159,7 +1195,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
// Remove read components.
|
// Remove read components.
|
||||||
int firstComponentId = toComponentIndex(readerIndex);
|
int firstComponentId = toComponentIndex(readerIndex);
|
||||||
for (int i = 0; i < firstComponentId; i ++) {
|
for (int i = 0; i < firstComponentId; i ++) {
|
||||||
components.get(i).buf.unsafe().release();
|
components.get(i).freeIfNecessary();
|
||||||
}
|
}
|
||||||
components.subList(0, firstComponentId).clear();
|
components.subList(0, firstComponentId).clear();
|
||||||
|
|
||||||
@ -1173,6 +1209,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeByteBuf discardReadBytes() {
|
public CompositeByteBuf discardReadBytes() {
|
||||||
|
assert !freed;
|
||||||
final int readerIndex = readerIndex();
|
final int readerIndex = readerIndex();
|
||||||
if (readerIndex == 0) {
|
if (readerIndex == 0) {
|
||||||
return this;
|
return this;
|
||||||
@ -1182,7 +1219,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
int writerIndex = writerIndex();
|
int writerIndex = writerIndex();
|
||||||
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
||||||
for (Component c: components) {
|
for (Component c: components) {
|
||||||
c.buf.unsafe().release();
|
c.freeIfNecessary();
|
||||||
}
|
}
|
||||||
components.clear();
|
components.clear();
|
||||||
setIndex(0, 0);
|
setIndex(0, 0);
|
||||||
@ -1193,7 +1230,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
// Remove read components.
|
// Remove read components.
|
||||||
int firstComponentId = toComponentIndex(readerIndex);
|
int firstComponentId = toComponentIndex(readerIndex);
|
||||||
for (int i = 0; i < firstComponentId; i ++) {
|
for (int i = 0; i < firstComponentId; i ++) {
|
||||||
components.get(i).buf.unsafe().release();
|
components.get(i).freeIfNecessary();
|
||||||
}
|
}
|
||||||
components.subList(0, firstComponentId).clear();
|
components.subList(0, firstComponentId).clear();
|
||||||
|
|
||||||
@ -1204,8 +1241,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
// new slice would be empty, so remove instead
|
// new slice would be empty, so remove instead
|
||||||
components.remove(0);
|
components.remove(0);
|
||||||
} else {
|
} else {
|
||||||
Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment));
|
Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment), c.allocatedBySelf);
|
||||||
c.buf.unsafe().release();
|
|
||||||
components.set(0, newC);
|
components.set(0, newC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1224,14 +1260,29 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class Component {
|
private static final class Component {
|
||||||
final ByteBuf buf;
|
final UnsafeByteBuf buf;
|
||||||
final int length;
|
final int length;
|
||||||
|
final boolean allocatedBySelf;
|
||||||
int offset;
|
int offset;
|
||||||
int endOffset;
|
int endOffset;
|
||||||
|
|
||||||
Component(ByteBuf buf) {
|
Component(ByteBuf buf, boolean allocatedBySelf) {
|
||||||
this.buf = buf;
|
this.buf = (UnsafeByteBuf) buf;
|
||||||
length = buf.readableBytes();
|
length = buf.readableBytes();
|
||||||
|
this.allocatedBySelf = allocatedBySelf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeIfNecessary() {
|
||||||
|
if (!allocatedBySelf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap so that we can free slices, too.
|
||||||
|
UnsafeByteBuf buf;
|
||||||
|
for (buf = this.buf; buf.unwrap() != null; buf = (UnsafeByteBuf) buf.unwrap()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buf.free(); // We should not get a NPE here. If so, it must be a bug.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1458,68 +1509,47 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer[] nioBuffers() {
|
||||||
return unsafe;
|
return nioBuffers(readerIndex(), readableBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class CompositeUnsafe implements Unsafe {
|
@Override
|
||||||
@Override
|
public ByteBuffer internalNioBuffer() {
|
||||||
public ByteBuffer nioBuffer() {
|
if (components.size() == 1) {
|
||||||
if (components.size() == 1) {
|
return components.get(0).buf.internalNioBuffer();
|
||||||
return components.get(0).buf.unsafe().nioBuffer();
|
}
|
||||||
}
|
throw new UnsupportedOperationException();
|
||||||
throw new UnsupportedOperationException();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
|
ByteBuffer[] nioBuffers = new ByteBuffer[components.size()];
|
||||||
|
int index = 0;
|
||||||
|
for (Component component : components) {
|
||||||
|
nioBuffers[index++] = component.buf.internalNioBuffer();
|
||||||
|
}
|
||||||
|
return nioBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
discardReadComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free() {
|
||||||
|
if (freed) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
freed = true;
|
||||||
public ByteBuffer[] nioBuffers() {
|
for (Component c: components) {
|
||||||
ByteBuffer[] nioBuffers = new ByteBuffer[components.size()];
|
c.freeIfNecessary();
|
||||||
int index = 0;
|
|
||||||
for (Component component : components) {
|
|
||||||
nioBuffers[index++] = component.buf.unsafe().nioBuffer();
|
|
||||||
}
|
|
||||||
return nioBuffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf newBuffer(int initialCapacity) {
|
|
||||||
CompositeByteBuf buf = new DefaultCompositeByteBuf(maxNumComponents);
|
|
||||||
buf.addComponent(new HeapByteBuf(new byte[initialCapacity], initialCapacity));
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discardSomeReadBytes() {
|
|
||||||
discardReadComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acquire() {
|
|
||||||
if (refCnt <= 0) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
refCnt ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release() {
|
|
||||||
if (refCnt <= 0) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
refCnt --;
|
|
||||||
if (refCnt == 0) {
|
|
||||||
for (Component c: components) {
|
|
||||||
c.buf.unsafe().release();
|
|
||||||
}
|
|
||||||
|
|
||||||
components.clear();
|
|
||||||
lastAccessed = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer[] nioBuffers() {
|
public ByteBuf unwrap() {
|
||||||
return nioBuffers(readerIndex(), readableBytes());
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,6 @@ public class DefaultMessageBuf<T> extends ArrayDeque<T> implements MessageBuf<T>
|
|||||||
super(initialCapacity);
|
super(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPooled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelBufType type() {
|
public ChannelBufType type() {
|
||||||
return ChannelBufType.MESSAGE;
|
return ChannelBufType.MESSAGE;
|
||||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
|
|
||||||
@ -28,13 +29,12 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
* parent. It is recommended to use {@link ByteBuf#duplicate()} instead
|
* parent. It is recommended to use {@link ByteBuf#duplicate()} instead
|
||||||
* of calling the constructor explicitly.
|
* of calling the constructor explicitly.
|
||||||
*/
|
*/
|
||||||
public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
public class DuplicatedByteBuf extends AbstractByteBuf {
|
||||||
|
|
||||||
private final Unsafe unsafe = new DuplicatedUnsafe();
|
private final UnsafeByteBuf buffer;
|
||||||
final ByteBuf buffer;
|
|
||||||
|
|
||||||
public DuplicatedByteBuf(ByteBuf buffer) {
|
public DuplicatedByteBuf(UnsafeByteBuf buffer) {
|
||||||
super(buffer.order(), buffer.maxCapacity());
|
super(buffer.maxCapacity());
|
||||||
|
|
||||||
if (buffer instanceof DuplicatedByteBuf) {
|
if (buffer instanceof DuplicatedByteBuf) {
|
||||||
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
||||||
@ -43,8 +43,6 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||||
|
|
||||||
buffer.unsafe().acquire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -52,6 +50,16 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return buffer.alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return buffer.order();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirect() {
|
public boolean isDirect() {
|
||||||
return buffer.isDirect();
|
return buffer.isDirect();
|
||||||
@ -63,7 +71,7 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf capacity(int newCapacity) {
|
public ByteBuf capacity(int newCapacity) {
|
||||||
buffer.capacity(newCapacity);
|
buffer.capacity(newCapacity);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -119,73 +127,73 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
buffer.getBytes(index, dst, dstIndex, length);
|
buffer.getBytes(index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
buffer.getBytes(index, dst, dstIndex, length);
|
buffer.getBytes(index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
buffer.getBytes(index, dst);
|
buffer.getBytes(index, dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setByte(int index, int value) {
|
public ByteBuf setByte(int index, int value) {
|
||||||
buffer.setByte(index, value);
|
buffer.setByte(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setShort(int index, int value) {
|
public ByteBuf setShort(int index, int value) {
|
||||||
buffer.setShort(index, value);
|
buffer.setShort(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setMedium(int index, int value) {
|
public ByteBuf setMedium(int index, int value) {
|
||||||
buffer.setMedium(index, value);
|
buffer.setMedium(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setInt(int index, int value) {
|
public ByteBuf setInt(int index, int value) {
|
||||||
buffer.setInt(index, value);
|
buffer.setInt(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setLong(int index, long value) {
|
public ByteBuf setLong(int index, long value) {
|
||||||
buffer.setLong(index, value);
|
buffer.setLong(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
buffer.setBytes(index, src, srcIndex, length);
|
buffer.setBytes(index, src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
buffer.setBytes(index, src, srcIndex, length);
|
buffer.setBytes(index, src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
buffer.setBytes(index, src);
|
buffer.setBytes(index, src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length)
|
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
buffer.getBytes(index, out, length);
|
buffer.getBytes(index, out, length);
|
||||||
return this;
|
return this;
|
||||||
@ -230,40 +238,22 @@ public class DuplicatedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer internalNioBuffer() {
|
||||||
return unsafe;
|
return buffer.internalNioBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class DuplicatedUnsafe implements Unsafe {
|
@Override
|
||||||
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
|
return buffer.internalNioBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer nioBuffer() {
|
public void discardSomeReadBytes() {
|
||||||
return buffer.unsafe().nioBuffer();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer[] nioBuffers() {
|
public void free() {
|
||||||
return buffer.unsafe().nioBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf newBuffer(int initialCapacity) {
|
|
||||||
return buffer.unsafe().newBuffer(initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discardSomeReadBytes() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acquire() {
|
|
||||||
buffer.unsafe().acquire();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release() {
|
|
||||||
buffer.unsafe().release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,6 @@ public class QueueBackedMessageBuf<T> implements MessageBuf<T> {
|
|||||||
this.queue = queue;
|
this.queue = queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPooled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelBufType type() {
|
public ChannelBufType type() {
|
||||||
return ChannelBufType.MESSAGE;
|
return ChannelBufType.MESSAGE;
|
||||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.nio.ReadOnlyBufferException;
|
import java.nio.ReadOnlyBufferException;
|
||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
@ -28,27 +29,36 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
* recommended to use {@link Unpooled#unmodifiableBuffer(ByteBuf)}
|
* recommended to use {@link Unpooled#unmodifiableBuffer(ByteBuf)}
|
||||||
* instead of calling the constructor explicitly.
|
* instead of calling the constructor explicitly.
|
||||||
*/
|
*/
|
||||||
public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
public class ReadOnlyByteBuf extends AbstractByteBuf {
|
||||||
|
|
||||||
private final ByteBuf buffer;
|
private final UnsafeByteBuf buffer;
|
||||||
|
|
||||||
|
public ReadOnlyByteBuf(UnsafeByteBuf buffer) {
|
||||||
|
super(buffer.maxCapacity());
|
||||||
|
|
||||||
|
if (buffer instanceof ReadOnlyByteBuf) {
|
||||||
|
buffer = ((ReadOnlyByteBuf) buffer).buffer;
|
||||||
|
}
|
||||||
|
|
||||||
public ReadOnlyByteBuf(ByteBuf buffer) {
|
|
||||||
super(buffer.order(), buffer.maxCapacity());
|
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlyByteBuf(ReadOnlyByteBuf buffer) {
|
|
||||||
super(buffer.buffer.order(), buffer.maxCapacity());
|
|
||||||
this.buffer = buffer.buffer;
|
|
||||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf unwrap() {
|
public ByteBuf unwrap() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return buffer.alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return buffer.order();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirect() {
|
public boolean isDirect() {
|
||||||
return buffer.isDirect();
|
return buffer.isDirect();
|
||||||
@ -70,47 +80,47 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf discardReadBytes() {
|
public ByteBuf discardReadBytes() {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setByte(int index, int value) {
|
public ByteBuf setByte(int index, int value) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setShort(int index, int value) {
|
public ByteBuf setShort(int index, int value) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setMedium(int index, int value) {
|
public ByteBuf setMedium(int index, int value) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setInt(int index, int value) {
|
public ByteBuf setInt(int index, int value) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setLong(int index, long value) {
|
public ByteBuf setLong(int index, long value) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,26 +143,26 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length)
|
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
buffer.getBytes(index, out, length);
|
buffer.getBytes(index, out, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
buffer.getBytes(index, dst, dstIndex, length);
|
buffer.getBytes(index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
buffer.getBytes(index, dst, dstIndex, length);
|
buffer.getBytes(index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
buffer.getBytes(index, dst);
|
buffer.getBytes(index, dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -169,7 +179,7 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf slice(int index, int length) {
|
public ByteBuf slice(int index, int length) {
|
||||||
return new ReadOnlyByteBuf(buffer.slice(index, length));
|
return new ReadOnlyByteBuf((UnsafeByteBuf) buffer.slice(index, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -223,12 +233,25 @@ public class ReadOnlyByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf capacity(int newCapacity) {
|
public ByteBuf capacity(int newCapacity) {
|
||||||
throw new ReadOnlyBufferException();
|
throw new ReadOnlyBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer internalNioBuffer() {
|
||||||
return buffer.unsafe();
|
return buffer.internalNioBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
|
return buffer.internalNioBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free() { }
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
|
|
||||||
@ -29,15 +30,14 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
* {@link ByteBuf#slice(int, int)} instead of calling the constructor
|
* {@link ByteBuf#slice(int, int)} instead of calling the constructor
|
||||||
* explicitly.
|
* explicitly.
|
||||||
*/
|
*/
|
||||||
public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
public class SlicedByteBuf extends AbstractByteBuf {
|
||||||
|
|
||||||
private final Unsafe unsafe = new SlicedUnsafe();
|
private final UnsafeByteBuf buffer;
|
||||||
private final ByteBuf buffer;
|
|
||||||
private final int adjustment;
|
private final int adjustment;
|
||||||
private final int length;
|
private final int length;
|
||||||
|
|
||||||
public SlicedByteBuf(ByteBuf buffer, int index, int length) {
|
public SlicedByteBuf(UnsafeByteBuf buffer, int index, int length) {
|
||||||
super(buffer.order(), length);
|
super(length);
|
||||||
if (index < 0 || index > buffer.capacity()) {
|
if (index < 0 || index > buffer.capacity()) {
|
||||||
throw new IndexOutOfBoundsException("Invalid index of " + index
|
throw new IndexOutOfBoundsException("Invalid index of " + index
|
||||||
+ ", maximum is " + buffer.capacity());
|
+ ", maximum is " + buffer.capacity());
|
||||||
@ -52,7 +52,7 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
this.buffer = ((SlicedByteBuf) buffer).buffer;
|
this.buffer = ((SlicedByteBuf) buffer).buffer;
|
||||||
adjustment = ((SlicedByteBuf) buffer).adjustment + index;
|
adjustment = ((SlicedByteBuf) buffer).adjustment + index;
|
||||||
} else if (buffer instanceof DuplicatedByteBuf) {
|
} else if (buffer instanceof DuplicatedByteBuf) {
|
||||||
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
this.buffer = (UnsafeByteBuf) buffer.unwrap();
|
||||||
adjustment = index;
|
adjustment = index;
|
||||||
} else {
|
} else {
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
@ -61,8 +61,6 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
this.length = length;
|
this.length = length;
|
||||||
|
|
||||||
writerIndex(length);
|
writerIndex(length);
|
||||||
|
|
||||||
buffer.unsafe().acquire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -70,6 +68,16 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return buffer.alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return buffer.order();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirect() {
|
public boolean isDirect() {
|
||||||
return buffer.isDirect();
|
return buffer.isDirect();
|
||||||
@ -81,7 +89,7 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf capacity(int newCapacity) {
|
public ByteBuf capacity(int newCapacity) {
|
||||||
throw new UnsupportedOperationException("sliced buffer");
|
throw new UnsupportedOperationException("sliced buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,84 +161,84 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
buffer.getBytes(index + adjustment, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
checkIndex(index, dst.remaining());
|
checkIndex(index, dst.remaining());
|
||||||
buffer.getBytes(index + adjustment, dst);
|
buffer.getBytes(index + adjustment, dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setByte(int index, int value) {
|
public ByteBuf setByte(int index, int value) {
|
||||||
checkIndex(index);
|
checkIndex(index);
|
||||||
buffer.setByte(index + adjustment, value);
|
buffer.setByte(index + adjustment, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setShort(int index, int value) {
|
public ByteBuf setShort(int index, int value) {
|
||||||
checkIndex(index, 2);
|
checkIndex(index, 2);
|
||||||
buffer.setShort(index + adjustment, value);
|
buffer.setShort(index + adjustment, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setMedium(int index, int value) {
|
public ByteBuf setMedium(int index, int value) {
|
||||||
checkIndex(index, 3);
|
checkIndex(index, 3);
|
||||||
buffer.setMedium(index + adjustment, value);
|
buffer.setMedium(index + adjustment, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setInt(int index, int value) {
|
public ByteBuf setInt(int index, int value) {
|
||||||
checkIndex(index, 4);
|
checkIndex(index, 4);
|
||||||
buffer.setInt(index + adjustment, value);
|
buffer.setInt(index + adjustment, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setLong(int index, long value) {
|
public ByteBuf setLong(int index, long value) {
|
||||||
checkIndex(index, 8);
|
checkIndex(index, 8);
|
||||||
buffer.setLong(index + adjustment, value);
|
buffer.setLong(index + adjustment, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
buffer.setBytes(index + adjustment, src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
checkIndex(index, src.remaining());
|
checkIndex(index, src.remaining());
|
||||||
buffer.setBytes(index + adjustment, src);
|
buffer.setBytes(index + adjustment, src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length)
|
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
buffer.getBytes(index + adjustment, out, length);
|
buffer.getBytes(index + adjustment, out, length);
|
||||||
@ -302,40 +310,20 @@ public class SlicedByteBuf extends AbstractWrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer internalNioBuffer() {
|
||||||
return unsafe;
|
return buffer.nioBuffer(adjustment, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SlicedUnsafe implements Unsafe {
|
@Override
|
||||||
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
@Override
|
return buffer.nioBuffers(adjustment, length);
|
||||||
public ByteBuffer nioBuffer() {
|
|
||||||
return buffer.nioBuffer(adjustment, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuffer[] nioBuffers() {
|
|
||||||
return buffer.nioBuffers(adjustment, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf newBuffer(int initialCapacity) {
|
|
||||||
return buffer.unsafe().newBuffer(initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discardSomeReadBytes() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acquire() {
|
|
||||||
buffer.unsafe().acquire();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release() {
|
|
||||||
buffer.unsafe().release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free() { }
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,12 @@ import java.nio.channels.GatheringByteChannel;
|
|||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
public class SwappedByteBuf implements WrappedByteBuf {
|
public class SwappedByteBuf implements UnsafeByteBuf {
|
||||||
|
|
||||||
private final ByteBuf buf;
|
private final UnsafeByteBuf buf;
|
||||||
private final ByteOrder order;
|
private final ByteOrder order;
|
||||||
|
|
||||||
public SwappedByteBuf(ByteBuf buf) {
|
public SwappedByteBuf(UnsafeByteBuf buf) {
|
||||||
if (buf == null) {
|
if (buf == null) {
|
||||||
throw new NullPointerException("buf");
|
throw new NullPointerException("buf");
|
||||||
}
|
}
|
||||||
@ -63,8 +63,8 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPooled() {
|
public ByteBufAllocator alloc() {
|
||||||
return buf.isPooled();
|
return buf.alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -78,7 +78,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf capacity(int newCapacity) {
|
public ByteBuf capacity(int newCapacity) {
|
||||||
buf.capacity(newCapacity);
|
buf.capacity(newCapacity);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readerIndex(int readerIndex) {
|
public ByteBuf readerIndex(int readerIndex) {
|
||||||
buf.readerIndex(readerIndex);
|
buf.readerIndex(readerIndex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -110,13 +110,13 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writerIndex(int writerIndex) {
|
public ByteBuf writerIndex(int writerIndex) {
|
||||||
buf.writerIndex(writerIndex);
|
buf.writerIndex(writerIndex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setIndex(int readerIndex, int writerIndex) {
|
public ByteBuf setIndex(int readerIndex, int writerIndex) {
|
||||||
buf.setIndex(readerIndex, writerIndex);
|
buf.setIndex(readerIndex, writerIndex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -142,43 +142,43 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf clear() {
|
public ByteBuf clear() {
|
||||||
buf.clear();
|
buf.clear();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf markReaderIndex() {
|
public ByteBuf markReaderIndex() {
|
||||||
buf.markReaderIndex();
|
buf.markReaderIndex();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf resetReaderIndex() {
|
public ByteBuf resetReaderIndex() {
|
||||||
buf.resetReaderIndex();
|
buf.resetReaderIndex();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf markWriterIndex() {
|
public ByteBuf markWriterIndex() {
|
||||||
buf.markWriterIndex();
|
buf.markWriterIndex();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf resetWriterIndex() {
|
public ByteBuf resetWriterIndex() {
|
||||||
buf.resetWriterIndex();
|
buf.resetWriterIndex();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf discardReadBytes() {
|
public ByteBuf discardReadBytes() {
|
||||||
buf.discardReadBytes();
|
buf.discardReadBytes();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf ensureWritableBytes(int writableBytes) {
|
public ByteBuf ensureWritableBytes(int writableBytes) {
|
||||||
buf.ensureWritableBytes(writableBytes);
|
buf.ensureWritableBytes(writableBytes);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -254,43 +254,43 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst) {
|
public ByteBuf getBytes(int index, ByteBuf dst) {
|
||||||
buf.getBytes(index, dst);
|
buf.getBytes(index, dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int length) {
|
||||||
buf.getBytes(index, dst, length);
|
buf.getBytes(index, dst, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
buf.getBytes(index, dst, dstIndex, length);
|
buf.getBytes(index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, byte[] dst) {
|
public ByteBuf getBytes(int index, byte[] dst) {
|
||||||
buf.getBytes(index, dst);
|
buf.getBytes(index, dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
buf.getBytes(index, dst, dstIndex, length);
|
buf.getBytes(index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
buf.getBytes(index, dst);
|
buf.getBytes(index, dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||||
buf.getBytes(index, out, length);
|
buf.getBytes(index, out, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -301,91 +301,91 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBoolean(int index, boolean value) {
|
public ByteBuf setBoolean(int index, boolean value) {
|
||||||
buf.setBoolean(index, value);
|
buf.setBoolean(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setByte(int index, int value) {
|
public ByteBuf setByte(int index, int value) {
|
||||||
buf.setByte(index, value);
|
buf.setByte(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setShort(int index, int value) {
|
public ByteBuf setShort(int index, int value) {
|
||||||
buf.setShort(index, ByteBufUtil.swapShort((short) value));
|
buf.setShort(index, ByteBufUtil.swapShort((short) value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setMedium(int index, int value) {
|
public ByteBuf setMedium(int index, int value) {
|
||||||
buf.setMedium(index, ByteBufUtil.swapMedium(value));
|
buf.setMedium(index, ByteBufUtil.swapMedium(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setInt(int index, int value) {
|
public ByteBuf setInt(int index, int value) {
|
||||||
buf.setInt(index, ByteBufUtil.swapInt(value));
|
buf.setInt(index, ByteBufUtil.swapInt(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setLong(int index, long value) {
|
public ByteBuf setLong(int index, long value) {
|
||||||
buf.setLong(index, ByteBufUtil.swapLong(value));
|
buf.setLong(index, ByteBufUtil.swapLong(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setChar(int index, int value) {
|
public ByteBuf setChar(int index, int value) {
|
||||||
setShort(index, value);
|
setShort(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setFloat(int index, float value) {
|
public ByteBuf setFloat(int index, float value) {
|
||||||
setInt(index, Float.floatToRawIntBits(value));
|
setInt(index, Float.floatToRawIntBits(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setDouble(int index, double value) {
|
public ByteBuf setDouble(int index, double value) {
|
||||||
setLong(index, Double.doubleToRawLongBits(value));
|
setLong(index, Double.doubleToRawLongBits(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src) {
|
public ByteBuf setBytes(int index, ByteBuf src) {
|
||||||
buf.setBytes(index, src);
|
buf.setBytes(index, src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int length) {
|
||||||
buf.setBytes(index, src, length);
|
buf.setBytes(index, src, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
buf.setBytes(index, src, srcIndex, length);
|
buf.setBytes(index, src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, byte[] src) {
|
public ByteBuf setBytes(int index, byte[] src) {
|
||||||
buf.setBytes(index, src);
|
buf.setBytes(index, src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
buf.setBytes(index, src, srcIndex, length);
|
buf.setBytes(index, src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setBytes(int index, ByteBuffer src) {
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
buf.setBytes(index, src);
|
buf.setBytes(index, src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -401,7 +401,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf setZero(int index, int length) {
|
public ByteBuf setZero(int index, int length) {
|
||||||
buf.setZero(index, length);
|
buf.setZero(index, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -473,7 +473,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf readBytes(int length) {
|
public ByteBuf readBytes(int length) {
|
||||||
return buf.readBytes(length);
|
return buf.readBytes(length).order(order());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -482,43 +482,43 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(ByteBuf dst) {
|
public ByteBuf readBytes(ByteBuf dst) {
|
||||||
buf.readBytes(dst);
|
buf.readBytes(dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(ByteBuf dst, int length) {
|
public ByteBuf readBytes(ByteBuf dst, int length) {
|
||||||
buf.readBytes(dst, length);
|
buf.readBytes(dst, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
|
||||||
buf.readBytes(dst, dstIndex, length);
|
buf.readBytes(dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(byte[] dst) {
|
public ByteBuf readBytes(byte[] dst) {
|
||||||
buf.readBytes(dst);
|
buf.readBytes(dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
||||||
buf.readBytes(dst, dstIndex, length);
|
buf.readBytes(dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(ByteBuffer dst) {
|
public ByteBuf readBytes(ByteBuffer dst) {
|
||||||
buf.readBytes(dst);
|
buf.readBytes(dst);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf readBytes(OutputStream out, int length) throws IOException {
|
public ByteBuf readBytes(OutputStream out, int length) throws IOException {
|
||||||
buf.readBytes(out, length);
|
buf.readBytes(out, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -529,97 +529,97 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf skipBytes(int length) {
|
public ByteBuf skipBytes(int length) {
|
||||||
buf.skipBytes(length);
|
buf.skipBytes(length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBoolean(boolean value) {
|
public ByteBuf writeBoolean(boolean value) {
|
||||||
buf.writeBoolean(value);
|
buf.writeBoolean(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeByte(int value) {
|
public ByteBuf writeByte(int value) {
|
||||||
buf.writeByte(value);
|
buf.writeByte(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeShort(int value) {
|
public ByteBuf writeShort(int value) {
|
||||||
buf.writeShort(ByteBufUtil.swapShort((short) value));
|
buf.writeShort(ByteBufUtil.swapShort((short) value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeMedium(int value) {
|
public ByteBuf writeMedium(int value) {
|
||||||
buf.writeMedium(ByteBufUtil.swapMedium(value));
|
buf.writeMedium(ByteBufUtil.swapMedium(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeInt(int value) {
|
public ByteBuf writeInt(int value) {
|
||||||
buf.writeInt(ByteBufUtil.swapInt(value));
|
buf.writeInt(ByteBufUtil.swapInt(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeLong(long value) {
|
public ByteBuf writeLong(long value) {
|
||||||
buf.writeLong(ByteBufUtil.swapLong(value));
|
buf.writeLong(ByteBufUtil.swapLong(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeChar(int value) {
|
public ByteBuf writeChar(int value) {
|
||||||
writeShort(value);
|
writeShort(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeFloat(float value) {
|
public ByteBuf writeFloat(float value) {
|
||||||
writeInt(Float.floatToRawIntBits(value));
|
writeInt(Float.floatToRawIntBits(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeDouble(double value) {
|
public ByteBuf writeDouble(double value) {
|
||||||
writeLong(Double.doubleToRawLongBits(value));
|
writeLong(Double.doubleToRawLongBits(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBytes(ByteBuf src) {
|
public ByteBuf writeBytes(ByteBuf src) {
|
||||||
buf.writeBytes(src);
|
buf.writeBytes(src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBytes(ByteBuf src, int length) {
|
public ByteBuf writeBytes(ByteBuf src, int length) {
|
||||||
buf.writeBytes(src, length);
|
buf.writeBytes(src, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
|
public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
|
||||||
buf.writeBytes(src, srcIndex, length);
|
buf.writeBytes(src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBytes(byte[] src) {
|
public ByteBuf writeBytes(byte[] src) {
|
||||||
buf.writeBytes(src);
|
buf.writeBytes(src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBytes(byte[] src, int srcIndex, int length) {
|
public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
|
||||||
buf.writeBytes(src, srcIndex, length);
|
buf.writeBytes(src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeBytes(ByteBuffer src) {
|
public ByteBuf writeBytes(ByteBuffer src) {
|
||||||
buf.writeBytes(src);
|
buf.writeBytes(src);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -635,7 +635,7 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WrappedByteBuf writeZero(int length) {
|
public ByteBuf writeZero(int length) {
|
||||||
buf.writeZero(length);
|
buf.writeZero(length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -768,11 +768,6 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
return buf.toString(index, length, charset);
|
return buf.toString(index, length, charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Unsafe unsafe() {
|
|
||||||
return buf.unsafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return buf.hashCode();
|
return buf.hashCode();
|
||||||
@ -798,4 +793,22 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Swapped(" + buf.toString() + ')';
|
return "Swapped(" + buf.toString() + ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer internalNioBuffer() {
|
||||||
|
return buf.internalNioBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
|
return buf.internalNioBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
buf.discardSomeReadBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free() { }
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,8 @@ import java.util.Queue;
|
|||||||
*/
|
*/
|
||||||
public final class Unpooled {
|
public final class Unpooled {
|
||||||
|
|
||||||
|
private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Big endian byte order.
|
* Big endian byte order.
|
||||||
*/
|
*/
|
||||||
@ -90,15 +92,7 @@ public final class Unpooled {
|
|||||||
/**
|
/**
|
||||||
* A buffer whose capacity is {@code 0}.
|
* A buffer whose capacity is {@code 0}.
|
||||||
*/
|
*/
|
||||||
public static final ByteBuf EMPTY_BUFFER = new HeapByteBuf(0, 0) {
|
public static final ByteBuf EMPTY_BUFFER = ALLOC.heapBuffer(0, 0);
|
||||||
@Override
|
|
||||||
public ByteBuf order(ByteOrder endianness) {
|
|
||||||
if (endianness == null) {
|
|
||||||
throw new NullPointerException("endianness");
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static <T> MessageBuf<T> messageBuffer() {
|
public static <T> MessageBuf<T> messageBuffer() {
|
||||||
return new DefaultMessageBuf<T>();
|
return new DefaultMessageBuf<T>();
|
||||||
@ -120,7 +114,7 @@ public final class Unpooled {
|
|||||||
* expands its capacity boundlessly on demand.
|
* expands its capacity boundlessly on demand.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf buffer() {
|
public static ByteBuf buffer() {
|
||||||
return buffer(256, Integer.MAX_VALUE);
|
return ALLOC.heapBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,7 +122,7 @@ public final class Unpooled {
|
|||||||
* expands its capacity boundlessly on demand.
|
* expands its capacity boundlessly on demand.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf directBuffer() {
|
public static ByteBuf directBuffer() {
|
||||||
return directBuffer(256, Integer.MAX_VALUE);
|
return ALLOC.directBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,7 +131,7 @@ public final class Unpooled {
|
|||||||
* {@code writerIndex} are {@code 0}.
|
* {@code writerIndex} are {@code 0}.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf buffer(int initialCapacity) {
|
public static ByteBuf buffer(int initialCapacity) {
|
||||||
return buffer(initialCapacity, Integer.MAX_VALUE);
|
return ALLOC.heapBuffer(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +140,7 @@ public final class Unpooled {
|
|||||||
* {@code writerIndex} are {@code 0}.
|
* {@code writerIndex} are {@code 0}.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf directBuffer(int initialCapacity) {
|
public static ByteBuf directBuffer(int initialCapacity) {
|
||||||
return directBuffer(initialCapacity, Integer.MAX_VALUE);
|
return ALLOC.directBuffer(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,10 +149,7 @@ public final class Unpooled {
|
|||||||
* {@code writerIndex} are {@code 0}.
|
* {@code writerIndex} are {@code 0}.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf buffer(int initialCapacity, int maxCapacity) {
|
public static ByteBuf buffer(int initialCapacity, int maxCapacity) {
|
||||||
if (initialCapacity == 0 && maxCapacity == 0) {
|
return ALLOC.heapBuffer(initialCapacity, maxCapacity);
|
||||||
return EMPTY_BUFFER;
|
|
||||||
}
|
|
||||||
return new HeapByteBuf(initialCapacity, maxCapacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,10 +158,7 @@ public final class Unpooled {
|
|||||||
* {@code writerIndex} are {@code 0}.
|
* {@code writerIndex} are {@code 0}.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
|
public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
|
||||||
if (initialCapacity == 0 && maxCapacity == 0) {
|
return ALLOC.directBuffer(initialCapacity, maxCapacity);
|
||||||
return EMPTY_BUFFER;
|
|
||||||
}
|
|
||||||
return new DirectByteBuf(initialCapacity, maxCapacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,7 +170,7 @@ public final class Unpooled {
|
|||||||
if (array.length == 0) {
|
if (array.length == 0) {
|
||||||
return EMPTY_BUFFER;
|
return EMPTY_BUFFER;
|
||||||
}
|
}
|
||||||
return new HeapByteBuf(array, array.length);
|
return new UnpooledHeapByteBuf(ALLOC, array, array.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,7 +187,7 @@ public final class Unpooled {
|
|||||||
return wrappedBuffer(array);
|
return wrappedBuffer(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SlicedByteBuf(wrappedBuffer(array), offset, length);
|
return wrappedBuffer(array).slice(offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,7 +205,7 @@ public final class Unpooled {
|
|||||||
buffer.arrayOffset() + buffer.position(),
|
buffer.arrayOffset() + buffer.position(),
|
||||||
buffer.remaining()).order(buffer.order());
|
buffer.remaining()).order(buffer.order());
|
||||||
} else {
|
} else {
|
||||||
return new DirectByteBuf(buffer, buffer.remaining());
|
return new UnpooledDirectByteBuf(ALLOC, buffer, buffer.remaining());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +276,7 @@ public final class Unpooled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!components.isEmpty()) {
|
if (!components.isEmpty()) {
|
||||||
return new DefaultCompositeByteBuf(maxNumComponents, components);
|
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents, components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +300,7 @@ public final class Unpooled {
|
|||||||
default:
|
default:
|
||||||
for (ByteBuf b: buffers) {
|
for (ByteBuf b: buffers) {
|
||||||
if (b.readable()) {
|
if (b.readable()) {
|
||||||
return new DefaultCompositeByteBuf(maxNumComponents, buffers);
|
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents, buffers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,7 +334,7 @@ public final class Unpooled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!components.isEmpty()) {
|
if (!components.isEmpty()) {
|
||||||
return new DefaultCompositeByteBuf(maxNumComponents, components);
|
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents, components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +352,7 @@ public final class Unpooled {
|
|||||||
* Returns a new big-endian composite buffer with no components.
|
* Returns a new big-endian composite buffer with no components.
|
||||||
*/
|
*/
|
||||||
public static CompositeByteBuf compositeBuffer(int maxNumComponents) {
|
public static CompositeByteBuf compositeBuffer(int maxNumComponents) {
|
||||||
return new DefaultCompositeByteBuf(maxNumComponents);
|
return new DefaultCompositeByteBuf(ALLOC, maxNumComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -674,10 +662,7 @@ public final class Unpooled {
|
|||||||
* {@code buffer}.
|
* {@code buffer}.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf unmodifiableBuffer(ByteBuf buffer) {
|
public static ByteBuf unmodifiableBuffer(ByteBuf buffer) {
|
||||||
if (buffer instanceof ReadOnlyByteBuf) {
|
return new ReadOnlyByteBuf((UnsafeByteBuf) buffer);
|
||||||
buffer = ((ReadOnlyByteBuf) buffer).unwrap();
|
|
||||||
}
|
|
||||||
return new ReadOnlyByteBuf(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import io.netty.util.internal.DetectionUtil;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplistic {@link ByteBufAllocator} implementation that does not pool anything.
|
||||||
|
*/
|
||||||
|
public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {
|
||||||
|
|
||||||
|
public static final UnpooledByteBufAllocator HEAP_BY_DEFAULT = new UnpooledByteBufAllocator(false);
|
||||||
|
public static final UnpooledByteBufAllocator DIRECT_BY_DEFAULT = new UnpooledByteBufAllocator(true);
|
||||||
|
|
||||||
|
private UnpooledByteBufAllocator(boolean directByDefault) {
|
||||||
|
super(directByDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
|
||||||
|
return new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
|
||||||
|
return new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf ioBuffer() {
|
||||||
|
if (DetectionUtil.canFreeDirectBuffer()) {
|
||||||
|
return directBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return heapBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
throw new IllegalStateException(getClass().getName() + " cannot be shut down.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShutdown() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTerminated() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
|
Thread.sleep(unit.toMillis(timeout));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
* constructor explicitly.
|
* constructor explicitly.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("restriction")
|
@SuppressWarnings("restriction")
|
||||||
public class DirectByteBuf extends AbstractByteBuf {
|
public class UnpooledDirectByteBuf extends AbstractByteBuf {
|
||||||
|
|
||||||
private static final Field CLEANER_FIELD;
|
private static final Field CLEANER_FIELD;
|
||||||
|
|
||||||
@ -52,6 +52,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void freeDirect(ByteBuffer buffer) {
|
private static void freeDirect(ByteBuffer buffer) {
|
||||||
|
if (CLEANER_FIELD == null) {
|
||||||
|
// Doomed to wait for GC.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Cleaner cleaner;
|
Cleaner cleaner;
|
||||||
try {
|
try {
|
||||||
cleaner = (Cleaner) CLEANER_FIELD.get(buffer);
|
cleaner = (Cleaner) CLEANER_FIELD.get(buffer);
|
||||||
@ -61,12 +66,12 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Unsafe unsafe = new DirectUnsafe();
|
private final ByteBufAllocator alloc;
|
||||||
|
|
||||||
private boolean doNotFree;
|
|
||||||
private ByteBuffer buffer;
|
private ByteBuffer buffer;
|
||||||
private ByteBuffer tmpBuf;
|
private ByteBuffer tmpNioBuf;
|
||||||
private int capacity;
|
private int capacity;
|
||||||
|
private boolean freed;
|
||||||
|
private boolean doNotFree;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new direct buffer.
|
* Creates a new direct buffer.
|
||||||
@ -74,8 +79,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
* @param initialCapacity the initial capacity of the underlying direct buffer
|
* @param initialCapacity the initial capacity of the underlying direct buffer
|
||||||
* @param maxCapacity the maximum capacity of the underlying direct buffer
|
* @param maxCapacity the maximum capacity of the underlying direct buffer
|
||||||
*/
|
*/
|
||||||
public DirectByteBuf(int initialCapacity, int maxCapacity) {
|
public UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
|
||||||
super(ByteOrder.BIG_ENDIAN, maxCapacity);
|
super(maxCapacity);
|
||||||
|
if (alloc == null) {
|
||||||
|
throw new NullPointerException("alloc");
|
||||||
|
}
|
||||||
if (initialCapacity < 0) {
|
if (initialCapacity < 0) {
|
||||||
throw new IllegalArgumentException("initialCapacity: " + initialCapacity);
|
throw new IllegalArgumentException("initialCapacity: " + initialCapacity);
|
||||||
}
|
}
|
||||||
@ -87,6 +95,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
|
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.alloc = alloc;
|
||||||
setByteBuffer(ByteBuffer.allocateDirect(initialCapacity));
|
setByteBuffer(ByteBuffer.allocateDirect(initialCapacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,9 +104,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
*
|
*
|
||||||
* @param maxCapacity the maximum capacity of the underlying direct buffer
|
* @param maxCapacity the maximum capacity of the underlying direct buffer
|
||||||
*/
|
*/
|
||||||
public DirectByteBuf(ByteBuffer initialBuffer, int maxCapacity) {
|
public UnpooledDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) {
|
||||||
super(ByteOrder.BIG_ENDIAN, maxCapacity);
|
super(maxCapacity);
|
||||||
|
if (alloc == null) {
|
||||||
|
throw new NullPointerException("alloc");
|
||||||
|
}
|
||||||
if (initialBuffer == null) {
|
if (initialBuffer == null) {
|
||||||
throw new NullPointerException("initialBuffer");
|
throw new NullPointerException("initialBuffer");
|
||||||
}
|
}
|
||||||
@ -114,6 +125,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
|
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.alloc = alloc;
|
||||||
doNotFree = true;
|
doNotFree = true;
|
||||||
setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN));
|
setByteBuffer(initialBuffer.slice().order(ByteOrder.BIG_ENDIAN));
|
||||||
writerIndex(initialCapacity);
|
writerIndex(initialCapacity);
|
||||||
@ -130,7 +142,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
tmpBuf = buffer.duplicate();
|
tmpNioBuf = null;
|
||||||
capacity = buffer.remaining();
|
capacity = buffer.remaining();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +158,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf capacity(int newCapacity) {
|
public ByteBuf capacity(int newCapacity) {
|
||||||
|
assert !freed;
|
||||||
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
||||||
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
||||||
}
|
}
|
||||||
@ -181,6 +194,16 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return ByteOrder.BIG_ENDIAN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasArray() {
|
public boolean hasArray() {
|
||||||
return false;
|
return false;
|
||||||
@ -198,34 +221,40 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getByte(int index) {
|
public byte getByte(int index) {
|
||||||
|
assert !freed;
|
||||||
return buffer.get(index);
|
return buffer.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short getShort(int index) {
|
public short getShort(int index) {
|
||||||
|
assert !freed;
|
||||||
return buffer.getShort(index);
|
return buffer.getShort(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getUnsignedMedium(int index) {
|
public int getUnsignedMedium(int index) {
|
||||||
|
assert !freed;
|
||||||
return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff;
|
return (getByte(index) & 0xff) << 16 | (getByte(index + 1) & 0xff) << 8 | getByte(index + 2) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(int index) {
|
public int getInt(int index) {
|
||||||
|
assert !freed;
|
||||||
return buffer.getInt(index);
|
return buffer.getInt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLong(int index) {
|
public long getLong(int index) {
|
||||||
|
assert !freed;
|
||||||
return buffer.getLong(index);
|
return buffer.getLong(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
if (dst instanceof DirectByteBuf) {
|
assert !freed;
|
||||||
DirectByteBuf bbdst = (DirectByteBuf) dst;
|
if (dst instanceof UnpooledDirectByteBuf) {
|
||||||
ByteBuffer data = bbdst.tmpBuf;
|
UnpooledDirectByteBuf bbdst = (UnpooledDirectByteBuf) dst;
|
||||||
|
ByteBuffer data = bbdst.internalNioBuffer();
|
||||||
data.clear().position(dstIndex).limit(dstIndex + length);
|
data.clear().position(dstIndex).limit(dstIndex + length);
|
||||||
getBytes(index, data);
|
getBytes(index, data);
|
||||||
} else if (buffer.hasArray()) {
|
} else if (buffer.hasArray()) {
|
||||||
@ -238,6 +267,8 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
|
assert !freed;
|
||||||
|
ByteBuffer tmpBuf = internalNioBuffer();
|
||||||
try {
|
try {
|
||||||
tmpBuf.clear().position(index).limit(index + length);
|
tmpBuf.clear().position(index).limit(index + length);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@ -250,7 +281,9 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
|
assert !freed;
|
||||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
||||||
|
ByteBuffer tmpBuf = internalNioBuffer();
|
||||||
try {
|
try {
|
||||||
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@ -263,18 +296,21 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setByte(int index, int value) {
|
public ByteBuf setByte(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
buffer.put(index, (byte) value);
|
buffer.put(index, (byte) value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setShort(int index, int value) {
|
public ByteBuf setShort(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
buffer.putShort(index, (short) value);
|
buffer.putShort(index, (short) value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setMedium(int index, int value) {
|
public ByteBuf setMedium(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
setByte(index, (byte) (value >>> 16));
|
setByte(index, (byte) (value >>> 16));
|
||||||
setByte(index + 1, (byte) (value >>> 8));
|
setByte(index + 1, (byte) (value >>> 8));
|
||||||
setByte(index + 2, (byte) value);
|
setByte(index + 2, (byte) value);
|
||||||
@ -283,21 +319,24 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setInt(int index, int value) {
|
public ByteBuf setInt(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
buffer.putInt(index, value);
|
buffer.putInt(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setLong(int index, long value) {
|
public ByteBuf setLong(int index, long value) {
|
||||||
|
assert !freed;
|
||||||
buffer.putLong(index, value);
|
buffer.putLong(index, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
if (src instanceof DirectByteBuf) {
|
assert !freed;
|
||||||
DirectByteBuf bbsrc = (DirectByteBuf) src;
|
if (src instanceof UnpooledDirectByteBuf) {
|
||||||
ByteBuffer data = bbsrc.tmpBuf;
|
UnpooledDirectByteBuf bbsrc = (UnpooledDirectByteBuf) src;
|
||||||
|
ByteBuffer data = bbsrc.internalNioBuffer();
|
||||||
|
|
||||||
data.clear().position(srcIndex).limit(srcIndex + length);
|
data.clear().position(srcIndex).limit(srcIndex + length);
|
||||||
setBytes(index, data);
|
setBytes(index, data);
|
||||||
@ -311,6 +350,8 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
|
assert !freed;
|
||||||
|
ByteBuffer tmpBuf = internalNioBuffer();
|
||||||
tmpBuf.clear().position(index).limit(index + length);
|
tmpBuf.clear().position(index).limit(index + length);
|
||||||
tmpBuf.put(src, srcIndex, length);
|
tmpBuf.put(src, srcIndex, length);
|
||||||
return this;
|
return this;
|
||||||
@ -318,6 +359,8 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
|
assert !freed;
|
||||||
|
ByteBuffer tmpBuf = internalNioBuffer();
|
||||||
if (src == tmpBuf) {
|
if (src == tmpBuf) {
|
||||||
src = src.duplicate();
|
src = src.duplicate();
|
||||||
}
|
}
|
||||||
@ -329,6 +372,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||||
|
assert !freed;
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -337,6 +381,7 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
out.write(buffer.array(), index + buffer.arrayOffset(), length);
|
out.write(buffer.array(), index + buffer.arrayOffset(), length);
|
||||||
} else {
|
} else {
|
||||||
byte[] tmp = new byte[length];
|
byte[] tmp = new byte[length];
|
||||||
|
ByteBuffer tmpBuf = internalNioBuffer();
|
||||||
tmpBuf.clear().position(index);
|
tmpBuf.clear().position(index);
|
||||||
tmpBuf.get(tmp);
|
tmpBuf.get(tmp);
|
||||||
out.write(tmp);
|
out.write(tmp);
|
||||||
@ -346,33 +391,38 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||||
|
assert !freed;
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteBuffer tmpBuf = internalNioBuffer();
|
||||||
tmpBuf.clear().position(index).limit(index + length);
|
tmpBuf.clear().position(index).limit(index + length);
|
||||||
return out.write(tmpBuf);
|
return out.write(tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||||
|
assert !freed;
|
||||||
if (buffer.hasArray()) {
|
if (buffer.hasArray()) {
|
||||||
return in.read(buffer.array(), buffer.arrayOffset() + index, length);
|
return in.read(buffer.array(), buffer.arrayOffset() + index, length);
|
||||||
} else {
|
} else {
|
||||||
byte[] tmp = new byte[length];
|
byte[] tmp = new byte[length];
|
||||||
int readBytes = in.read(tmp);
|
int readBytes = in.read(tmp);
|
||||||
tmpBuf.clear().position(index);
|
ByteBuffer tmpNioBuf = internalNioBuffer();
|
||||||
tmpBuf.put(tmp);
|
tmpNioBuf.clear().position(index);
|
||||||
|
tmpNioBuf.put(tmp);
|
||||||
return readBytes;
|
return readBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||||
tmpBuf.clear().position(index).limit(index + length);
|
assert !freed;
|
||||||
|
ByteBuffer tmpNioBuf = internalNioBuffer();
|
||||||
|
tmpNioBuf.clear().position(index).limit(index + length);
|
||||||
try {
|
try {
|
||||||
return in.read(tmpBuf);
|
return in.read(tmpNioBuf);
|
||||||
} catch (ClosedChannelException e) {
|
} catch (ClosedChannelException e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -385,10 +435,11 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer nioBuffer(int index, int length) {
|
public ByteBuffer nioBuffer(int index, int length) {
|
||||||
|
assert !freed;
|
||||||
if (index == 0 && length == capacity()) {
|
if (index == 0 && length == capacity()) {
|
||||||
return buffer.duplicate();
|
return buffer.duplicate();
|
||||||
} else {
|
} else {
|
||||||
return ((ByteBuffer) tmpBuf.clear().position(index).limit(index + length)).slice();
|
return ((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)).slice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,9 +455,10 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf copy(int index, int length) {
|
public ByteBuf copy(int index, int length) {
|
||||||
|
assert !freed;
|
||||||
ByteBuffer src;
|
ByteBuffer src;
|
||||||
try {
|
try {
|
||||||
src = (ByteBuffer) tmpBuf.clear().position(index).limit(index + length);
|
src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
|
throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
|
||||||
}
|
}
|
||||||
@ -416,67 +468,52 @@ public class DirectByteBuf extends AbstractByteBuf {
|
|||||||
dst.put(src);
|
dst.put(src);
|
||||||
dst.order(order());
|
dst.order(order());
|
||||||
dst.clear();
|
dst.clear();
|
||||||
return new DirectByteBuf(dst, maxCapacity());
|
return new UnpooledDirectByteBuf(alloc(), dst, maxCapacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer internalNioBuffer() {
|
||||||
return unsafe;
|
ByteBuffer tmpNioBuf = this.tmpNioBuf;
|
||||||
|
if (tmpNioBuf == null) {
|
||||||
|
this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
|
||||||
|
}
|
||||||
|
return tmpNioBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DirectUnsafe implements Unsafe {
|
@Override
|
||||||
@Override
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
public ByteBuffer nioBuffer() {
|
throw new UnsupportedOperationException();
|
||||||
return tmpBuf;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
final int readerIndex = readerIndex();
|
||||||
|
if (readerIndex == writerIndex()) {
|
||||||
|
discardReadBytes();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
if (readerIndex > 0 && readerIndex >= capacity >>> 1) {
|
||||||
public ByteBuffer[] nioBuffers() {
|
discardReadBytes();
|
||||||
throw new UnsupportedOperationException();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free() {
|
||||||
|
if (freed) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
freed = true;
|
||||||
public ByteBuf newBuffer(int initialCapacity) {
|
if (doNotFree) {
|
||||||
return new DirectByteBuf(initialCapacity, Math.max(initialCapacity, maxCapacity()));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
freeDirect(buffer);
|
||||||
public void discardSomeReadBytes() {
|
}
|
||||||
final int readerIndex = readerIndex();
|
|
||||||
if (readerIndex == writerIndex()) {
|
|
||||||
discardReadBytes();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readerIndex > 0 && readerIndex >= capacity >>> 1) {
|
@Override
|
||||||
discardReadBytes();
|
public ByteBuf unwrap() {
|
||||||
}
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acquire() {
|
|
||||||
if (refCnt <= 0) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
refCnt ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release() {
|
|
||||||
if (refCnt <= 0) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
refCnt --;
|
|
||||||
if (refCnt == 0) {
|
|
||||||
if (doNotFree) {
|
|
||||||
doNotFree = false;
|
|
||||||
} else {
|
|
||||||
freeDirect(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = null;
|
|
||||||
tmpBuf = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,12 +27,12 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
/**
|
/**
|
||||||
* Big endian Java heap buffer implementation.
|
* Big endian Java heap buffer implementation.
|
||||||
*/
|
*/
|
||||||
public class HeapByteBuf extends AbstractByteBuf {
|
public class UnpooledHeapByteBuf extends AbstractByteBuf {
|
||||||
|
|
||||||
private final Unsafe unsafe = new HeapUnsafe();
|
|
||||||
|
|
||||||
|
private final ByteBufAllocator alloc;
|
||||||
private byte[] array;
|
private byte[] array;
|
||||||
private ByteBuffer nioBuf;
|
private ByteBuffer tmpNioBuf;
|
||||||
|
private boolean freed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new heap buffer with a newly allocated byte array.
|
* Creates a new heap buffer with a newly allocated byte array.
|
||||||
@ -40,8 +40,8 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
* @param initialCapacity the initial capacity of the underlying byte array
|
* @param initialCapacity the initial capacity of the underlying byte array
|
||||||
* @param maxCapacity the max capacity of the underlying byte array
|
* @param maxCapacity the max capacity of the underlying byte array
|
||||||
*/
|
*/
|
||||||
public HeapByteBuf(int initialCapacity, int maxCapacity) {
|
public UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
|
||||||
this(new byte[initialCapacity], 0, 0, maxCapacity);
|
this(alloc, new byte[initialCapacity], 0, 0, maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,12 +50,18 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
* @param initialArray the initial underlying byte array
|
* @param initialArray the initial underlying byte array
|
||||||
* @param maxCapacity the max capacity of the underlying byte array
|
* @param maxCapacity the max capacity of the underlying byte array
|
||||||
*/
|
*/
|
||||||
public HeapByteBuf(byte[] initialArray, int maxCapacity) {
|
public UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {
|
||||||
this(initialArray, 0, initialArray.length, maxCapacity);
|
this(alloc, initialArray, 0, initialArray.length, maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HeapByteBuf(byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {
|
private UnpooledHeapByteBuf(
|
||||||
super(ByteOrder.BIG_ENDIAN, maxCapacity);
|
ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {
|
||||||
|
|
||||||
|
super(maxCapacity);
|
||||||
|
|
||||||
|
if (alloc == null) {
|
||||||
|
throw new NullPointerException("alloc");
|
||||||
|
}
|
||||||
if (initialArray == null) {
|
if (initialArray == null) {
|
||||||
throw new NullPointerException("initialArray");
|
throw new NullPointerException("initialArray");
|
||||||
}
|
}
|
||||||
@ -64,13 +70,24 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
"initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));
|
"initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.alloc = alloc;
|
||||||
setArray(initialArray);
|
setArray(initialArray);
|
||||||
setIndex(readerIndex, writerIndex);
|
setIndex(readerIndex, writerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setArray(byte[] initialArray) {
|
private void setArray(byte[] initialArray) {
|
||||||
array = initialArray;
|
array = initialArray;
|
||||||
nioBuf = ByteBuffer.wrap(initialArray);
|
tmpNioBuf = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return ByteOrder.BIG_ENDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -85,6 +102,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf capacity(int newCapacity) {
|
public ByteBuf capacity(int newCapacity) {
|
||||||
|
assert !freed;
|
||||||
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
if (newCapacity < 0 || newCapacity > maxCapacity()) {
|
||||||
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
throw new IllegalArgumentException("newCapacity: " + newCapacity);
|
||||||
}
|
}
|
||||||
@ -118,6 +136,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] array() {
|
public byte[] array() {
|
||||||
|
assert !freed;
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,13 +147,15 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getByte(int index) {
|
public byte getByte(int index) {
|
||||||
|
assert !freed;
|
||||||
return array[index];
|
return array[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
if (dst instanceof HeapByteBuf) {
|
assert !freed;
|
||||||
getBytes(index, ((HeapByteBuf) dst).array, dstIndex, length);
|
if (dst instanceof UnpooledHeapByteBuf) {
|
||||||
|
getBytes(index, ((UnpooledHeapByteBuf) dst).array, dstIndex, length);
|
||||||
} else {
|
} else {
|
||||||
dst.setBytes(dstIndex, array, index, length);
|
dst.setBytes(dstIndex, array, index, length);
|
||||||
}
|
}
|
||||||
@ -143,39 +164,43 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
|
assert !freed;
|
||||||
System.arraycopy(array, index, dst, dstIndex, length);
|
System.arraycopy(array, index, dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
|
assert !freed;
|
||||||
dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
|
dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||||
throws IOException {
|
assert !freed;
|
||||||
out.write(array, index, length);
|
out.write(array, index, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||||
throws IOException {
|
assert !freed;
|
||||||
return out.write((ByteBuffer) nioBuf.clear().position(index).limit(index + length));
|
return out.write((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setByte(int index, int value) {
|
public ByteBuf setByte(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
array[index] = (byte) value;
|
array[index] = (byte) value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
if (src instanceof HeapByteBuf) {
|
assert !freed;
|
||||||
setBytes(index, ((HeapByteBuf) src).array, srcIndex, length);
|
if (src instanceof UnpooledHeapByteBuf) {
|
||||||
|
setBytes(index, ((UnpooledHeapByteBuf) src).array, srcIndex, length);
|
||||||
} else {
|
} else {
|
||||||
src.getBytes(srcIndex, array, index, length);
|
src.getBytes(srcIndex, array, index, length);
|
||||||
}
|
}
|
||||||
@ -184,25 +209,29 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
|
assert !freed;
|
||||||
System.arraycopy(src, srcIndex, array, index, length);
|
System.arraycopy(src, srcIndex, array, index, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
|
assert !freed;
|
||||||
src.get(array, index, src.remaining());
|
src.get(array, index, src.remaining());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||||
|
assert !freed;
|
||||||
return in.read(array, index, length);
|
return in.read(array, index, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||||
|
assert !freed;
|
||||||
try {
|
try {
|
||||||
return in.read((ByteBuffer) nioBuf.clear().position(index).limit(index + length));
|
return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));
|
||||||
} catch (ClosedChannelException e) {
|
} catch (ClosedChannelException e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -215,6 +244,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer nioBuffer(int index, int length) {
|
public ByteBuffer nioBuffer(int index, int length) {
|
||||||
|
assert !freed;
|
||||||
return ByteBuffer.wrap(array, index, length);
|
return ByteBuffer.wrap(array, index, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,11 +260,13 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short getShort(int index) {
|
public short getShort(int index) {
|
||||||
|
assert !freed;
|
||||||
return (short) (array[index] << 8 | array[index + 1] & 0xFF);
|
return (short) (array[index] << 8 | array[index + 1] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getUnsignedMedium(int index) {
|
public int getUnsignedMedium(int index) {
|
||||||
|
assert !freed;
|
||||||
return (array[index] & 0xff) << 16 |
|
return (array[index] & 0xff) << 16 |
|
||||||
(array[index + 1] & 0xff) << 8 |
|
(array[index + 1] & 0xff) << 8 |
|
||||||
array[index + 2] & 0xff;
|
array[index + 2] & 0xff;
|
||||||
@ -242,6 +274,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(int index) {
|
public int getInt(int index) {
|
||||||
|
assert !freed;
|
||||||
return (array[index] & 0xff) << 24 |
|
return (array[index] & 0xff) << 24 |
|
||||||
(array[index + 1] & 0xff) << 16 |
|
(array[index + 1] & 0xff) << 16 |
|
||||||
(array[index + 2] & 0xff) << 8 |
|
(array[index + 2] & 0xff) << 8 |
|
||||||
@ -250,6 +283,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLong(int index) {
|
public long getLong(int index) {
|
||||||
|
assert !freed;
|
||||||
return ((long) array[index] & 0xff) << 56 |
|
return ((long) array[index] & 0xff) << 56 |
|
||||||
((long) array[index + 1] & 0xff) << 48 |
|
((long) array[index + 1] & 0xff) << 48 |
|
||||||
((long) array[index + 2] & 0xff) << 40 |
|
((long) array[index + 2] & 0xff) << 40 |
|
||||||
@ -262,6 +296,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setShort(int index, int value) {
|
public ByteBuf setShort(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
array[index] = (byte) (value >>> 8);
|
array[index] = (byte) (value >>> 8);
|
||||||
array[index + 1] = (byte) value;
|
array[index + 1] = (byte) value;
|
||||||
return this;
|
return this;
|
||||||
@ -269,6 +304,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setMedium(int index, int value) {
|
public ByteBuf setMedium(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
array[index] = (byte) (value >>> 16);
|
array[index] = (byte) (value >>> 16);
|
||||||
array[index + 1] = (byte) (value >>> 8);
|
array[index + 1] = (byte) (value >>> 8);
|
||||||
array[index + 2] = (byte) value;
|
array[index + 2] = (byte) value;
|
||||||
@ -277,6 +313,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setInt(int index, int value) {
|
public ByteBuf setInt(int index, int value) {
|
||||||
|
assert !freed;
|
||||||
array[index] = (byte) (value >>> 24);
|
array[index] = (byte) (value >>> 24);
|
||||||
array[index + 1] = (byte) (value >>> 16);
|
array[index + 1] = (byte) (value >>> 16);
|
||||||
array[index + 2] = (byte) (value >>> 8);
|
array[index + 2] = (byte) (value >>> 8);
|
||||||
@ -286,6 +323,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setLong(int index, long value) {
|
public ByteBuf setLong(int index, long value) {
|
||||||
|
assert !freed;
|
||||||
array[index] = (byte) (value >>> 56);
|
array[index] = (byte) (value >>> 56);
|
||||||
array[index + 1] = (byte) (value >>> 48);
|
array[index + 1] = (byte) (value >>> 48);
|
||||||
array[index + 2] = (byte) (value >>> 40);
|
array[index + 2] = (byte) (value >>> 40);
|
||||||
@ -299,6 +337,7 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf copy(int index, int length) {
|
public ByteBuf copy(int index, int length) {
|
||||||
|
assert !freed;
|
||||||
if (index < 0 || length < 0 || index + length > array.length) {
|
if (index < 0 || length < 0 || index + length > array.length) {
|
||||||
throw new IndexOutOfBoundsException("Too many bytes to copy - Need "
|
throw new IndexOutOfBoundsException("Too many bytes to copy - Need "
|
||||||
+ (index + length) + ", maximum is " + array.length);
|
+ (index + length) + ", maximum is " + array.length);
|
||||||
@ -306,61 +345,43 @@ public class HeapByteBuf extends AbstractByteBuf {
|
|||||||
|
|
||||||
byte[] copiedArray = new byte[length];
|
byte[] copiedArray = new byte[length];
|
||||||
System.arraycopy(array, index, copiedArray, 0, length);
|
System.arraycopy(array, index, copiedArray, 0, length);
|
||||||
return new HeapByteBuf(copiedArray, maxCapacity());
|
return new UnpooledHeapByteBuf(alloc(), copiedArray, maxCapacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer internalNioBuffer() {
|
||||||
return unsafe;
|
ByteBuffer tmpNioBuf = this.tmpNioBuf;
|
||||||
|
if (tmpNioBuf == null) {
|
||||||
|
this.tmpNioBuf = tmpNioBuf = ByteBuffer.wrap(array);
|
||||||
|
}
|
||||||
|
return tmpNioBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HeapUnsafe implements Unsafe {
|
@Override
|
||||||
@Override
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
public ByteBuffer nioBuffer() {
|
throw new UnsupportedOperationException();
|
||||||
return nioBuf;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
final int readerIndex = readerIndex();
|
||||||
|
if (readerIndex == writerIndex()) {
|
||||||
|
discardReadBytes();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
if (readerIndex > 0 && readerIndex >= capacity() >>> 1) {
|
||||||
public ByteBuffer[] nioBuffers() {
|
discardReadBytes();
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newBuffer(int initialCapacity) {
|
public void free() {
|
||||||
return new HeapByteBuf(initialCapacity, Math.max(initialCapacity, maxCapacity()));
|
freed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void discardSomeReadBytes() {
|
public ByteBuf unwrap() {
|
||||||
final int readerIndex = readerIndex();
|
return null;
|
||||||
if (readerIndex == writerIndex()) {
|
|
||||||
discardReadBytes();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readerIndex > 0 && readerIndex >= capacity() >>> 1) {
|
|
||||||
discardReadBytes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acquire() {
|
|
||||||
if (refCnt <= 0) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
refCnt ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release() {
|
|
||||||
if (refCnt <= 0) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
refCnt --;
|
|
||||||
if (refCnt == 0) {
|
|
||||||
array = null;
|
|
||||||
nioBuf = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
57
buffer/src/main/java/io/netty/buffer/UnsafeByteBuf.java
Normal file
57
buffer/src/main/java/io/netty/buffer/UnsafeByteBuf.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public interface UnsafeByteBuf extends ByteBuf {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the internal NIO buffer that is reused for I/O.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer
|
||||||
|
*/
|
||||||
|
ByteBuffer internalNioBuffer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the internal NIO buffer array that is reused for I/O.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if the buffer has no internal NIO buffer array
|
||||||
|
*/
|
||||||
|
ByteBuffer[] internalNioBuffers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard
|
||||||
|
* some, all, or none of read bytes depending on its internal implementation to reduce
|
||||||
|
* overall memory bandwidth consumption at the cost of potentially additional memory
|
||||||
|
* consumption.
|
||||||
|
*/
|
||||||
|
void discardSomeReadBytes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deallocates the internal memory block of this buffer or returns it to the {@link ByteBufAllocator} it came
|
||||||
|
* from. The result of accessing a released buffer is unspecified and can even cause JVM crash.
|
||||||
|
*/
|
||||||
|
void free();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying buffer instance if this buffer is a wrapper.
|
||||||
|
*
|
||||||
|
* @return {@code null} if this buffer is not a wrapper
|
||||||
|
*/
|
||||||
|
ByteBuf unwrap();
|
||||||
|
}
|
@ -1,205 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 The Netty Project
|
|
||||||
*
|
|
||||||
* The Netty Project licenses this file to you under the Apache License,
|
|
||||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package io.netty.buffer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The common interface for buffer wrappers and derived buffers. Most users won't
|
|
||||||
* need to use this interface. It is used internally in most cases.
|
|
||||||
*/
|
|
||||||
public interface WrappedByteBuf extends ByteBuf {
|
|
||||||
/**
|
|
||||||
* Returns this buffer's parent that this buffer is wrapping.
|
|
||||||
*/
|
|
||||||
ByteBuf unwrap();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf capacity(int newCapacity);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readerIndex(int readerIndex);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writerIndex(int writerIndex);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setIndex(int readerIndex, int writerIndex);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf clear();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf markReaderIndex();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf resetReaderIndex();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf markWriterIndex();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf resetWriterIndex();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf discardReadBytes();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf ensureWritableBytes(int minWritableBytes);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, ByteBuf dst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, ByteBuf dst, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, byte[] dst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, ByteBuffer dst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf getBytes(int index, OutputStream out, int length) throws IOException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBoolean(int index, boolean value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setByte(int index, int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setShort(int index, int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setMedium(int index, int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setInt(int index, int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setLong(int index, long value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setChar(int index, int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setFloat(int index, float value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setDouble(int index, double value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBytes(int index, ByteBuf src);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBytes(int index, ByteBuf src, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBytes(int index, byte[] src);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBytes(int index, byte[] src, int srcIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setBytes(int index, ByteBuffer src);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf setZero(int index, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(ByteBuf dst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(ByteBuf dst, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(ByteBuf dst, int dstIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(byte[] dst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(byte[] dst, int dstIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(ByteBuffer dst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf readBytes(OutputStream out, int length) throws IOException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf skipBytes(int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBoolean(boolean value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeByte(int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeShort(int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeMedium(int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeInt(int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeLong(long value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeChar(int value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeFloat(float value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeDouble(double value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBytes(ByteBuf src);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBytes(ByteBuf src, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBytes(ByteBuf src, int srcIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBytes(byte[] src);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBytes(byte[] src, int srcIndex, int length);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeBytes(ByteBuffer src);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
WrappedByteBuf writeZero(int length);
|
|
||||||
}
|
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer;
|
package io.netty.buffer;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests big-endian heap channel buffers
|
* Tests big-endian heap channel buffers
|
||||||
*/
|
*/
|
||||||
@ -39,7 +39,12 @@ public class BigEndianHeapChannelBufferTest extends AbstractChannelBufferTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void shouldNotAllowNullInConstructor() {
|
public void shouldNotAllowNullInConstructor1() {
|
||||||
new HeapByteBuf(null, 0);
|
new UnpooledHeapByteBuf(null, new byte[1], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = NullPointerException.class)
|
||||||
|
public void shouldNotAllowNullInConstructor2() {
|
||||||
|
new UnpooledHeapByteBuf(UnpooledByteBufAllocator.HEAP_BY_DEFAULT, null, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer;
|
package io.netty.buffer;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests duplicated channel buffers
|
* Tests duplicated channel buffers
|
||||||
*/
|
*/
|
||||||
@ -28,7 +28,7 @@ public class DuplicateChannelBufferTest extends AbstractChannelBufferTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ByteBuf newBuffer(int length) {
|
protected ByteBuf newBuffer(int length) {
|
||||||
buffer = new DuplicatedByteBuf(Unpooled.buffer(length));
|
buffer = new DuplicatedByteBuf((UnsafeByteBuf) Unpooled.buffer(length));
|
||||||
assertEquals(0, buffer.writerIndex());
|
assertEquals(0, buffer.writerIndex());
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer;
|
package io.netty.buffer;
|
||||||
|
|
||||||
import static io.netty.buffer.Unpooled.*;
|
import org.junit.Test;
|
||||||
import static org.easymock.EasyMock.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -26,7 +24,9 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
|
|
||||||
import org.junit.Test;
|
import static io.netty.buffer.Unpooled.*;
|
||||||
|
import static org.easymock.EasyMock.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests read-only channel buffers
|
* Tests read-only channel buffers
|
||||||
@ -46,7 +46,7 @@ public class ReadOnlyChannelBufferTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testUnwrap() {
|
public void testUnwrap() {
|
||||||
ByteBuf buf = buffer(1);
|
ByteBuf buf = buffer(1);
|
||||||
assertSame(buf, ((WrappedByteBuf) Unpooled.unmodifiableBuffer(buf)).unwrap());
|
assertSame(buf, ((UnsafeByteBuf) Unpooled.unmodifiableBuffer(buf)).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -74,7 +74,7 @@ public class ReadOnlyChannelBufferTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldForwardReadCallsBlindly() throws Exception {
|
public void shouldForwardReadCallsBlindly() throws Exception {
|
||||||
ByteBuf buf = createStrictMock(ByteBuf.class);
|
ByteBuf buf = createStrictMock(UnsafeByteBuf.class);
|
||||||
expect(buf.order()).andReturn(BIG_ENDIAN).anyTimes();
|
expect(buf.order()).andReturn(BIG_ENDIAN).anyTimes();
|
||||||
expect(buf.maxCapacity()).andReturn(65536).anyTimes();
|
expect(buf.maxCapacity()).andReturn(65536).anyTimes();
|
||||||
expect(buf.readerIndex()).andReturn(0).anyTimes();
|
expect(buf.readerIndex()).andReturn(0).anyTimes();
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerAdapter;
|
import io.netty.channel.ChannelHandlerAdapter;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
@ -64,7 +63,7 @@ public abstract class SpdyOrHttpChooser extends ChannelHandlerAdapter implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
@ -95,6 +96,16 @@ public class SpdySessionHandler
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||||
MessageBuf<Object> in = ctx.inboundMessageBuffer();
|
MessageBuf<Object> in = ctx.inboundMessageBuffer();
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundByteHandlerAdapter;
|
import io.netty.channel.ChannelInboundByteHandlerAdapter;
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
if (out.readableBytes() > oldOutSize) {
|
if (out.readableBytes() > oldOutSize) {
|
||||||
ctx.fireInboundBufferUpdated();
|
ctx.fireInboundBufferUpdated();
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundByteHandlerAdapter;
|
import io.netty.channel.ChannelOutboundByteHandlerAdapter;
|
||||||
@ -43,7 +44,7 @@ public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
ctx.flush(future);
|
ctx.flush(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,13 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.ChannelBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
import io.netty.channel.ChannelInboundByteHandler;
|
import io.netty.channel.ChannelInboundByteHandler;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
|
||||||
|
|
||||||
public abstract class ByteToMessageDecoder<O>
|
public abstract class ByteToMessageDecoder<O>
|
||||||
extends ChannelInboundHandlerAdapter implements ChannelInboundByteHandler {
|
extends ChannelInboundHandlerAdapter implements ChannelInboundByteHandler {
|
||||||
@ -36,7 +37,12 @@ public abstract class ByteToMessageDecoder<O>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,7 +98,7 @@ public abstract class ByteToMessageDecoder<O>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
|
|
||||||
if (decoded) {
|
if (decoded) {
|
||||||
decoded = false;
|
decoded = false;
|
||||||
@ -107,7 +113,7 @@ public abstract class ByteToMessageDecoder<O>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
|
|
||||||
if (decoded) {
|
if (decoded) {
|
||||||
ctx.fireInboundBufferUpdated();
|
ctx.fireInboundBufferUpdated();
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +67,7 @@ public class FixedLengthFrameDecoder extends ByteToMessageDecoder<Object> {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
if (allocateFullBuffer) {
|
if (allocateFullBuffer) {
|
||||||
return Unpooled.buffer(frameLength);
|
return ctx.alloc().buffer(frameLength);
|
||||||
} else {
|
} else {
|
||||||
return super.newInboundBuffer(ctx);
|
return super.newInboundBuffer(ctx);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
|
|
||||||
@ -426,7 +427,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder<Object> {
|
|||||||
* is overridden to avoid memory copy.
|
* is overridden to avoid memory copy.
|
||||||
*/
|
*/
|
||||||
protected ByteBuf extractFrame(ByteBuf buffer, int index, int length) {
|
protected ByteBuf extractFrame(ByteBuf buffer, int index, int length) {
|
||||||
ByteBuf frame = buffer.unsafe().newBuffer(length);
|
ByteBuf frame = Unpooled.buffer(length);
|
||||||
frame.writeBytes(buffer, index, length);
|
frame.writeBytes(buffer, index, length);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerAdapter;
|
import io.netty.channel.ChannelHandlerAdapter;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
import io.netty.channel.ChannelInboundMessageHandler;
|
import io.netty.channel.ChannelInboundMessageHandler;
|
||||||
import io.netty.channel.ChannelOutboundMessageHandler;
|
import io.netty.channel.ChannelOutboundMessageHandler;
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
|
||||||
|
|
||||||
public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN, OUTBOUND_OUT>
|
public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN, OUTBOUND_OUT>
|
||||||
extends ChannelHandlerAdapter
|
extends ChannelHandlerAdapter
|
||||||
@ -72,6 +73,11 @@ public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN
|
|||||||
return decoder.newInboundBuffer(ctx);
|
return decoder.newInboundBuffer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(
|
public void inboundBufferUpdated(
|
||||||
ChannelHandlerContext ctx) throws Exception {
|
ChannelHandlerContext ctx) throws Exception {
|
||||||
@ -83,6 +89,11 @@ public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN
|
|||||||
return encoder.newOutboundBuffer(ctx);
|
return encoder.newOutboundBuffer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush(ChannelHandlerContext ctx, ChannelFuture future) throws Exception {
|
public void flush(ChannelHandlerContext ctx, ChannelFuture future) throws Exception {
|
||||||
encoder.flush(ctx, future);
|
encoder.flush(ctx, future);
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelInboundMessageHandler;
|
import io.netty.channel.ChannelInboundMessageHandler;
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
|
||||||
|
|
||||||
public abstract class MessageToMessageDecoder<I, O>
|
public abstract class MessageToMessageDecoder<I, O>
|
||||||
extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<I> {
|
extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<I> {
|
||||||
@ -36,6 +37,11 @@ public abstract class MessageToMessageDecoder<I, O>
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx)
|
public void inboundBufferUpdated(ChannelHandlerContext ctx)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelPipeline;
|
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.util.internal.Signal;
|
import io.netty.util.internal.Signal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,8 +282,8 @@ public abstract class ReplayingDecoder<O, S> extends ByteToMessageDecoder<O> {
|
|||||||
|
|
||||||
static final Signal REPLAY = new Signal(ReplayingDecoder.class.getName() + ".REPLAY");
|
static final Signal REPLAY = new Signal(ReplayingDecoder.class.getName() + ".REPLAY");
|
||||||
|
|
||||||
private final ByteBuf cumulation = Unpooled.buffer();
|
private ByteBuf cumulation;
|
||||||
private final ReplayingDecoderBuffer replayable = new ReplayingDecoderBuffer(cumulation);
|
private ReplayingDecoderBuffer replayable;
|
||||||
private S state;
|
private S state;
|
||||||
private int checkpoint = -1;
|
private int checkpoint = -1;
|
||||||
|
|
||||||
@ -357,6 +357,8 @@ public abstract class ReplayingDecoder<O, S> extends ByteToMessageDecoder<O> {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(
|
public ByteBuf newInboundBuffer(
|
||||||
ChannelHandlerContext ctx) throws Exception {
|
ChannelHandlerContext ctx) throws Exception {
|
||||||
|
cumulation = ctx.alloc().buffer();
|
||||||
|
replayable = new ReplayingDecoderBuffer(cumulation);
|
||||||
return cumulation;
|
return cumulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +459,7 @@ public abstract class ReplayingDecoder<O, S> extends ByteToMessageDecoder<O> {
|
|||||||
|
|
||||||
private void fireInboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) {
|
private void fireInboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) {
|
||||||
final int oldReaderIndex = in.readerIndex();
|
final int oldReaderIndex = in.readerIndex();
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
final int newReaderIndex = in.readerIndex();
|
final int newReaderIndex = in.readerIndex();
|
||||||
checkpoint -= oldReaderIndex - newReaderIndex;
|
checkpoint -= oldReaderIndex - newReaderIndex;
|
||||||
ctx.fireInboundBufferUpdated();
|
ctx.fireInboundBufferUpdated();
|
||||||
|
@ -16,10 +16,12 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.buffer.ByteBufIndexFinder;
|
import io.netty.buffer.ByteBufIndexFinder;
|
||||||
import io.netty.buffer.ChannelBufType;
|
import io.netty.buffer.ChannelBufType;
|
||||||
import io.netty.buffer.SwappedByteBuf;
|
import io.netty.buffer.SwappedByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.util.internal.Signal;
|
import io.netty.util.internal.Signal;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -31,7 +33,7 @@ import java.nio.channels.GatheringByteChannel;
|
|||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
class ReplayingDecoderBuffer implements ByteBuf {
|
class ReplayingDecoderBuffer implements UnsafeByteBuf {
|
||||||
|
|
||||||
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
||||||
|
|
||||||
@ -79,8 +81,8 @@ class ReplayingDecoderBuffer implements ByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPooled() {
|
public ByteBufAllocator alloc() {
|
||||||
return false;
|
return buffer.alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -849,7 +851,27 @@ class ReplayingDecoderBuffer implements ByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Unsafe unsafe() {
|
public ByteBuffer internalNioBuffer() {
|
||||||
|
throw new UnreplayableOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer[] internalNioBuffers() {
|
||||||
|
throw new UnreplayableOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void discardSomeReadBytes() {
|
||||||
|
throw new UnreplayableOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free() {
|
||||||
|
throw new UnreplayableOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf unwrap() {
|
||||||
throw new UnreplayableOperationException();
|
throw new UnreplayableOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
package io.netty.handler.codec.base64;
|
package io.netty.handler.codec.base64;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for {@link ByteBuf} that encodes and decodes to and from
|
* Utility class for {@link ByteBuf} that encodes and decodes to and from
|
||||||
@ -115,10 +116,10 @@ public final class Base64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int len43 = len * 4 / 3;
|
int len43 = len * 4 / 3;
|
||||||
ByteBuf dest = src.unsafe().newBuffer(
|
ByteBuf dest = Unpooled.buffer(
|
||||||
len43 +
|
len43 +
|
||||||
(len % 3 > 0? 4 : 0) + // Account for padding
|
(len % 3 > 0 ? 4 : 0) + // Account for padding
|
||||||
(breakLines? len43 / MAX_LINE_LENGTH : 0)).order(src.order()); // New lines
|
(breakLines ? len43 / MAX_LINE_LENGTH : 0)).order(src.order()); // New lines
|
||||||
int d = 0;
|
int d = 0;
|
||||||
int e = 0;
|
int e = 0;
|
||||||
int len2 = len - 2;
|
int len2 = len - 2;
|
||||||
@ -219,7 +220,7 @@ public final class Base64 {
|
|||||||
byte[] DECODABET = decodabet(dialect);
|
byte[] DECODABET = decodabet(dialect);
|
||||||
|
|
||||||
int len34 = len * 3 / 4;
|
int len34 = len * 3 / 4;
|
||||||
ByteBuf dest = src.unsafe().newBuffer(len34).order(src.order()); // Upper limit on size of output
|
ByteBuf dest = Unpooled.buffer(len34).order(src.order()); // Upper limit on size of output
|
||||||
int outBuffPosn = 0;
|
int outBuffPosn = 0;
|
||||||
|
|
||||||
byte[] b4 = new byte[4];
|
byte[] b4 = new byte[4];
|
||||||
|
@ -17,6 +17,7 @@ package io.netty.handler.codec.serialization;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufOutputStream;
|
import io.netty.buffer.ByteBufOutputStream;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToByteEncoder;
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
@ -97,7 +98,7 @@ public class CompatibleObjectEncoder extends MessageToByteEncoder<Object> {
|
|||||||
oos.reset();
|
oos.reset();
|
||||||
|
|
||||||
// Also discard the byproduct to avoid OOM on the sending side.
|
// Also discard the byproduct to avoid OOM on the sending side.
|
||||||
out.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) out).discardSomeReadBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.util.internal;
|
package io.netty.util.internal;
|
||||||
|
|
||||||
|
import sun.misc.Cleaner;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedActionException;
|
import java.security.PrivilegedActionException;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
@ -38,11 +42,11 @@ public final class DetectionUtil {
|
|||||||
|
|
||||||
private static final int JAVA_VERSION = javaVersion0();
|
private static final int JAVA_VERSION = javaVersion0();
|
||||||
private static final boolean HAS_UNSAFE = hasUnsafe(AtomicInteger.class.getClassLoader());
|
private static final boolean HAS_UNSAFE = hasUnsafe(AtomicInteger.class.getClassLoader());
|
||||||
|
private static final boolean CAN_FREE_DIRECT_BUFFER;
|
||||||
private static final boolean IS_WINDOWS;
|
private static final boolean IS_WINDOWS;
|
||||||
private static final boolean IS_ROOT;
|
private static final boolean IS_ROOT;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
||||||
Pattern PERMISSION_DENIED = Pattern.compile(".*permission.*denied.*");
|
Pattern PERMISSION_DENIED = Pattern.compile(".*permission.*denied.*");
|
||||||
String os = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.UK);
|
String os = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.UK);
|
||||||
// windows
|
// windows
|
||||||
@ -82,6 +86,21 @@ public final class DetectionUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IS_ROOT = root;
|
IS_ROOT = root;
|
||||||
|
|
||||||
|
boolean canFreeDirectBuffer = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteBuffer direct = ByteBuffer.allocateDirect(1);
|
||||||
|
Field cleanerField = direct.getClass().getDeclaredField("cleaner");
|
||||||
|
cleanerField.setAccessible(true);
|
||||||
|
Cleaner cleaner = (Cleaner) cleanerField.get(direct);
|
||||||
|
cleaner.clean();
|
||||||
|
canFreeDirectBuffer = true;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,6 +126,10 @@ public final class DetectionUtil {
|
|||||||
return JAVA_VERSION;
|
return JAVA_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean canFreeDirectBuffer() {
|
||||||
|
return CAN_FREE_DIRECT_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean hasUnsafe(ClassLoader loader) {
|
private static boolean hasUnsafe(ClassLoader loader) {
|
||||||
boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
|
boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
|
||||||
if (noUnsafe) {
|
if (noUnsafe) {
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
package io.netty.handler.logging;
|
package io.netty.handler.logging;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.ChannelBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundByteHandler;
|
import io.netty.channel.ChannelInboundByteHandler;
|
||||||
@ -108,12 +109,22 @@ public class ByteLoggingHandler
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.logging;
|
package io.netty.handler.logging;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
@ -57,6 +58,16 @@ public class MessageLoggingHandler
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx)
|
public void inboundBufferUpdated(ChannelHandlerContext ctx)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -17,7 +17,8 @@ package io.netty.handler.ssl;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.ChannelBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFlushFutureNotifier;
|
import io.netty.channel.ChannelFlushFutureNotifier;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
@ -32,6 +33,10 @@ import io.netty.logging.InternalLogger;
|
|||||||
import io.netty.logging.InternalLoggerFactory;
|
import io.netty.logging.InternalLoggerFactory;
|
||||||
import io.netty.util.internal.DetectionUtil;
|
import io.netty.util.internal.DetectionUtil;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
import javax.net.ssl.SSLEngineResult;
|
||||||
|
import javax.net.ssl.SSLEngineResult.Status;
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.ClosedChannelException;
|
import java.nio.channels.ClosedChannelException;
|
||||||
@ -44,11 +49,6 @@ import java.util.concurrent.ScheduledFuture;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
|
||||||
import javax.net.ssl.SSLEngineResult;
|
|
||||||
import javax.net.ssl.SSLEngineResult.Status;
|
|
||||||
import javax.net.ssl.SSLException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds <a href="http://en.wikipedia.org/wiki/Transport_Layer_Security">SSL
|
* Adds <a href="http://en.wikipedia.org/wiki/Transport_Layer_Security">SSL
|
||||||
* · TLS</a> and StartTLS support to a {@link Channel}. Please refer
|
* · TLS</a> and StartTLS support to a {@link Channel}. Please refer
|
||||||
@ -376,12 +376,22 @@ public class SslHandler
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -401,7 +411,7 @@ public class SslHandler
|
|||||||
final ByteBuf in = ctx.outboundByteBuffer();
|
final ByteBuf in = ctx.outboundByteBuffer();
|
||||||
final ByteBuf out = ctx.nextOutboundByteBuffer();
|
final ByteBuf out = ctx.nextOutboundByteBuffer();
|
||||||
|
|
||||||
out.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) out).discardSomeReadBytes();
|
||||||
|
|
||||||
// Do not encrypt the first write request if this handler is
|
// Do not encrypt the first write request if this handler is
|
||||||
// created with startTLS flag turned on.
|
// created with startTLS flag turned on.
|
||||||
@ -473,7 +483,7 @@ public class SslHandler
|
|||||||
setHandshakeFailure(e);
|
setHandshakeFailure(e);
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
flush0(ctx, bytesConsumed);
|
flush0(ctx, bytesConsumed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.stream;
|
package io.netty.handler.stream;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
@ -95,6 +96,11 @@ public class ChunkedWriteHandler
|
|||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isWritable() {
|
private boolean isWritable() {
|
||||||
return pendingWrites.get() < maxPendingWrites;
|
return pendingWrites.get() < maxPendingWrites;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.bootstrap;
|
package io.netty.bootstrap;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
@ -229,6 +230,11 @@ public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap> {
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) {
|
public void inboundBufferUpdated(ChannelHandlerContext ctx) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.logging.InternalLogger;
|
import io.netty.logging.InternalLogger;
|
||||||
import io.netty.logging.InternalLoggerFactory;
|
import io.netty.logging.InternalLoggerFactory;
|
||||||
@ -146,6 +147,11 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return config().getAllocator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventLoop eventLoop() {
|
public EventLoop eventLoop() {
|
||||||
EventLoop eventLoop = this.eventLoop;
|
EventLoop eventLoop = this.eventLoop;
|
||||||
|
@ -106,7 +106,7 @@ import java.nio.channels.SelectionKey;
|
|||||||
*
|
*
|
||||||
* @apiviz.exclude ^io\.netty\.channel\.([a-z]+\.)+[^\.]+Channel$
|
* @apiviz.exclude ^io\.netty\.channel\.([a-z]+\.)+[^\.]+Channel$
|
||||||
*/
|
*/
|
||||||
public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelFutureFactory, Comparable<Channel> {
|
public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelPropertyAccess, Comparable<Channel> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the unique integer ID of this channel.
|
* Returns the unique integer ID of this channel.
|
||||||
@ -131,12 +131,6 @@ public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelFu
|
|||||||
*/
|
*/
|
||||||
ChannelConfig config();
|
ChannelConfig config();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ChannelPipeline} which handles {@link ChannelEvent}s
|
|
||||||
* associated with this channel.
|
|
||||||
*/
|
|
||||||
ChannelPipeline pipeline();
|
|
||||||
|
|
||||||
boolean isOpen();
|
boolean isOpen();
|
||||||
boolean isRegistered();
|
boolean isRegistered();
|
||||||
boolean isActive();
|
boolean isActive();
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.channel.socket.SocketChannelConfig;
|
import io.netty.channel.socket.SocketChannelConfig;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -136,4 +137,7 @@ public interface ChannelConfig {
|
|||||||
* if the specified value is {@code 0} or less than {@code 0}
|
* if the specified value is {@code 0} or less than {@code 0}
|
||||||
*/
|
*/
|
||||||
void setWriteSpinCount(int writeSpinCount);
|
void setWriteSpinCount(int writeSpinCount);
|
||||||
|
|
||||||
|
ByteBufAllocator getAllocator();
|
||||||
|
ByteBufAllocator setAllocator(ByteBufAllocator bufferPool);
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ import java.util.Set;
|
|||||||
* @apiviz.owns io.netty.channel.ChannelHandler
|
* @apiviz.owns io.netty.channel.ChannelHandler
|
||||||
*/
|
*/
|
||||||
public interface ChannelHandlerContext
|
public interface ChannelHandlerContext
|
||||||
extends AttributeMap, ChannelFutureFactory,
|
extends AttributeMap, ChannelPropertyAccess,
|
||||||
ChannelInboundInvoker, ChannelOutboundInvoker {
|
ChannelInboundInvoker, ChannelOutboundInvoker {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,11 +134,6 @@ public interface ChannelHandlerContext
|
|||||||
*/
|
*/
|
||||||
Channel channel();
|
Channel channel();
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the {@link ChannelPipeline} which belongs this {@link ChannelHandlerContext}.
|
|
||||||
*/
|
|
||||||
ChannelPipeline pipeline();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly
|
* The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly
|
||||||
* submit tasks that get executed in the event loop. For more informations please refer to the
|
* submit tasks that get executed in the event loop. For more informations please refer to the
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.ChannelBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,7 +35,12 @@ public abstract class ChannelInboundByteHandlerAdapter
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -44,7 +50,7 @@ public abstract class ChannelInboundByteHandlerAdapter
|
|||||||
inboundBufferUpdated(ctx, in);
|
inboundBufferUpdated(ctx, in);
|
||||||
} finally {
|
} finally {
|
||||||
if (!in.readable()) {
|
if (!in.readable()) {
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,10 @@ public interface ChannelInboundHandler extends ChannelStateHandler {
|
|||||||
* Return the {@link ChannelBuf} which will be used for inbound data for the given {@link ChannelHandlerContext}.
|
* Return the {@link ChannelBuf} which will be used for inbound data for the given {@link ChannelHandlerContext}.
|
||||||
*/
|
*/
|
||||||
ChannelBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception;
|
ChannelBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when this handler is not going to receive any inbound message anymore and thus it's safe to
|
||||||
|
* deallocate its inbound buffer.
|
||||||
|
*/
|
||||||
|
void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
@ -33,6 +34,11 @@ public abstract class ChannelInboundMessageHandlerAdapter<I>
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.util.UniqueName;
|
import io.netty.util.UniqueName;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -28,6 +29,7 @@ public class ChannelOption<T> extends UniqueName {
|
|||||||
|
|
||||||
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
|
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
|
||||||
|
|
||||||
|
public static final ChannelOption<ByteBufAllocator> ALLOCATOR = new ChannelOption<ByteBufAllocator>("ALLOCATOR");
|
||||||
public static final ChannelOption<Integer> CONNECT_TIMEOUT_MILLIS =
|
public static final ChannelOption<Integer> CONNECT_TIMEOUT_MILLIS =
|
||||||
new ChannelOption<Integer>("CONNECT_TIMEOUT_MILLIS");
|
new ChannelOption<Integer>("CONNECT_TIMEOUT_MILLIS");
|
||||||
public static final ChannelOption<Integer> WRITE_SPIN_COUNT =
|
public static final ChannelOption<Integer> WRITE_SPIN_COUNT =
|
||||||
|
@ -16,12 +16,18 @@
|
|||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.ChannelBuf;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
|
|
||||||
public abstract class ChannelOutboundByteHandlerAdapter
|
public abstract class ChannelOutboundByteHandlerAdapter
|
||||||
extends ChannelOutboundHandlerAdapter implements ChannelOutboundByteHandler {
|
extends ChannelOutboundHandlerAdapter implements ChannelOutboundByteHandler {
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,4 +19,10 @@ import io.netty.buffer.ChannelBuf;
|
|||||||
|
|
||||||
public interface ChannelOutboundHandler extends ChannelOperationHandler {
|
public interface ChannelOutboundHandler extends ChannelOperationHandler {
|
||||||
ChannelBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception;
|
ChannelBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when this handler is not allowed to send any outbound message anymore and thus it's safe to
|
||||||
|
* deallocate its outbound buffer.
|
||||||
|
*/
|
||||||
|
void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
@ -24,4 +25,9 @@ public abstract class ChannelOutboundMessageHandlerAdapter<I>
|
|||||||
public MessageBuf<I> newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public MessageBuf<I> newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory which is responsible to create new {@link ChannelFuture}'s
|
* Provides common methods between {@link Channel} and {@link ChannelHandlerContext}.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface ChannelFutureFactory {
|
interface ChannelPropertyAccess {
|
||||||
|
|
||||||
|
ChannelPipeline pipeline();
|
||||||
|
|
||||||
|
ByteBufAllocator alloc();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link ChannelFuture}
|
* Create a new {@link ChannelFuture}
|
@ -68,12 +68,22 @@ public class CombinedChannelHandler
|
|||||||
return in.newInboundBuffer(ctx);
|
return in.newInboundBuffer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
in.freeInboundBuffer(ctx, buf);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelBuf newOutboundBuffer(
|
public ChannelBuf newOutboundBuffer(
|
||||||
ChannelHandlerContext ctx) throws Exception {
|
ChannelHandlerContext ctx) throws Exception {
|
||||||
return out.newOutboundBuffer(ctx);
|
return out.newOutboundBuffer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
out.freeOutboundBuffer(ctx, buf);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
|
public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
|
||||||
if (in == null) {
|
if (in == null) {
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import io.netty.channel.socket.SocketChannelConfig;
|
import io.netty.channel.socket.SocketChannelConfig;
|
||||||
|
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
@ -28,14 +30,16 @@ import static io.netty.channel.ChannelOption.*;
|
|||||||
*/
|
*/
|
||||||
public class DefaultChannelConfig implements ChannelConfig {
|
public class DefaultChannelConfig implements ChannelConfig {
|
||||||
|
|
||||||
|
private static final ByteBufAllocator DEFAULT_ALLOCATOR = UnpooledByteBufAllocator.HEAP_BY_DEFAULT;
|
||||||
private static final int DEFAULT_CONNECT_TIMEOUT = 30000;
|
private static final int DEFAULT_CONNECT_TIMEOUT = 30000;
|
||||||
|
|
||||||
|
private volatile ByteBufAllocator allocator = DEFAULT_ALLOCATOR;
|
||||||
private volatile int connectTimeoutMillis = DEFAULT_CONNECT_TIMEOUT;
|
private volatile int connectTimeoutMillis = DEFAULT_CONNECT_TIMEOUT;
|
||||||
private volatile int writeSpinCount = 16;
|
private volatile int writeSpinCount = 16;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<ChannelOption<?>, Object> getOptions() {
|
public Map<ChannelOption<?>, Object> getOptions() {
|
||||||
return getOptions(null, CONNECT_TIMEOUT_MILLIS, WRITE_SPIN_COUNT);
|
return getOptions(null, CONNECT_TIMEOUT_MILLIS, WRITE_SPIN_COUNT, ALLOCATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<ChannelOption<?>, Object> getOptions(
|
protected Map<ChannelOption<?>, Object> getOptions(
|
||||||
@ -79,6 +83,9 @@ public class DefaultChannelConfig implements ChannelConfig {
|
|||||||
if (option == WRITE_SPIN_COUNT) {
|
if (option == WRITE_SPIN_COUNT) {
|
||||||
return (T) Integer.valueOf(getWriteSpinCount());
|
return (T) Integer.valueOf(getWriteSpinCount());
|
||||||
}
|
}
|
||||||
|
if (option == ALLOCATOR) {
|
||||||
|
return (T) getAllocator();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -91,6 +98,8 @@ public class DefaultChannelConfig implements ChannelConfig {
|
|||||||
setConnectTimeoutMillis((Integer) value);
|
setConnectTimeoutMillis((Integer) value);
|
||||||
} else if (option == WRITE_SPIN_COUNT) {
|
} else if (option == WRITE_SPIN_COUNT) {
|
||||||
setWriteSpinCount((Integer) value);
|
setWriteSpinCount((Integer) value);
|
||||||
|
} else if (option == ALLOCATOR) {
|
||||||
|
setAllocator((ByteBufAllocator) value);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -132,4 +141,19 @@ public class DefaultChannelConfig implements ChannelConfig {
|
|||||||
}
|
}
|
||||||
this.writeSpinCount = writeSpinCount;
|
this.writeSpinCount = writeSpinCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator getAllocator() {
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator setAllocator(ByteBufAllocator allocator) {
|
||||||
|
if (allocator == null) {
|
||||||
|
throw new NullPointerException("allocator");
|
||||||
|
}
|
||||||
|
ByteBufAllocator oldAllocator = this.allocator;
|
||||||
|
this.allocator = allocator;
|
||||||
|
return oldAllocator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.channel;
|
package io.netty.channel;
|
||||||
|
|
||||||
import static io.netty.channel.DefaultChannelPipeline.*;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.buffer.ChannelBuf;
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.util.DefaultAttributeMap;
|
import io.netty.util.DefaultAttributeMap;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
@ -34,42 +35,47 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static io.netty.channel.DefaultChannelPipeline.*;
|
||||||
|
|
||||||
final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
|
final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
|
||||||
|
|
||||||
private static final EnumSet<ChannelHandlerType> EMPTY_TYPE = EnumSet.noneOf(ChannelHandlerType.class);
|
private static final EnumSet<ChannelHandlerType> EMPTY_TYPE = EnumSet.noneOf(ChannelHandlerType.class);
|
||||||
|
|
||||||
static final int DIR_INBOUND = 0x00000001;
|
static final int DIR_INBOUND = 1;
|
||||||
static final int DIR_OUTBOUND = 0x80000000;
|
static final int DIR_OUTBOUND = 2;
|
||||||
|
|
||||||
|
private static final int FLAG_NEEDS_LAZY_INIT = 4;
|
||||||
|
|
||||||
volatile DefaultChannelHandlerContext next;
|
volatile DefaultChannelHandlerContext next;
|
||||||
volatile DefaultChannelHandlerContext prev;
|
volatile DefaultChannelHandlerContext prev;
|
||||||
|
|
||||||
private final Channel channel;
|
private final Channel channel;
|
||||||
private final DefaultChannelPipeline pipeline;
|
private final DefaultChannelPipeline pipeline;
|
||||||
EventExecutor executor; // not thread-safe but OK because it never changes once set.
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Set<ChannelHandlerType> type;
|
private final Set<ChannelHandlerType> type;
|
||||||
final int directions;
|
|
||||||
private final ChannelHandler handler;
|
private final ChannelHandler handler;
|
||||||
|
final int flags;
|
||||||
|
final AtomicBoolean readable = new AtomicBoolean(true);
|
||||||
|
|
||||||
MessageBuf<Object> inMsgBuf;
|
EventExecutor executor; // not thread-safe but OK because it never changes once set.
|
||||||
ByteBuf inByteBuf;
|
|
||||||
MessageBuf<Object> outMsgBuf;
|
private MessageBuf<Object> inMsgBuf;
|
||||||
ByteBuf outByteBuf;
|
private UnsafeByteBuf inByteBuf;
|
||||||
|
private MessageBuf<Object> outMsgBuf;
|
||||||
|
private UnsafeByteBuf outByteBuf;
|
||||||
|
|
||||||
// When the two handlers run in a different thread and they are next to each other,
|
// When the two handlers run in a different thread and they are next to each other,
|
||||||
// each other's buffers can be accessed at the same time resulting in a race condition.
|
// each other's buffers can be accessed at the same time resulting in a race condition.
|
||||||
// To avoid such situation, we lazily creates an additional thread-safe buffer called
|
// To avoid such situation, we lazily creates an additional thread-safe buffer called
|
||||||
// 'bridge' so that the two handlers access each other's buffer only via the bridges.
|
// 'bridge' so that the two handlers access each other's buffer only via the bridges.
|
||||||
// The content written into a bridge is flushed into the actual buffer by flushBridge().
|
// The content written into a bridge is flushed into the actual buffer by flushBridge().
|
||||||
final AtomicReference<MessageBridge> inMsgBridge;
|
private final AtomicReference<MessageBridge> inMsgBridge;
|
||||||
final AtomicReference<MessageBridge> outMsgBridge;
|
AtomicReference<MessageBridge> outMsgBridge;
|
||||||
final AtomicReference<ByteBridge> inByteBridge;
|
private final AtomicReference<ByteBridge> inByteBridge;
|
||||||
final AtomicReference<ByteBridge> outByteBridge;
|
AtomicReference<ByteBridge> outByteBridge;
|
||||||
|
|
||||||
final AtomicBoolean readable = new AtomicBoolean(true);
|
|
||||||
|
|
||||||
// Runnables that calls handlers
|
// Runnables that calls handlers
|
||||||
final Runnable fireChannelRegisteredTask = new Runnable() {
|
private final Runnable fireChannelRegisteredTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
@ -80,7 +86,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final Runnable fireChannelUnregisteredTask = new Runnable() {
|
private final Runnable fireChannelUnregisteredTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
@ -91,7 +97,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final Runnable fireChannelActiveTask = new Runnable() {
|
private final Runnable fireChannelActiveTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
@ -102,7 +108,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final Runnable fireChannelInactiveTask = new Runnable() {
|
private final Runnable fireChannelInactiveTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
@ -113,7 +119,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final Runnable curCtxFireInboundBufferUpdatedTask = new Runnable() {
|
private final Runnable curCtxFireInboundBufferUpdatedTask = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
@ -148,6 +154,55 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private final Runnable freeInboundBufferTask = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
|
if (ctx.handler instanceof ChannelInboundHandler) {
|
||||||
|
ChannelInboundHandler h = (ChannelInboundHandler) ctx.handler;
|
||||||
|
try {
|
||||||
|
if (ctx.inByteBuf != null) {
|
||||||
|
h.freeInboundBuffer(ctx, ctx.inByteBuf);
|
||||||
|
} else {
|
||||||
|
h.freeInboundBuffer(ctx, ctx.inMsgBuf);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
pipeline.notifyHandlerException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultChannelHandlerContext nextCtx = nextContext(ctx.next, DIR_INBOUND);
|
||||||
|
if (nextCtx != null) {
|
||||||
|
nextCtx.callFreeInboundBuffer();
|
||||||
|
} else {
|
||||||
|
// Freed all inbound buffers. Free all outbound buffers in a reverse order.
|
||||||
|
pipeline.firstContext(DIR_OUTBOUND).callFreeOutboundBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final Runnable freeOutboundBufferTask = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DefaultChannelHandlerContext ctx = DefaultChannelHandlerContext.this;
|
||||||
|
if (ctx.handler instanceof ChannelOutboundHandler) {
|
||||||
|
ChannelOutboundHandler h = (ChannelOutboundHandler) ctx.handler;
|
||||||
|
try {
|
||||||
|
if (ctx.outByteBuf != null) {
|
||||||
|
h.freeOutboundBuffer(ctx, ctx.outByteBuf);
|
||||||
|
} else {
|
||||||
|
h.freeOutboundBuffer(ctx, ctx.outMsgBuf);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
pipeline.notifyHandlerException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultChannelHandlerContext nextCtx = nextContext(ctx.prev, DIR_OUTBOUND);
|
||||||
|
if (nextCtx != null) {
|
||||||
|
nextCtx.callFreeOutboundBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
DefaultChannelHandlerContext(
|
DefaultChannelHandlerContext(
|
||||||
@ -162,25 +217,25 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
throw new NullPointerException("handler");
|
throw new NullPointerException("handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
// Determine the type of the specified handler.
|
// Determine the type of the specified handler.
|
||||||
int typeValue = 0;
|
|
||||||
EnumSet<ChannelHandlerType> type = EMPTY_TYPE.clone();
|
EnumSet<ChannelHandlerType> type = EMPTY_TYPE.clone();
|
||||||
if (handler instanceof ChannelStateHandler) {
|
if (handler instanceof ChannelStateHandler) {
|
||||||
type.add(ChannelHandlerType.STATE);
|
type.add(ChannelHandlerType.STATE);
|
||||||
typeValue |= DIR_INBOUND;
|
flags |= DIR_INBOUND;
|
||||||
if (handler instanceof ChannelInboundHandler) {
|
if (handler instanceof ChannelInboundHandler) {
|
||||||
type.add(ChannelHandlerType.INBOUND);
|
type.add(ChannelHandlerType.INBOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (handler instanceof ChannelOperationHandler) {
|
if (handler instanceof ChannelOperationHandler) {
|
||||||
type.add(ChannelHandlerType.OPERATION);
|
type.add(ChannelHandlerType.OPERATION);
|
||||||
typeValue |= DIR_OUTBOUND;
|
flags |= DIR_OUTBOUND;
|
||||||
if (handler instanceof ChannelOutboundHandler) {
|
if (handler instanceof ChannelOutboundHandler) {
|
||||||
type.add(ChannelHandlerType.OUTBOUND);
|
type.add(ChannelHandlerType.OUTBOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.type = Collections.unmodifiableSet(type);
|
this.type = Collections.unmodifiableSet(type);
|
||||||
directions = typeValue;
|
|
||||||
|
|
||||||
this.prev = prev;
|
this.prev = prev;
|
||||||
this.next = next;
|
this.next = next;
|
||||||
@ -217,8 +272,8 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
throw new ChannelPipelineException("A user handler's newInboundBuffer() returned null");
|
throw new ChannelPipelineException("A user handler's newInboundBuffer() returned null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf instanceof ByteBuf) {
|
if (buf instanceof UnsafeByteBuf) {
|
||||||
inByteBuf = (ByteBuf) buf;
|
inByteBuf = (UnsafeByteBuf) buf;
|
||||||
inByteBridge = new AtomicReference<ByteBridge>();
|
inByteBridge = new AtomicReference<ByteBridge>();
|
||||||
inMsgBuf = null;
|
inMsgBuf = null;
|
||||||
inMsgBridge = null;
|
inMsgBridge = null;
|
||||||
@ -238,29 +293,15 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type.contains(ChannelHandlerType.OUTBOUND)) {
|
if (type.contains(ChannelHandlerType.OUTBOUND)) {
|
||||||
ChannelBuf buf;
|
if (prev == null) {
|
||||||
try {
|
// Special case: if pref == null, it means this context for HeadHandler.
|
||||||
buf = ((ChannelOutboundHandler) handler).newOutboundBuffer(this);
|
// HeadHandler is an outbound handler instantiated by the constructor of DefaultChannelPipeline.
|
||||||
} catch (Exception e) {
|
// Because Channel is not really fully initialized at this point, we should not call
|
||||||
throw new ChannelPipelineException("A user handler failed to create a new outbound buffer.", e);
|
// newOutboundBuffer() yet because it will usually lead to NPE.
|
||||||
}
|
// To work around this problem, we lazily initialize the outbound buffer for this special case.
|
||||||
|
flags |= FLAG_NEEDS_LAZY_INIT;
|
||||||
if (buf == null) {
|
|
||||||
throw new ChannelPipelineException("A user handler's newOutboundBuffer() returned null");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf instanceof ByteBuf) {
|
|
||||||
outByteBuf = (ByteBuf) buf;
|
|
||||||
outByteBridge = new AtomicReference<ByteBridge>();
|
|
||||||
outMsgBuf = null;
|
|
||||||
outMsgBridge = null;
|
|
||||||
} else if (buf instanceof MessageBuf) {
|
|
||||||
outByteBuf = null;
|
|
||||||
outByteBridge = null;
|
|
||||||
outMsgBuf = (MessageBuf<Object>) buf;
|
|
||||||
outMsgBridge = new AtomicReference<MessageBridge>();
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error();
|
initOutboundBuffer();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outByteBuf = null;
|
outByteBuf = null;
|
||||||
@ -268,6 +309,43 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
outMsgBuf = null;
|
outMsgBuf = null;
|
||||||
outMsgBridge = null;
|
outMsgBridge = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lazyInitOutboundBuffer() {
|
||||||
|
if ((flags & FLAG_NEEDS_LAZY_INIT) != 0) {
|
||||||
|
if (outByteBuf == null && outMsgBuf == null) {
|
||||||
|
initOutboundBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initOutboundBuffer() {
|
||||||
|
ChannelBuf buf;
|
||||||
|
try {
|
||||||
|
buf = ((ChannelOutboundHandler) handler).newOutboundBuffer(this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ChannelPipelineException("A user handler failed to create a new outbound buffer.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf == null) {
|
||||||
|
throw new ChannelPipelineException("A user handler's newOutboundBuffer() returned null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf instanceof UnsafeByteBuf) {
|
||||||
|
outByteBuf = (UnsafeByteBuf) buf;
|
||||||
|
outByteBridge = new AtomicReference<ByteBridge>();
|
||||||
|
outMsgBuf = null;
|
||||||
|
outMsgBridge = null;
|
||||||
|
} else if (buf instanceof MessageBuf) {
|
||||||
|
outByteBuf = null;
|
||||||
|
outByteBridge = null;
|
||||||
|
outMsgBuf = (MessageBuf<Object>) buf;
|
||||||
|
outMsgBridge = new AtomicReference<MessageBridge>();
|
||||||
|
} else {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillBridge() {
|
void fillBridge() {
|
||||||
@ -309,6 +387,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazyInitOutboundBuffer();
|
||||||
if (outMsgBridge != null) {
|
if (outMsgBridge != null) {
|
||||||
MessageBridge bridge = outMsgBridge.get();
|
MessageBridge bridge = outMsgBridge.get();
|
||||||
if (bridge != null) {
|
if (bridge != null) {
|
||||||
@ -332,6 +411,11 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return channel.config().getAllocator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventExecutor executor() {
|
public EventExecutor executor() {
|
||||||
if (executor == null) {
|
if (executor == null) {
|
||||||
@ -405,16 +489,22 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasOutboundByteBuffer() {
|
public boolean hasOutboundByteBuffer() {
|
||||||
|
lazyInitOutboundBuffer();
|
||||||
return outByteBuf != null;
|
return outByteBuf != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasOutboundMessageBuffer() {
|
public boolean hasOutboundMessageBuffer() {
|
||||||
|
lazyInitOutboundBuffer();
|
||||||
return outMsgBuf != null;
|
return outMsgBuf != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf outboundByteBuffer() {
|
public ByteBuf outboundByteBuffer() {
|
||||||
|
if (outMsgBuf == null) {
|
||||||
|
lazyInitOutboundBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
if (outByteBuf == null) {
|
if (outByteBuf == null) {
|
||||||
if (handler instanceof ChannelOutboundHandler) {
|
if (handler instanceof ChannelOutboundHandler) {
|
||||||
throw new NoSuchBufferException(String.format(
|
throw new NoSuchBufferException(String.format(
|
||||||
@ -434,6 +524,10 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> MessageBuf<T> outboundMessageBuffer() {
|
public <T> MessageBuf<T> outboundMessageBuffer() {
|
||||||
|
if (outMsgBuf == null) {
|
||||||
|
initOutboundBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
if (outMsgBuf == null) {
|
if (outMsgBuf == null) {
|
||||||
if (handler instanceof ChannelOutboundHandler) {
|
if (handler instanceof ChannelOutboundHandler) {
|
||||||
throw new NoSuchBufferException(String.format(
|
throw new NoSuchBufferException(String.format(
|
||||||
@ -470,7 +564,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
||||||
* {@link Throwable}.
|
* {@link Throwable}.
|
||||||
*/
|
*/
|
||||||
<T> T executeOnEventLoop(Callable<T> c) throws Exception {
|
private <T> T executeOnEventLoop(Callable<T> c) throws Exception {
|
||||||
return getFromFuture(executor().submit(c));
|
return getFromFuture(executor().submit(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,7 +607,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
||||||
* {@link Throwable}.
|
* {@link Throwable}.
|
||||||
*/
|
*/
|
||||||
<T> T getFromFuture(Future<T> future) throws Exception {
|
private static <T> T getFromFuture(Future<T> future) throws Exception {
|
||||||
try {
|
try {
|
||||||
return future.get();
|
return future.get();
|
||||||
} catch (ExecutionException ex) {
|
} catch (ExecutionException ex) {
|
||||||
@ -547,7 +641,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
* @throws ChannelPipelineException with a {@link Throwable} as a cause, if the task threw another type of
|
||||||
* {@link Throwable}.
|
* {@link Throwable}.
|
||||||
*/
|
*/
|
||||||
void waitForFuture(Future future) {
|
static void waitForFuture(Future<?> future) {
|
||||||
try {
|
try {
|
||||||
future.get();
|
future.get();
|
||||||
} catch (ExecutionException ex) {
|
} catch (ExecutionException ex) {
|
||||||
@ -585,7 +679,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
ByteBuf currentInboundByteBuf = inboundByteBuffer();
|
ByteBuf currentInboundByteBuf = inboundByteBuffer();
|
||||||
|
|
||||||
this.inByteBuf = newInboundByteBuf;
|
inByteBuf = (UnsafeByteBuf) newInboundByteBuf;
|
||||||
return currentInboundByteBuf;
|
return currentInboundByteBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +705,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
MessageBuf<T> currentInboundMsgBuf = inboundMessageBuffer();
|
MessageBuf<T> currentInboundMsgBuf = inboundMessageBuffer();
|
||||||
|
|
||||||
this.inMsgBuf = (MessageBuf<Object>) newInboundMsgBuf;
|
inMsgBuf = (MessageBuf<Object>) newInboundMsgBuf;
|
||||||
return currentInboundMsgBuf;
|
return currentInboundMsgBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +730,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
ByteBuf currentOutboundByteBuf = outboundByteBuffer();
|
ByteBuf currentOutboundByteBuf = outboundByteBuffer();
|
||||||
|
|
||||||
this.outByteBuf = newOutboundByteBuf;
|
outByteBuf = (UnsafeByteBuf) newOutboundByteBuf;
|
||||||
return currentOutboundByteBuf;
|
return currentOutboundByteBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,7 +756,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
MessageBuf<T> currentOutboundMsgBuf = outboundMessageBuffer();
|
MessageBuf<T> currentOutboundMsgBuf = outboundMessageBuffer();
|
||||||
|
|
||||||
this.outMsgBuf = (MessageBuf<Object>) newOutboundMsgBuf;
|
outMsgBuf = (MessageBuf<Object>) newOutboundMsgBuf;
|
||||||
return currentOutboundMsgBuf;
|
return currentOutboundMsgBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,12 +790,36 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNextOutboundByteBuffer() {
|
public boolean hasNextOutboundByteBuffer() {
|
||||||
return DefaultChannelPipeline.hasNextOutboundByteBuffer(prev);
|
DefaultChannelHandlerContext ctx = prev;
|
||||||
|
for (;;) {
|
||||||
|
if (ctx == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.lazyInitOutboundBuffer();
|
||||||
|
|
||||||
|
if (ctx.outByteBridge != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ctx = ctx.prev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNextOutboundMessageBuffer() {
|
public boolean hasNextOutboundMessageBuffer() {
|
||||||
return DefaultChannelPipeline.hasNextOutboundMessageBuffer(prev);
|
DefaultChannelHandlerContext ctx = prev;
|
||||||
|
for (;;) {
|
||||||
|
if (ctx == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.lazyInitOutboundBuffer();
|
||||||
|
|
||||||
|
if (ctx.outMsgBridge != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ctx = ctx.prev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -728,7 +846,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
} else {
|
} else {
|
||||||
ByteBridge bridge = ctx.inByteBridge.get();
|
ByteBridge bridge = ctx.inByteBridge.get();
|
||||||
if (bridge == null) {
|
if (bridge == null) {
|
||||||
bridge = new ByteBridge();
|
bridge = new ByteBridge(ctx);
|
||||||
if (!ctx.inByteBridge.compareAndSet(null, bridge)) {
|
if (!ctx.inByteBridge.compareAndSet(null, bridge)) {
|
||||||
bridge = ctx.inByteBridge.get();
|
bridge = ctx.inByteBridge.get();
|
||||||
}
|
}
|
||||||
@ -779,12 +897,12 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf nextOutboundByteBuffer() {
|
public ByteBuf nextOutboundByteBuffer() {
|
||||||
return DefaultChannelPipeline.nextOutboundByteBuffer(prev);
|
return pipeline.nextOutboundByteBuffer(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageBuf<Object> nextOutboundMessageBuffer() {
|
public MessageBuf<Object> nextOutboundMessageBuffer() {
|
||||||
return DefaultChannelPipeline.nextOutboundMessageBuffer(prev);
|
return pipeline.nextOutboundMessageBuffer(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -876,8 +994,8 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
} else {
|
} else {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"An exceptionCaught() event was fired, and it reached at the end of the " +
|
"An exceptionCaught() event was fired, and it reached at the end of the " +
|
||||||
"pipeline. It usually means the last inbound handler in the pipeline did not " +
|
"pipeline. It usually means the last inbound handler in the pipeline did not " +
|
||||||
"handle the exception.", cause);
|
"handle the exception.", cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,6 +1129,25 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
return pipeline.write(prev, message, future);
|
return pipeline.write(prev, message, future);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void callFreeInboundBuffer() {
|
||||||
|
EventExecutor executor = executor();
|
||||||
|
if (executor.inEventLoop()) {
|
||||||
|
freeInboundBufferTask.run();
|
||||||
|
} else {
|
||||||
|
executor.execute(freeInboundBufferTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Invocation initiated by {@link #freeInboundBufferTask} after freeing all inbound buffers. */
|
||||||
|
private void callFreeOutboundBuffer() {
|
||||||
|
EventExecutor executor = executor();
|
||||||
|
if (executor.inEventLoop()) {
|
||||||
|
freeOutboundBufferTask.run();
|
||||||
|
} else {
|
||||||
|
executor.execute(freeOutboundBufferTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture newFuture() {
|
public ChannelFuture newFuture() {
|
||||||
return channel.newFuture();
|
return channel.newFuture();
|
||||||
@ -1028,9 +1165,10 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
|
|
||||||
static final class MessageBridge {
|
static final class MessageBridge {
|
||||||
final MessageBuf<Object> msgBuf = Unpooled.messageBuffer();
|
final MessageBuf<Object> msgBuf = Unpooled.messageBuffer();
|
||||||
final Queue<Object[]> exchangeBuf = new ConcurrentLinkedQueue<Object[]>();
|
|
||||||
|
|
||||||
void fill() {
|
private final Queue<Object[]> exchangeBuf = new ConcurrentLinkedQueue<Object[]>();
|
||||||
|
|
||||||
|
private void fill() {
|
||||||
if (msgBuf.isEmpty()) {
|
if (msgBuf.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1039,7 +1177,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
exchangeBuf.add(data);
|
exchangeBuf.add(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush(MessageBuf<Object> out) {
|
private void flush(MessageBuf<Object> out) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Object[] data = exchangeBuf.poll();
|
Object[] data = exchangeBuf.poll();
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
@ -1052,26 +1190,48 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final class ByteBridge {
|
static final class ByteBridge {
|
||||||
final ByteBuf byteBuf = Unpooled.buffer();
|
final UnsafeByteBuf byteBuf;
|
||||||
final Queue<ByteBuf> exchangeBuf = new ConcurrentLinkedQueue<ByteBuf>();
|
|
||||||
|
|
||||||
void fill() {
|
private final Queue<UnsafeByteBuf> exchangeBuf = new ConcurrentLinkedQueue<UnsafeByteBuf>();
|
||||||
|
private final ChannelHandlerContext ctx;
|
||||||
|
|
||||||
|
ByteBridge(ChannelHandlerContext ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
// TODO Choose whether to use heap or direct buffer depending on the context's buffer type.
|
||||||
|
byteBuf = (UnsafeByteBuf) ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fill() {
|
||||||
if (!byteBuf.readable()) {
|
if (!byteBuf.readable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ByteBuf data = byteBuf.readBytes(byteBuf.readableBytes());
|
|
||||||
byteBuf.discardReadBytes();
|
int dataLen = byteBuf.readableBytes();
|
||||||
exchangeBuf.add(data);
|
ByteBuf data;
|
||||||
|
if (byteBuf.isDirect()) {
|
||||||
|
data = ctx.alloc().directBuffer(dataLen, dataLen);
|
||||||
|
} else {
|
||||||
|
data = ctx.alloc().buffer(dataLen, dataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
byteBuf.readBytes(data);
|
||||||
|
byteBuf.discardSomeReadBytes();
|
||||||
|
|
||||||
|
exchangeBuf.add((UnsafeByteBuf) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush(ByteBuf out) {
|
private void flush(ByteBuf out) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ByteBuf data = exchangeBuf.poll();
|
UnsafeByteBuf data = exchangeBuf.poll();
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeBytes(data);
|
try {
|
||||||
|
out.writeBytes(data);
|
||||||
|
} finally {
|
||||||
|
data.free();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import io.netty.buffer.ChannelBuf;
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.logging.InternalLogger;
|
import io.netty.logging.InternalLogger;
|
||||||
import io.netty.logging.InternalLoggerFactory;
|
import io.netty.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
@ -358,7 +359,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
private DefaultChannelHandlerContext remove(final DefaultChannelHandlerContext ctx) {
|
private DefaultChannelHandlerContext remove(final DefaultChannelHandlerContext ctx) {
|
||||||
DefaultChannelHandlerContext context;
|
DefaultChannelHandlerContext context;
|
||||||
Future future;
|
Future<?> future;
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (head == tail) {
|
if (head == tail) {
|
||||||
@ -407,7 +408,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
// Run the following 'waiting' code outside of the above synchronized block
|
// Run the following 'waiting' code outside of the above synchronized block
|
||||||
// in order to avoid deadlock
|
// in order to avoid deadlock
|
||||||
|
|
||||||
context.waitForFuture(future);
|
waitForFuture(future);
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@ -497,9 +498,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
private ChannelHandler replace(
|
private ChannelHandler replace(
|
||||||
final DefaultChannelHandlerContext ctx, final String newName, ChannelHandler newHandler) {
|
final DefaultChannelHandlerContext ctx, final String newName, ChannelHandler newHandler) {
|
||||||
Future future;
|
Future<?> future;
|
||||||
DefaultChannelHandlerContext context;
|
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (ctx == head) {
|
if (ctx == head) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
@ -528,7 +527,6 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context = oldTail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -555,7 +553,6 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context = newCtx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -563,7 +560,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
// Run the following 'waiting' code outside of the above synchronized block
|
// Run the following 'waiting' code outside of the above synchronized block
|
||||||
// in order to avoid deadlock
|
// in order to avoid deadlock
|
||||||
|
|
||||||
context.waitForFuture(future);
|
waitForFuture(future);
|
||||||
|
|
||||||
return ctx.handler();
|
return ctx.handler();
|
||||||
}
|
}
|
||||||
@ -866,33 +863,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
return nextOutboundByteBuffer(tail);
|
return nextOutboundByteBuffer(tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean hasNextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
ByteBuf nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
||||||
for (;;) {
|
|
||||||
if (ctx == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.outByteBridge != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ctx = ctx.prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean hasNextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
|
||||||
for (;;) {
|
|
||||||
if (ctx == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.outMsgBridge != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ctx = ctx.prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static ByteBuf nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
|
|
||||||
final DefaultChannelHandlerContext initialCtx = ctx;
|
final DefaultChannelHandlerContext initialCtx = ctx;
|
||||||
final Thread currentThread = Thread.currentThread();
|
final Thread currentThread = Thread.currentThread();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -910,13 +881,13 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.outByteBuf != null) {
|
if (ctx.hasOutboundByteBuffer()) {
|
||||||
if (ctx.executor().inEventLoop(currentThread)) {
|
if (ctx.executor().inEventLoop(currentThread)) {
|
||||||
return ctx.outByteBuf;
|
return ctx.outboundByteBuffer();
|
||||||
} else {
|
} else {
|
||||||
ByteBridge bridge = ctx.outByteBridge.get();
|
ByteBridge bridge = ctx.outByteBridge.get();
|
||||||
if (bridge == null) {
|
if (bridge == null) {
|
||||||
bridge = new ByteBridge();
|
bridge = new ByteBridge(ctx);
|
||||||
if (!ctx.outByteBridge.compareAndSet(null, bridge)) {
|
if (!ctx.outByteBridge.compareAndSet(null, bridge)) {
|
||||||
bridge = ctx.outByteBridge.get();
|
bridge = ctx.outByteBridge.get();
|
||||||
}
|
}
|
||||||
@ -928,7 +899,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static MessageBuf<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
MessageBuf<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
|
||||||
final DefaultChannelHandlerContext initialCtx = ctx;
|
final DefaultChannelHandlerContext initialCtx = ctx;
|
||||||
final Thread currentThread = Thread.currentThread();
|
final Thread currentThread = Thread.currentThread();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -946,9 +917,9 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.outMsgBuf != null) {
|
if (ctx.hasOutboundMessageBuffer()) {
|
||||||
if (ctx.executor().inEventLoop(currentThread)) {
|
if (ctx.executor().inEventLoop(currentThread)) {
|
||||||
return ctx.outMsgBuf;
|
return ctx.outboundMessageBuffer();
|
||||||
} else {
|
} else {
|
||||||
MessageBridge bridge = ctx.outMsgBridge.get();
|
MessageBridge bridge = ctx.outMsgBridge.get();
|
||||||
if (bridge == null) {
|
if (bridge == null) {
|
||||||
@ -972,6 +943,11 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
@Override
|
@Override
|
||||||
public void fireChannelUnregistered() {
|
public void fireChannelUnregistered() {
|
||||||
head.fireChannelUnregistered();
|
head.fireChannelUnregistered();
|
||||||
|
|
||||||
|
// Free all buffers if channel is closed and unregistered.
|
||||||
|
if (!channel.isOpen()) {
|
||||||
|
head.callFreeInboundBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1232,8 +1208,8 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
notifyHandlerException(t);
|
notifyHandlerException(t);
|
||||||
} finally {
|
} finally {
|
||||||
if (ctx.outByteBuf != null) {
|
if (ctx.hasOutboundByteBuffer()) {
|
||||||
ByteBuf buf = ctx.outByteBuf;
|
ByteBuf buf = ctx.outboundByteBuffer();
|
||||||
if (!buf.readable()) {
|
if (!buf.readable()) {
|
||||||
buf.discardReadBytes();
|
buf.discardReadBytes();
|
||||||
}
|
}
|
||||||
@ -1289,10 +1265,10 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
if (msgBuf) {
|
if (msgBuf) {
|
||||||
ctx.outMsgBuf.add(message);
|
ctx.outboundMessageBuffer().add(message);
|
||||||
} else {
|
} else {
|
||||||
ByteBuf buf = (ByteBuf) message;
|
ByteBuf buf = (ByteBuf) message;
|
||||||
ctx.outByteBuf.writeBytes(buf, buf.readerIndex(), buf.readableBytes());
|
ctx.outboundByteBuffer().writeBytes(buf, buf.readerIndex(), buf.readableBytes());
|
||||||
}
|
}
|
||||||
flush0(ctx, future);
|
flush0(ctx, future);
|
||||||
return future;
|
return future;
|
||||||
@ -1325,12 +1301,12 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultChannelHandlerContext firstContext(int direction) {
|
DefaultChannelHandlerContext firstContext(int direction) {
|
||||||
assert direction == DIR_INBOUND || direction == DIR_OUTBOUND;
|
assert direction == DIR_INBOUND || direction == DIR_OUTBOUND;
|
||||||
if (direction > 0) {
|
if (direction == DIR_INBOUND) {
|
||||||
return nextContext(head.next, direction);
|
return nextContext(head.next, DIR_INBOUND);
|
||||||
} else {
|
} else { // DIR_OUTBOUND
|
||||||
return nextContext(tail, direction);
|
return nextContext(tail, DIR_OUTBOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,15 +1318,15 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DefaultChannelHandlerContext realCtx = ctx;
|
DefaultChannelHandlerContext realCtx = ctx;
|
||||||
if (direction > 0) {
|
if (direction == DIR_INBOUND) {
|
||||||
while ((realCtx.directions & direction) == 0) {
|
while ((realCtx.flags & DIR_INBOUND) == 0) {
|
||||||
realCtx = realCtx.next;
|
realCtx = realCtx.next;
|
||||||
if (realCtx == null) {
|
if (realCtx == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else { // DIR_OUTBOUND
|
||||||
while ((realCtx.directions & direction) == 0) {
|
while ((realCtx.flags & DIR_OUTBOUND) == 0) {
|
||||||
realCtx = realCtx.prev;
|
realCtx = realCtx.prev;
|
||||||
if (realCtx == null) {
|
if (realCtx == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -1448,8 +1424,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
public ChannelBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ChannelBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
switch (channel.metadata().bufferType()) {
|
switch (channel.metadata().bufferType()) {
|
||||||
case BYTE:
|
case BYTE:
|
||||||
// TODO: Use a direct buffer once buffer pooling is implemented.
|
return ctx.alloc().ioBuffer();
|
||||||
return Unpooled.buffer();
|
|
||||||
case MESSAGE:
|
case MESSAGE:
|
||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
default:
|
default:
|
||||||
@ -1457,6 +1432,13 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||||
|
if (buf instanceof UnsafeByteBuf) {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
|
public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
|
||||||
// NOOP
|
// NOOP
|
||||||
|
@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import io.netty.buffer.ChannelBuf;
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.AbstractChannel;
|
import io.netty.channel.AbstractChannel;
|
||||||
import io.netty.channel.ChannelConfig;
|
import io.netty.channel.ChannelConfig;
|
||||||
import io.netty.channel.ChannelException;
|
import io.netty.channel.ChannelException;
|
||||||
@ -211,6 +212,11 @@ public abstract class AbstractEmbeddedChannel extends AbstractChannel {
|
|||||||
return lastInboundMessageBuffer;
|
return lastInboundMessageBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
@ -235,6 +241,11 @@ public abstract class AbstractEmbeddedChannel extends AbstractChannel {
|
|||||||
return lastInboundByteBuffer;
|
return lastInboundByteBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||||
// No nothing
|
// No nothing
|
||||||
|
@ -17,8 +17,10 @@ package io.netty.channel.local;
|
|||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ChannelBuf;
|
||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.buffer.UnsafeByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerAdapter;
|
import io.netty.channel.ChannelHandlerAdapter;
|
||||||
@ -349,6 +351,16 @@ public class LocalTransportThreadModelTest {
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(
|
public void inboundBufferUpdated(
|
||||||
ChannelHandlerContext ctx) throws Exception {
|
ChannelHandlerContext ctx) throws Exception {
|
||||||
@ -393,7 +405,17 @@ public class LocalTransportThreadModelTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -440,7 +462,7 @@ public class LocalTransportThreadModelTest {
|
|||||||
out.add(msg);
|
out.add(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.unsafe().discardSomeReadBytes();
|
((UnsafeByteBuf) in).discardSomeReadBytes();
|
||||||
if (swallow) {
|
if (swallow) {
|
||||||
future.setSuccess();
|
future.setSuccess();
|
||||||
} else {
|
} else {
|
||||||
@ -472,7 +494,7 @@ public class LocalTransportThreadModelTest {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf newInboundBuffer(
|
public ByteBuf newInboundBuffer(
|
||||||
ChannelHandlerContext ctx) throws Exception {
|
ChannelHandlerContext ctx) throws Exception {
|
||||||
return Unpooled.buffer();
|
return ctx.alloc().buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -481,6 +503,16 @@ public class LocalTransportThreadModelTest {
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
((UnsafeByteBuf) buf).free();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(
|
public void inboundBufferUpdated(
|
||||||
ChannelHandlerContext ctx) throws Exception {
|
ChannelHandlerContext ctx) throws Exception {
|
||||||
@ -556,6 +588,16 @@ public class LocalTransportThreadModelTest {
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||||
Thread t = this.t;
|
Thread t = this.t;
|
||||||
@ -632,6 +674,16 @@ public class LocalTransportThreadModelTest {
|
|||||||
return Unpooled.messageBuffer();
|
return Unpooled.messageBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void freeOutboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) {
|
||||||
|
// Nothing to free
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
|
||||||
Thread t = this.t;
|
Thread t = this.t;
|
||||||
|
Loading…
Reference in New Issue
Block a user