Make retained derived buffers recyclable
Related: #4333 #4421 #5128 Motivation: slice(), duplicate() and readSlice() currently create a non-recyclable derived buffer instance. Under heavy load, an application that creates a lot of derived buffers can put the garbage collector under pressure. Modifications: - Add the following methods which creates a non-recyclable derived buffer - retainedSlice() - retainedDuplicate() - readRetainedSlice() - Add the new recyclable derived buffer implementations, which has its own reference count value - Add ByteBufHolder.retainedDuplicate() - Add ByteBufHolder.replace(ByteBuf) so that.. - a user can replace the content of the holder in a consistent way - copy/duplicate/retainedDuplicate() can delegate the holder construction to replace(ByteBuf) - Use retainedDuplicate() and retainedSlice() wherever possible - Miscellaneous: - Rename DuplicateByteBufTest to DuplicatedByteBufTest (missing 'D') - Make ReplayingDecoderByteBuf.reject() return an exception instead of throwing it so that its callers don't need to add dummy return statement Result: Derived buffers are now recycled when created via retainedSlice() and retainedDuplicate() and derived from a pooled buffer
This commit is contained in:
parent
68cd670eb9
commit
3a9f472161
@ -836,6 +836,13 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
||||
return slice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
ByteBuf slice = retainedSlice(readerIndex, length);
|
||||
readerIndex += length;
|
||||
return slice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
|
||||
checkReadableBytes(length);
|
||||
@ -1159,16 +1166,31 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
||||
return new DuplicatedAbstractByteBuf(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return duplicate().retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice() {
|
||||
return slice(readerIndex, readableBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return slice().retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return new SlicedAbstractByteBuf(this, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return slice(index, length).retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
return nioBuffer(readerIndex, readableBytes());
|
||||
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2016 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.Recycler.Handle;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Abstract base class for derived {@link ByteBuf} implementations.
|
||||
*/
|
||||
abstract class AbstractPooledDerivedByteBuf<T> extends AbstractReferenceCountedByteBuf {
|
||||
|
||||
private final Handle<AbstractPooledDerivedByteBuf<T>> recyclerHandle;
|
||||
private AbstractByteBuf buffer;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
AbstractPooledDerivedByteBuf(Handle<? extends AbstractPooledDerivedByteBuf<T>> recyclerHandle) {
|
||||
super(0);
|
||||
this.recyclerHandle = (Handle<AbstractPooledDerivedByteBuf<T>>) recyclerHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AbstractByteBuf unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
final <U extends AbstractPooledDerivedByteBuf<T>> U init(
|
||||
AbstractByteBuf buffer, int readerIndex, int writerIndex, int maxCapacity) {
|
||||
|
||||
buffer.retain();
|
||||
this.buffer = buffer;
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
maxCapacity(maxCapacity);
|
||||
setIndex(readerIndex, writerIndex);
|
||||
setRefCnt(1);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final U castThis = (U) this;
|
||||
success = true;
|
||||
return castThis;
|
||||
} finally {
|
||||
if (!success) {
|
||||
this.buffer = null;
|
||||
buffer.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void deallocate() {
|
||||
recyclerHandle.recycle(this);
|
||||
unwrap().release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBufAllocator alloc() {
|
||||
return unwrap().alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ByteOrder order() {
|
||||
return unwrap().order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return unwrap().isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDirect() {
|
||||
return unwrap().isDirect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasArray() {
|
||||
return unwrap().hasArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] array() {
|
||||
return unwrap().array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMemoryAddress() {
|
||||
return unwrap().hasMemoryAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int nioBufferCount() {
|
||||
return unwrap().nioBufferCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuffer internalNioBuffer(int index, int length) {
|
||||
return nioBuffer(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedDuplicate() {
|
||||
return PooledDuplicatedByteBuf.newInstance(this, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice() {
|
||||
final int index = readerIndex();
|
||||
return retainedSlice(index, writerIndex() - index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice(int index, int length) {
|
||||
return PooledSlicedByteBuf.newInstance(this, index, length, index);
|
||||
}
|
||||
}
|
@ -76,24 +76,48 @@ final class AdvancedLeakAwareByteBuf extends WrappedByteBuf {
|
||||
return new AdvancedLeakAwareByteBuf(super.slice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.retainedSlice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.slice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.retainedSlice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.duplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.retainedDuplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readSlice(int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.readSlice(length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.readRetainedSlice(length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf discardReadBytes() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
|
@ -58,24 +58,48 @@ final class AdvancedLeakAwareCompositeByteBuf extends WrappedCompositeByteBuf {
|
||||
return new AdvancedLeakAwareByteBuf(super.slice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.retainedSlice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.slice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.retainedSlice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.duplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.retainedDuplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readSlice(int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.readSlice(length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
return new AdvancedLeakAwareByteBuf(super.readRetainedSlice(length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeByteBuf discardReadBytes() {
|
||||
recordLeakNonRefCountingOperation(leak);
|
||||
|
@ -194,17 +194,31 @@ import java.nio.charset.UnsupportedCharsetException;
|
||||
*
|
||||
* <h3>Derived buffers</h3>
|
||||
*
|
||||
* You can create a view of an existing buffer by calling either
|
||||
* {@link #duplicate()}, {@link #slice()} or {@link #slice(int, int)}.
|
||||
* You can create a view of an existing buffer by calling one of the following methods:
|
||||
* <ul>
|
||||
* <li>{@link #duplicate()}</li>
|
||||
* <li>{@link #slice()}</li>
|
||||
* <li>{@link #slice(int, int)}</li>
|
||||
* <li>{@link #readSlice(int)}</li>
|
||||
* <li>{@link #retainedDuplicate()}</li>
|
||||
* <li>{@link #retainedSlice()}</li>
|
||||
* <li>{@link #retainedSlice(int, int)}</li>
|
||||
* <li>{@link #readRetainedSlice(int)}</li>
|
||||
* </ul>
|
||||
* A derived buffer will have an independent {@link #readerIndex() readerIndex},
|
||||
* {@link #writerIndex() writerIndex} and marker indexes, while it shares
|
||||
* other internal data representation, just like a NIO buffer does.
|
||||
* <p>
|
||||
* In case a completely fresh copy of an existing buffer is required, please
|
||||
* call {@link #copy()} method instead.
|
||||
* <p>
|
||||
* Also be aware that obtaining derived buffers will NOT call {@link #retain()} and so the
|
||||
* reference count will NOT be increased.
|
||||
*
|
||||
* <h4>Non-retained and retained derived buffers</h4>
|
||||
*
|
||||
* Note that the {@link #duplicate()}, {@link #slice()}, {@link #slice(int, int)} and {@link #readSlice(int)} does NOT
|
||||
* call {@link #retain()} on the returned derived buffer, and thus its reference count will NOT be increased. If you
|
||||
* need to create a derived buffer with increased reference count, consider using {@link #retainedDuplicate()},
|
||||
* {@link #retainedSlice()}, {@link #retainedSlice(int, int)} and {@link #readRetainedSlice(int)} which may return
|
||||
* a buffer implementation that produces less garbage.
|
||||
*
|
||||
* <h3>Conversion to existing JDK types</h3>
|
||||
*
|
||||
@ -1491,6 +1505,24 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
|
||||
*/
|
||||
public abstract ByteBuf readSlice(int length);
|
||||
|
||||
/**
|
||||
* Returns a new retained slice of this buffer's sub-region starting at the current
|
||||
* {@code readerIndex} and increases the {@code readerIndex} by the size
|
||||
* of the new slice (= {@code length}).
|
||||
* <p>
|
||||
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #readSlice(int)}.
|
||||
* This method behaves similarly to {@code readSlice(...).retain()} except that this method may return
|
||||
* a buffer implementation that produces less garbage.
|
||||
*
|
||||
* @param length the size of the new slice
|
||||
*
|
||||
* @return the newly created slice
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if {@code length} is greater than {@code this.readableBytes}
|
||||
*/
|
||||
public abstract ByteBuf readRetainedSlice(int length);
|
||||
|
||||
/**
|
||||
* Transfers this buffer's data to the specified destination starting at
|
||||
* the current {@code readerIndex} until the destination becomes
|
||||
@ -2060,6 +2092,20 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
|
||||
*/
|
||||
public abstract ByteBuf slice();
|
||||
|
||||
/**
|
||||
* Returns a retained slice of this buffer's readable bytes. Modifying the content
|
||||
* of the returned buffer or this buffer affects each other's content
|
||||
* while they maintain separate indexes and marks. This method is
|
||||
* identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
|
||||
* This method does not modify {@code readerIndex} or {@code writerIndex} of
|
||||
* this buffer.
|
||||
* <p>
|
||||
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice()}.
|
||||
* This method behaves similarly to {@code slice().retain()} except that this method may return
|
||||
* a buffer implementation that produces less garbage.
|
||||
*/
|
||||
public abstract ByteBuf retainedSlice();
|
||||
|
||||
/**
|
||||
* Returns a slice of this buffer's sub-region. Modifying the content of
|
||||
* the returned buffer or this buffer affects each other's content while
|
||||
@ -2072,6 +2118,19 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
|
||||
*/
|
||||
public abstract ByteBuf slice(int index, int length);
|
||||
|
||||
/**
|
||||
* Returns a retained slice of this buffer's sub-region. Modifying the content of
|
||||
* the returned buffer or this buffer affects each other's content while
|
||||
* they maintain separate indexes and marks.
|
||||
* This method does not modify {@code readerIndex} or {@code writerIndex} of
|
||||
* this buffer.
|
||||
* <p>
|
||||
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}.
|
||||
* This method behaves similarly to {@code slice(...).retain()} except that this method may return
|
||||
* a buffer implementation that produces less garbage.
|
||||
*/
|
||||
public abstract ByteBuf retainedSlice(int index, int length);
|
||||
|
||||
/**
|
||||
* Returns a buffer which shares the whole region of this buffer.
|
||||
* Modifying the content of the returned buffer or this buffer affects
|
||||
@ -2085,6 +2144,20 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
|
||||
*/
|
||||
public abstract ByteBuf duplicate();
|
||||
|
||||
/**
|
||||
* Returns a retained buffer which shares the whole region of this buffer.
|
||||
* Modifying the content of the returned buffer or this buffer affects
|
||||
* each other's content while they maintain separate indexes and marks.
|
||||
* This method is identical to {@code buf.slice(0, buf.capacity())}.
|
||||
* This method does not modify {@code readerIndex} or {@code writerIndex} of
|
||||
* this buffer.
|
||||
* <p>
|
||||
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}.
|
||||
* This method behaves similarly to {@code duplicate().retain()} except that this method may return
|
||||
* a buffer implementation that produces less garbage.
|
||||
*/
|
||||
public abstract ByteBuf retainedDuplicate();
|
||||
|
||||
/**
|
||||
* Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer. Note that {@link #nioBuffers()}
|
||||
* or {@link #nioBuffers(int, int)} might return a less number of {@link ByteBuffer}s.
|
||||
|
@ -28,15 +28,27 @@ public interface ByteBufHolder extends ReferenceCounted {
|
||||
ByteBuf content();
|
||||
|
||||
/**
|
||||
* Create a deep copy of this {@link ByteBufHolder}.
|
||||
* Creates a deep copy of this {@link ByteBufHolder}.
|
||||
*/
|
||||
ByteBufHolder copy();
|
||||
|
||||
/**
|
||||
* Duplicate the {@link ByteBufHolder}. Be aware that this will not automatically call {@link #retain()}.
|
||||
* Duplicates this {@link ByteBufHolder}. Be aware that this will not automatically call {@link #retain()}.
|
||||
*/
|
||||
ByteBufHolder duplicate();
|
||||
|
||||
/**
|
||||
* Duplicates this {@link ByteBufHolder}. This method returns a retained duplicate unlike {@link #duplicate()}.
|
||||
*
|
||||
* @see ByteBuf#retainedDuplicate()
|
||||
*/
|
||||
ByteBufHolder retainedDuplicate();
|
||||
|
||||
/**
|
||||
* Returns a new {@link ByteBufHolder} which contains the specified {@code content}.
|
||||
*/
|
||||
ByteBufHolder replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
ByteBufHolder retain();
|
||||
|
||||
|
@ -41,14 +41,46 @@ public class DefaultByteBufHolder implements ByteBufHolder {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This method calls {@code replace(content().copy())} by default.
|
||||
*/
|
||||
@Override
|
||||
public ByteBufHolder copy() {
|
||||
return new DefaultByteBufHolder(data.copy());
|
||||
return replace(data.copy());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This method calls {@code replace(content().duplicate())} by default.
|
||||
*/
|
||||
@Override
|
||||
public ByteBufHolder duplicate() {
|
||||
return new DefaultByteBufHolder(data.duplicate());
|
||||
return replace(data.duplicate());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This method calls {@code replace(content().retainedDuplicate())} by default.
|
||||
*/
|
||||
@Override
|
||||
public ByteBufHolder retainedDuplicate() {
|
||||
return replace(data.retainedDuplicate());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* Override this method to return a new instance of this object whose content is set to the specified
|
||||
* {@code content}. The default implementation of {@link #copy()}, {@link #duplicate()} and
|
||||
* {@link #retainedDuplicate()} invokes this method to create a copy.
|
||||
*/
|
||||
@Override
|
||||
public ByteBufHolder replace(ByteBuf content) {
|
||||
return new DefaultByteBufHolder(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,6 +39,10 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
||||
private final ByteBuf buffer;
|
||||
|
||||
public DuplicatedByteBuf(ByteBuf buffer) {
|
||||
this(buffer, buffer.readerIndex(), buffer.writerIndex());
|
||||
}
|
||||
|
||||
DuplicatedByteBuf(ByteBuf buffer, int readerIndex, int writerIndex) {
|
||||
super(buffer.maxCapacity());
|
||||
|
||||
if (buffer instanceof DuplicatedByteBuf) {
|
||||
@ -47,7 +51,7 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
setIndex(buffer.readerIndex(), buffer.writerIndex());
|
||||
setIndex(readerIndex, writerIndex);
|
||||
markReaderIndex();
|
||||
markWriterIndex();
|
||||
}
|
||||
|
@ -630,6 +630,11 @@ public final class EmptyByteBuf extends ByteBuf {
|
||||
return checkLength(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return checkLength(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(ByteBuf dst) {
|
||||
return checkLength(dst.writableBytes());
|
||||
@ -872,16 +877,31 @@ public final class EmptyByteBuf extends ByteBuf {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return checkIndex(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return checkIndex(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nioBufferCount() {
|
||||
return 1;
|
||||
|
@ -136,6 +136,22 @@ abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedDuplicate() {
|
||||
return PooledDuplicatedByteBuf.newInstance(this, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice() {
|
||||
final int index = readerIndex();
|
||||
return retainedSlice(index, writerIndex() - index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice(int index, int length) {
|
||||
return PooledSlicedByteBuf.newInstance(this, index, length, index);
|
||||
}
|
||||
|
||||
protected final ByteBuffer internalNioBuffer() {
|
||||
ByteBuffer tmpNioBuf = this.tmpNioBuf;
|
||||
if (tmpNioBuf == null) {
|
||||
|
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright 2016 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.ByteProcessor;
|
||||
import io.netty.util.Recycler;
|
||||
import io.netty.util.Recycler.Handle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
final class PooledDuplicatedByteBuf extends AbstractPooledDerivedByteBuf<PooledDuplicatedByteBuf> {
|
||||
|
||||
private static final Recycler<PooledDuplicatedByteBuf> RECYCLER = new Recycler<PooledDuplicatedByteBuf>() {
|
||||
@Override
|
||||
protected PooledDuplicatedByteBuf newObject(Handle<PooledDuplicatedByteBuf> handle) {
|
||||
return new PooledDuplicatedByteBuf(handle);
|
||||
}
|
||||
};
|
||||
|
||||
static PooledDuplicatedByteBuf newInstance(AbstractByteBuf buffer, int readerIndex, int writerIndex) {
|
||||
final PooledDuplicatedByteBuf duplicate = RECYCLER.get();
|
||||
duplicate.init(buffer, readerIndex, writerIndex, buffer.maxCapacity());
|
||||
duplicate.markReaderIndex();
|
||||
duplicate.markWriterIndex();
|
||||
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
private PooledDuplicatedByteBuf(Handle<PooledDuplicatedByteBuf> handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
return unwrap().capacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
unwrap().capacity(newCapacity);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arrayOffset() {
|
||||
return unwrap().arrayOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long memoryAddress() {
|
||||
return unwrap().memoryAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer(int index, int length) {
|
||||
return unwrap().nioBuffer(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers(int index, int length) {
|
||||
return unwrap().nioBuffers(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf copy(int index, int length) {
|
||||
return unwrap().copy(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
return unwrap().getByte(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte _getByte(int index) {
|
||||
return unwrap()._getByte(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
return unwrap().getShort(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShort(int index) {
|
||||
return unwrap()._getShort(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortLE(int index) {
|
||||
return unwrap().getShortLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShortLE(int index) {
|
||||
return unwrap()._getShortLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMedium(int index) {
|
||||
return unwrap().getUnsignedMedium(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMedium(int index) {
|
||||
return unwrap()._getUnsignedMedium(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMediumLE(int index) {
|
||||
return unwrap().getUnsignedMediumLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMediumLE(int index) {
|
||||
return unwrap()._getUnsignedMediumLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
return unwrap().getInt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getInt(int index) {
|
||||
return unwrap()._getInt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntLE(int index) {
|
||||
return unwrap().getIntLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getIntLE(int index) {
|
||||
return unwrap()._getIntLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
return unwrap().getLong(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLong(int index) {
|
||||
return unwrap()._getLong(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongLE(int index) {
|
||||
return unwrap().getLongLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLongLE(int index) {
|
||||
return unwrap()._getLongLE(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
unwrap().getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
unwrap().getBytes(index, dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
unwrap().getBytes(index, dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
unwrap().setByte(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setByte(int index, int value) {
|
||||
unwrap()._setByte(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
unwrap().setShort(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShort(int index, int value) {
|
||||
unwrap()._setShort(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShortLE(int index, int value) {
|
||||
unwrap().setShortLE(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShortLE(int index, int value) {
|
||||
unwrap()._setShortLE(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
unwrap().setMedium(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMedium(int index, int value) {
|
||||
unwrap()._setMedium(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMediumLE(int index, int value) {
|
||||
unwrap().setMediumLE(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMediumLE(int index, int value) {
|
||||
unwrap()._setMediumLE(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
unwrap().setInt(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setInt(int index, int value) {
|
||||
unwrap()._setInt(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setIntLE(int index, int value) {
|
||||
unwrap().setIntLE(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setIntLE(int index, int value) {
|
||||
unwrap()._setIntLE(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
unwrap().setLong(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLong(int index, long value) {
|
||||
unwrap()._setLong(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLongLE(int index, long value) {
|
||||
unwrap().setLongLE(index, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLongLE(int index, long value) {
|
||||
unwrap().setLongLE(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
unwrap().setBytes(index, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
unwrap().setBytes(index, src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
unwrap().setBytes(index, src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
unwrap().getBytes(index, out, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
return unwrap().getBytes(index, out, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, FileChannel out, long position, int length)
|
||||
throws IOException {
|
||||
return unwrap().getBytes(index, out, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
return unwrap().setBytes(index, in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
return unwrap().setBytes(index, in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, FileChannel in, long position, int length)
|
||||
throws IOException {
|
||||
return unwrap().setBytes(index, in, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int index, int length, ByteProcessor processor) {
|
||||
return unwrap().forEachByte(index, length, processor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor processor) {
|
||||
return unwrap().forEachByteDesc(index, length, processor);
|
||||
}
|
||||
}
|
418
buffer/src/main/java/io/netty/buffer/PooledSlicedByteBuf.java
Normal file
418
buffer/src/main/java/io/netty/buffer/PooledSlicedByteBuf.java
Normal file
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Copyright 2016 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.ByteProcessor;
|
||||
import io.netty.util.Recycler;
|
||||
import io.netty.util.Recycler.Handle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
import static io.netty.util.internal.MathUtil.isOutOfBounds;
|
||||
|
||||
final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf<PooledSlicedByteBuf> {
|
||||
|
||||
private static final Recycler<PooledSlicedByteBuf> RECYCLER = new Recycler<PooledSlicedByteBuf>() {
|
||||
@Override
|
||||
protected PooledSlicedByteBuf newObject(Handle<PooledSlicedByteBuf> handle) {
|
||||
return new PooledSlicedByteBuf(handle);
|
||||
}
|
||||
};
|
||||
|
||||
static PooledSlicedByteBuf newInstance(AbstractByteBuf buffer, int index, int length, int adjustment) {
|
||||
if (isOutOfBounds(index, length, buffer.capacity())) {
|
||||
throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')');
|
||||
}
|
||||
|
||||
final PooledSlicedByteBuf slice = RECYCLER.get();
|
||||
slice.init(buffer, 0, length, length);
|
||||
slice.discardMarks();
|
||||
slice.adjustment = adjustment;
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
private int adjustment;
|
||||
|
||||
private PooledSlicedByteBuf(Handle<PooledSlicedByteBuf> handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
return maxCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
return reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arrayOffset() {
|
||||
return idx(unwrap().arrayOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long memoryAddress() {
|
||||
return unwrap().memoryAddress() + adjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().nioBuffer(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().nioBuffers(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf copy(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().copy(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
checkIndex0(index, 1);
|
||||
return unwrap().getByte(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte _getByte(int index) {
|
||||
return unwrap()._getByte(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
checkIndex0(index, 2);
|
||||
return unwrap().getShort(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShort(int index) {
|
||||
return unwrap()._getShort(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortLE(int index) {
|
||||
checkIndex0(index, 2);
|
||||
return unwrap().getShortLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShortLE(int index) {
|
||||
return unwrap()._getShortLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMedium(int index) {
|
||||
checkIndex0(index, 3);
|
||||
return unwrap().getUnsignedMedium(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMedium(int index) {
|
||||
return unwrap()._getUnsignedMedium(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMediumLE(int index) {
|
||||
checkIndex0(index, 3);
|
||||
return unwrap().getUnsignedMediumLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMediumLE(int index) {
|
||||
return unwrap()._getUnsignedMediumLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
checkIndex0(index, 4);
|
||||
return unwrap().getInt(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getInt(int index) {
|
||||
return unwrap()._getInt(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntLE(int index) {
|
||||
checkIndex0(index, 4);
|
||||
return unwrap().getIntLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getIntLE(int index) {
|
||||
return unwrap()._getIntLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
checkIndex0(index, 8);
|
||||
return unwrap().getLong(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLong(int index) {
|
||||
return unwrap()._getLong(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongLE(int index) {
|
||||
checkIndex0(index, 8);
|
||||
return unwrap().getLongLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLongLE(int index) {
|
||||
return unwrap()._getLongLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
checkIndex0(index, dst.remaining());
|
||||
unwrap().getBytes(idx(index), dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
checkIndex0(index, 1);
|
||||
unwrap().setByte(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setByte(int index, int value) {
|
||||
unwrap()._setByte(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
checkIndex0(index, 2);
|
||||
unwrap().setShort(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShort(int index, int value) {
|
||||
unwrap()._setShort(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShortLE(int index, int value) {
|
||||
checkIndex0(index, 2);
|
||||
unwrap().setShortLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShortLE(int index, int value) {
|
||||
unwrap()._setShortLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
checkIndex0(index, 3);
|
||||
unwrap().setMedium(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMedium(int index, int value) {
|
||||
unwrap()._setMedium(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMediumLE(int index, int value) {
|
||||
checkIndex0(index, 3);
|
||||
unwrap().setMediumLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMediumLE(int index, int value) {
|
||||
unwrap()._setMediumLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
checkIndex0(index, 4);
|
||||
unwrap().setInt(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setInt(int index, int value) {
|
||||
unwrap()._setInt(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setIntLE(int index, int value) {
|
||||
checkIndex0(index, 4);
|
||||
unwrap().setIntLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setIntLE(int index, int value) {
|
||||
unwrap()._setIntLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
checkIndex0(index, 8);
|
||||
unwrap().setLong(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLong(int index, long value) {
|
||||
unwrap()._setLong(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLongLE(int index, long value) {
|
||||
checkIndex0(index, 8);
|
||||
unwrap().setLongLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLongLE(int index, long value) {
|
||||
unwrap().setLongLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().setBytes(idx(index), src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().setBytes(idx(index), src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
checkIndex0(index, src.remaining());
|
||||
unwrap().setBytes(idx(index), src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length)
|
||||
throws IOException {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), out, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, GatheringByteChannel out, int length)
|
||||
throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().getBytes(idx(index), out, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, FileChannel out, long position, int length)
|
||||
throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().getBytes(idx(index), out, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length)
|
||||
throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length)
|
||||
throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, FileChannel in, long position, int length)
|
||||
throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int index, int length, ByteProcessor processor) {
|
||||
checkIndex0(index, length);
|
||||
int ret = unwrap().forEachByte(idx(index), length, processor);
|
||||
if (ret < adjustment) {
|
||||
return -1;
|
||||
}
|
||||
return ret - adjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor processor) {
|
||||
checkIndex0(index, length);
|
||||
int ret = unwrap().forEachByteDesc(idx(index), length, processor);
|
||||
if (ret < adjustment) {
|
||||
return -1;
|
||||
}
|
||||
return ret - adjustment;
|
||||
}
|
||||
|
||||
private int idx(int index) {
|
||||
return index + adjustment;
|
||||
}
|
||||
|
||||
private static ByteBuf reject() {
|
||||
throw new UnsupportedOperationException("sliced buffer");
|
||||
}
|
||||
}
|
@ -72,18 +72,38 @@ final class SimpleLeakAwareByteBuf extends WrappedByteBuf {
|
||||
return new SimpleLeakAwareByteBuf(super.slice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return new SimpleLeakAwareByteBuf(super.retainedSlice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.slice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.retainedSlice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return new SimpleLeakAwareByteBuf(super.duplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return new SimpleLeakAwareByteBuf(super.retainedDuplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readSlice(int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.readSlice(length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.readRetainedSlice(length), leak);
|
||||
}
|
||||
}
|
||||
|
@ -62,18 +62,38 @@ final class SimpleLeakAwareCompositeByteBuf extends WrappedCompositeByteBuf {
|
||||
return new SimpleLeakAwareByteBuf(super.slice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return new SimpleLeakAwareByteBuf(super.retainedSlice(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.slice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.retainedSlice(index, length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return new SimpleLeakAwareByteBuf(super.duplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return new SimpleLeakAwareByteBuf(super.retainedDuplicate(), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readSlice(int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.readSlice(length), leak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return new SimpleLeakAwareByteBuf(super.readRetainedSlice(length), leak);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
|
||||
writerIndex(length);
|
||||
}
|
||||
|
||||
final int adjustment() {
|
||||
return adjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
return buffer;
|
||||
|
@ -631,6 +631,11 @@ public class SwappedByteBuf extends ByteBuf {
|
||||
return buf.readSlice(length).order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return buf.readRetainedSlice(length).order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(ByteBuf dst) {
|
||||
buf.readBytes(dst);
|
||||
@ -889,16 +894,31 @@ public class SwappedByteBuf extends ByteBuf {
|
||||
return buf.slice().order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return buf.slice().order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return buf.slice(index, length).order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return buf.slice(index, length).order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return buf.duplicate().order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return buf.retainedDuplicate().order(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nioBufferCount() {
|
||||
return buf.nioBufferCount();
|
||||
|
@ -55,21 +55,41 @@ final class UnreleasableByteBuf extends WrappedByteBuf {
|
||||
return new UnreleasableByteBuf(buf.readSlice(length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return new UnreleasableByteBuf(buf.readRetainedSlice(length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice() {
|
||||
return new UnreleasableByteBuf(buf.slice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return new UnreleasableByteBuf(buf.retainedSlice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return new UnreleasableByteBuf(buf.slice(index, length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return new UnreleasableByteBuf(buf.retainedSlice(index, length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return new UnreleasableByteBuf(buf.duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return new UnreleasableByteBuf(buf.retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retain(int increment) {
|
||||
return this;
|
||||
|
@ -621,6 +621,11 @@ class WrappedByteBuf extends ByteBuf {
|
||||
return buf.readSlice(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return buf.readRetainedSlice(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readBytes(ByteBuf dst) {
|
||||
buf.readBytes(dst);
|
||||
@ -879,16 +884,31 @@ class WrappedByteBuf extends ByteBuf {
|
||||
return buf.slice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return buf.retainedSlice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return buf.slice(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return buf.retainedSlice(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return buf.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return buf.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nioBufferCount() {
|
||||
return buf.nioBufferCount();
|
||||
|
@ -332,11 +332,21 @@ class WrappedCompositeByteBuf extends CompositeByteBuf {
|
||||
return wrapped.slice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice() {
|
||||
return wrapped.retainedSlice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return wrapped.slice(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return wrapped.retainedSlice(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer() {
|
||||
return wrapped.nioBuffer();
|
||||
@ -417,11 +427,21 @@ class WrappedCompositeByteBuf extends CompositeByteBuf {
|
||||
return wrapped.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return wrapped.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readSlice(int length) {
|
||||
return wrapped.readSlice(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf readRetainedSlice(int length) {
|
||||
return wrapped.readRetainedSlice(length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readBytes(GatheringByteChannel out, int length) throws IOException {
|
||||
return wrapped.readBytes(out, length);
|
||||
|
@ -22,7 +22,7 @@ import static org.junit.Assert.assertEquals;
|
||||
/**
|
||||
* Tests duplicated channel buffers
|
||||
*/
|
||||
public class DuplicateByteBufTest extends AbstractByteBufTest {
|
||||
public class DuplicatedByteBufTest extends AbstractByteBufTest {
|
||||
|
||||
@Override
|
||||
protected ByteBuf newBuffer(int length) {
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 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 static org.junit.Assert.assertEquals;
|
||||
|
||||
public class RetainedDuplicatedByteBufTest extends DuplicatedByteBufTest {
|
||||
@Override
|
||||
protected ByteBuf newBuffer(int length) {
|
||||
ByteBuf wrapped = Unpooled.buffer(length);
|
||||
ByteBuf buffer = wrapped.retainedDuplicate();
|
||||
wrapped.release();
|
||||
|
||||
assertEquals(wrapped.writerIndex(), buffer.writerIndex());
|
||||
assertEquals(wrapped.readerIndex(), buffer.readerIndex());
|
||||
return buffer;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2016 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.ThreadLocalRandom;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class RetainedSlicedByteBufTest extends SlicedByteBufTest {
|
||||
@Override
|
||||
protected ByteBuf newBuffer(int length) {
|
||||
ByteBuf wrapped = Unpooled.wrappedBuffer(new byte[length * 2]);
|
||||
ByteBuf buffer = wrapped.retainedSlice(ThreadLocalRandom.current().nextInt(length - 1) + 1, length);
|
||||
wrapped.release();
|
||||
|
||||
assertEquals(0, buffer.readerIndex());
|
||||
assertEquals(length, buffer.writerIndex());
|
||||
return buffer;
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -27,12 +28,11 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class SlicedByteBufTest extends AbstractByteBufTest {
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
protected ByteBuf newBuffer(int length) {
|
||||
ByteBuf buffer = Unpooled.wrappedBuffer(
|
||||
new byte[length * 2], random.nextInt(length - 1) + 1, length);
|
||||
new byte[length * 2], ThreadLocalRandom.current().nextInt(length - 1) + 1, length);
|
||||
assertEquals(0, buffer.readerIndex());
|
||||
assertEquals(length, buffer.writerIndex());
|
||||
return buffer;
|
||||
}
|
||||
|
@ -69,12 +69,22 @@ public class DefaultDnsRawRecord extends AbstractDnsRecord implements DnsRawReco
|
||||
|
||||
@Override
|
||||
public DnsRawRecord copy() {
|
||||
return new DefaultDnsRawRecord(name(), type(), dnsClass(), timeToLive(), content().copy());
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsRawRecord duplicate() {
|
||||
return new DefaultDnsRawRecord(name(), type(), dnsClass(), timeToLive(), content().duplicate());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsRawRecord retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsRawRecord replace(ByteBuf content) {
|
||||
return new DefaultDnsRawRecord(name(), type(), dnsClass(), timeToLive(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,7 +95,7 @@ public class DefaultDnsRecordDecoder implements DnsRecordDecoder {
|
||||
return new DefaultDnsPtrRecord(name, dnsClass, timeToLive, decodeName(in));
|
||||
}
|
||||
return new DefaultDnsRawRecord(
|
||||
name, type, dnsClass, timeToLive, in.duplicate().setIndex(offset, offset + length).retain());
|
||||
name, type, dnsClass, timeToLive, in.retainedDuplicate().setIndex(offset, offset + length));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
@ -29,6 +30,12 @@ public interface DnsRawRecord extends DnsRecord, ByteBufHolder {
|
||||
@Override
|
||||
DnsRawRecord duplicate();
|
||||
|
||||
@Override
|
||||
DnsRawRecord retainedDuplicate();
|
||||
|
||||
@Override
|
||||
DnsRawRecord replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
DnsRawRecord retain();
|
||||
|
||||
|
@ -27,6 +27,7 @@ final class ComposedLastHttpContent implements LastHttpContent {
|
||||
ComposedLastHttpContent(HttpHeaders trailingHeaders) {
|
||||
this.trailingHeaders = trailingHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders trailingHeaders() {
|
||||
return trailingHeaders;
|
||||
@ -39,6 +40,23 @@ final class ComposedLastHttpContent implements LastHttpContent {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent duplicate() {
|
||||
return copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent retainedDuplicate() {
|
||||
return copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent replace(ByteBuf content) {
|
||||
final LastHttpContent dup = new DefaultLastHttpContent(content);
|
||||
dup.trailingHeaders().setAll(trailingHeaders());
|
||||
return dup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent retain(int increment) {
|
||||
return this;
|
||||
@ -59,11 +77,6 @@ final class ComposedLastHttpContent implements LastHttpContent {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent duplicate() {
|
||||
return copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf content() {
|
||||
return Unpooled.EMPTY_BUFFER;
|
||||
|
@ -125,44 +125,24 @@ public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHt
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy this object
|
||||
*
|
||||
* @param copyContent
|
||||
* <ul>
|
||||
* <li>{@code true} if this object's {@link #content()} should be used to copy.</li>
|
||||
* <li>{@code false} if {@code newContent} should be used instead.</li>
|
||||
* </ul>
|
||||
* @param newContent
|
||||
* <ul>
|
||||
* <li>if {@code copyContent} is false then this will be used in the copy's content.</li>
|
||||
* <li>if {@code null} then a default buffer of 0 size will be selected</li>
|
||||
* </ul>
|
||||
* @return A copy of this object
|
||||
*/
|
||||
private FullHttpRequest copy(boolean copyContent, ByteBuf newContent) {
|
||||
return new DefaultFullHttpRequest(
|
||||
protocolVersion(), method(), uri(),
|
||||
copyContent ? content().copy() :
|
||||
newContent == null ? Unpooled.buffer(0) : newContent,
|
||||
headers(),
|
||||
trailingHeaders());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest copy(ByteBuf newContent) {
|
||||
return copy(false, newContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest copy() {
|
||||
return copy(true, null);
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest duplicate() {
|
||||
return new DefaultFullHttpRequest(
|
||||
protocolVersion(), method(), uri(), content().duplicate(), headers(), trailingHeaders());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest replace(ByteBuf content) {
|
||||
return new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content, headers(), trailingHeaders());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -132,44 +132,24 @@ public class DefaultFullHttpResponse extends DefaultHttpResponse implements Full
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy this object
|
||||
*
|
||||
* @param copyContent
|
||||
* <ul>
|
||||
* <li>{@code true} if this object's {@link #content()} should be used to copy.</li>
|
||||
* <li>{@code false} if {@code newContent} should be used instead.</li>
|
||||
* </ul>
|
||||
* @param newContent
|
||||
* <ul>
|
||||
* <li>if {@code copyContent} is false then this will be used in the copy's content.</li>
|
||||
* <li>if {@code null} then a default buffer of 0 size will be selected</li>
|
||||
* </ul>
|
||||
* @return A copy of this object
|
||||
*/
|
||||
private FullHttpResponse copy(boolean copyContent, ByteBuf newContent) {
|
||||
return new DefaultFullHttpResponse(
|
||||
protocolVersion(), status(),
|
||||
copyContent ? content().copy() :
|
||||
newContent == null ? Unpooled.buffer(0) : newContent,
|
||||
headers(),
|
||||
trailingHeaders());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse copy(ByteBuf newContent) {
|
||||
return copy(false, newContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse copy() {
|
||||
return copy(true, null);
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse duplicate() {
|
||||
return new DefaultFullHttpResponse(protocolVersion(), status(),
|
||||
content().duplicate(), headers(), trailingHeaders());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse replace(ByteBuf content) {
|
||||
return new DefaultFullHttpResponse(protocolVersion(), status(), content, headers(), trailingHeaders());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,12 +42,22 @@ public class DefaultHttpContent extends DefaultHttpObject implements HttpContent
|
||||
|
||||
@Override
|
||||
public HttpContent copy() {
|
||||
return new DefaultHttpContent(content.copy());
|
||||
return replace(content.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpContent duplicate() {
|
||||
return new DefaultHttpContent(content.duplicate());
|
||||
return replace(content.duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpContent retainedDuplicate() {
|
||||
return replace(content.retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpContent replace(ByteBuf content) {
|
||||
return new DefaultHttpContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,16 +45,24 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
|
||||
|
||||
@Override
|
||||
public LastHttpContent copy() {
|
||||
DefaultLastHttpContent copy = new DefaultLastHttpContent(content().copy(), validateHeaders);
|
||||
copy.trailingHeaders().set(trailingHeaders());
|
||||
return copy;
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent duplicate() {
|
||||
DefaultLastHttpContent copy = new DefaultLastHttpContent(content().duplicate(), validateHeaders);
|
||||
copy.trailingHeaders().set(trailingHeaders());
|
||||
return copy;
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent replace(ByteBuf content) {
|
||||
final DefaultLastHttpContent dup = new DefaultLastHttpContent(content, validateHeaders);
|
||||
dup.trailingHeaders().set(trailingHeaders());
|
||||
return dup;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,19 +22,18 @@ import io.netty.buffer.ByteBuf;
|
||||
* message. So it represent a <i>complete</i> http message.
|
||||
*/
|
||||
public interface FullHttpMessage extends HttpMessage, LastHttpContent {
|
||||
/**
|
||||
* Create a copy of this {@link FullHttpMessage} with alternative content.
|
||||
*
|
||||
* @param newContent The buffer to use instead of this {@link FullHttpMessage}'s content in the copy operation.
|
||||
* <p>
|
||||
* NOTE: retain will NOT be called on this buffer. {@code null} results in an empty default choice buffer.
|
||||
* @return The result of the copy operation
|
||||
*/
|
||||
FullHttpMessage copy(ByteBuf newContent);
|
||||
|
||||
@Override
|
||||
FullHttpMessage copy();
|
||||
|
||||
@Override
|
||||
FullHttpMessage duplicate();
|
||||
|
||||
@Override
|
||||
FullHttpMessage retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FullHttpMessage replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FullHttpMessage retain(int increment);
|
||||
|
||||
@ -46,7 +45,4 @@ public interface FullHttpMessage extends HttpMessage, LastHttpContent {
|
||||
|
||||
@Override
|
||||
FullHttpMessage touch(Object hint);
|
||||
|
||||
@Override
|
||||
FullHttpMessage duplicate();
|
||||
}
|
||||
|
@ -23,10 +23,16 @@ import io.netty.buffer.ByteBuf;
|
||||
*/
|
||||
public interface FullHttpRequest extends HttpRequest, FullHttpMessage {
|
||||
@Override
|
||||
FullHttpRequest copy(ByteBuf newContent);
|
||||
FullHttpRequest copy();
|
||||
|
||||
@Override
|
||||
FullHttpRequest copy();
|
||||
FullHttpRequest duplicate();
|
||||
|
||||
@Override
|
||||
FullHttpRequest retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FullHttpRequest replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FullHttpRequest retain(int increment);
|
||||
@ -40,9 +46,6 @@ public interface FullHttpRequest extends HttpRequest, FullHttpMessage {
|
||||
@Override
|
||||
FullHttpRequest touch(Object hint);
|
||||
|
||||
@Override
|
||||
FullHttpRequest duplicate();
|
||||
|
||||
@Override
|
||||
FullHttpRequest setProtocolVersion(HttpVersion version);
|
||||
|
||||
|
@ -23,10 +23,16 @@ import io.netty.buffer.ByteBuf;
|
||||
*/
|
||||
public interface FullHttpResponse extends HttpResponse, FullHttpMessage {
|
||||
@Override
|
||||
FullHttpResponse copy(ByteBuf newContent);
|
||||
FullHttpResponse copy();
|
||||
|
||||
@Override
|
||||
FullHttpResponse copy();
|
||||
FullHttpResponse duplicate();
|
||||
|
||||
@Override
|
||||
FullHttpResponse retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FullHttpResponse replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FullHttpResponse retain(int increment);
|
||||
@ -40,9 +46,6 @@ public interface FullHttpResponse extends HttpResponse, FullHttpMessage {
|
||||
@Override
|
||||
FullHttpResponse touch(Object hint);
|
||||
|
||||
@Override
|
||||
FullHttpResponse duplicate();
|
||||
|
||||
@Override
|
||||
FullHttpResponse setProtocolVersion(HttpVersion version);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
@ -33,6 +34,12 @@ public interface HttpContent extends HttpObject, ByteBufHolder {
|
||||
@Override
|
||||
HttpContent duplicate();
|
||||
|
||||
@Override
|
||||
HttpContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
HttpContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
HttpContent retain();
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.codec.http;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
@ -121,11 +120,11 @@ public class HttpObjectAggregator
|
||||
protected Object newContinueResponse(HttpMessage start, int maxContentLength, ChannelPipeline pipeline) {
|
||||
if (HttpUtil.is100ContinueExpected(start)) {
|
||||
if (getContentLength(start, -1L) <= maxContentLength) {
|
||||
return CONTINUE.duplicate().retain();
|
||||
return CONTINUE.retainedDuplicate();
|
||||
}
|
||||
|
||||
pipeline.fireUserEventTriggered(HttpExpectationFailedEvent.INSTANCE);
|
||||
return EXPECTATION_FAILED.duplicate().retain();
|
||||
return EXPECTATION_FAILED.retainedDuplicate();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -176,7 +175,7 @@ public class HttpObjectAggregator
|
||||
// See rfc2616 14.13 Content-Length
|
||||
if (!HttpUtil.isContentLengthSet(aggregated)) {
|
||||
aggregated.headers().set(
|
||||
HttpHeaderNames.CONTENT_LENGTH,
|
||||
CONTENT_LENGTH,
|
||||
String.valueOf(aggregated.content().readableBytes()));
|
||||
}
|
||||
}
|
||||
@ -185,7 +184,7 @@ public class HttpObjectAggregator
|
||||
protected void handleOversizedMessage(final ChannelHandlerContext ctx, HttpMessage oversized) throws Exception {
|
||||
if (oversized instanceof HttpRequest) {
|
||||
// send back a 413 and close the connection
|
||||
ChannelFuture future = ctx.writeAndFlush(TOO_LARGE.duplicate().retain()).addListener(
|
||||
ChannelFuture future = ctx.writeAndFlush(TOO_LARGE.retainedDuplicate()).addListener(
|
||||
new ChannelFutureListener() {
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
@ -217,7 +216,7 @@ public class HttpObjectAggregator
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class AggregatedFullHttpMessage implements ByteBufHolder, FullHttpMessage {
|
||||
private abstract static class AggregatedFullHttpMessage implements FullHttpMessage {
|
||||
protected final HttpMessage message;
|
||||
private final ByteBuf content;
|
||||
private HttpHeaders trailingHeaders;
|
||||
@ -327,6 +326,9 @@ public class HttpObjectAggregator
|
||||
|
||||
@Override
|
||||
public abstract FullHttpMessage duplicate();
|
||||
|
||||
@Override
|
||||
public abstract FullHttpMessage retainedDuplicate();
|
||||
}
|
||||
|
||||
private static final class AggregatedFullHttpRequest extends AggregatedFullHttpMessage implements FullHttpRequest {
|
||||
@ -335,48 +337,27 @@ public class HttpObjectAggregator
|
||||
super(request, content, trailingHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy this object
|
||||
*
|
||||
* @param copyContent
|
||||
* <ul>
|
||||
* <li>{@code true} if this object's {@link #content()} should be used to copy.</li>
|
||||
* <li>{@code false} if {@code newContent} should be used instead.</li>
|
||||
* </ul>
|
||||
* @param newContent
|
||||
* <ul>
|
||||
* <li>if {@code copyContent} is false then this will be used in the copy's content.</li>
|
||||
* <li>if {@code null} then a default buffer of 0 size will be selected</li>
|
||||
* </ul>
|
||||
* @return A copy of this object
|
||||
*/
|
||||
private FullHttpRequest copy(boolean copyContent, ByteBuf newContent) {
|
||||
DefaultFullHttpRequest copy = new DefaultFullHttpRequest(
|
||||
protocolVersion(), method(), uri(),
|
||||
copyContent ? content().copy() :
|
||||
newContent == null ? Unpooled.buffer(0) : newContent);
|
||||
copy.headers().set(headers());
|
||||
copy.trailingHeaders().set(trailingHeaders());
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest copy(ByteBuf newContent) {
|
||||
return copy(false, newContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest copy() {
|
||||
return copy(true, null);
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest duplicate() {
|
||||
DefaultFullHttpRequest duplicate = new DefaultFullHttpRequest(
|
||||
getProtocolVersion(), getMethod(), getUri(), content().duplicate());
|
||||
duplicate.headers().set(headers());
|
||||
duplicate.trailingHeaders().set(trailingHeaders());
|
||||
return duplicate;
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest replace(ByteBuf content) {
|
||||
DefaultFullHttpRequest dup = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content);
|
||||
dup.headers().set(headers());
|
||||
dup.trailingHeaders().set(trailingHeaders());
|
||||
return dup;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -454,48 +435,27 @@ public class HttpObjectAggregator
|
||||
super(message, content, trailingHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy this object
|
||||
*
|
||||
* @param copyContent
|
||||
* <ul>
|
||||
* <li>{@code true} if this object's {@link #content()} should be used to copy.</li>
|
||||
* <li>{@code false} if {@code newContent} should be used instead.</li>
|
||||
* </ul>
|
||||
* @param newContent
|
||||
* <ul>
|
||||
* <li>if {@code copyContent} is false then this will be used in the copy's content.</li>
|
||||
* <li>if {@code null} then a default buffer of 0 size will be selected</li>
|
||||
* </ul>
|
||||
* @return A copy of this object
|
||||
*/
|
||||
private FullHttpResponse copy(boolean copyContent, ByteBuf newContent) {
|
||||
DefaultFullHttpResponse copy = new DefaultFullHttpResponse(
|
||||
protocolVersion(), status(),
|
||||
copyContent ? content().copy() :
|
||||
newContent == null ? Unpooled.buffer(0) : newContent);
|
||||
copy.headers().set(headers());
|
||||
copy.trailingHeaders().set(trailingHeaders());
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse copy(ByteBuf newContent) {
|
||||
return copy(false, newContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse copy() {
|
||||
return copy(true, null);
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse duplicate() {
|
||||
DefaultFullHttpResponse duplicate = new DefaultFullHttpResponse(getProtocolVersion(), getStatus(),
|
||||
content().duplicate());
|
||||
duplicate.headers().set(headers());
|
||||
duplicate.trailingHeaders().set(trailingHeaders());
|
||||
return duplicate;
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpResponse replace(ByteBuf content) {
|
||||
DefaultFullHttpResponse dup = new DefaultFullHttpResponse(getProtocolVersion(), getStatus(), content);
|
||||
dup.headers().set(headers());
|
||||
dup.trailingHeaders().set(trailingHeaders());
|
||||
return dup;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -279,7 +279,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
// Keep reading data as a chunk until the end of connection is reached.
|
||||
int toRead = Math.min(buffer.readableBytes(), maxChunkSize);
|
||||
if (toRead > 0) {
|
||||
ByteBuf content = buffer.readSlice(toRead).retain();
|
||||
ByteBuf content = buffer.readRetainedSlice(toRead);
|
||||
out.add(new DefaultHttpContent(content));
|
||||
}
|
||||
return;
|
||||
@ -301,7 +301,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
if (toRead > chunkSize) {
|
||||
toRead = (int) chunkSize;
|
||||
}
|
||||
ByteBuf content = buffer.readSlice(toRead).retain();
|
||||
ByteBuf content = buffer.readRetainedSlice(toRead);
|
||||
chunkSize -= toRead;
|
||||
|
||||
if (chunkSize == 0) {
|
||||
@ -341,7 +341,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
if (toRead == 0) {
|
||||
return;
|
||||
}
|
||||
HttpContent chunk = new DefaultHttpContent(buffer.readSlice(toRead).retain());
|
||||
HttpContent chunk = new DefaultHttpContent(buffer.readRetainedSlice(toRead));
|
||||
chunkSize -= toRead;
|
||||
|
||||
out.add(chunk);
|
||||
|
@ -44,6 +44,16 @@ public interface LastHttpContent extends HttpContent {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent replace(ByteBuf content) {
|
||||
return new DefaultLastHttpContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastHttpContent retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders trailingHeaders() {
|
||||
return EmptyHttpHeaders.INSTANCE;
|
||||
@ -111,6 +121,15 @@ public interface LastHttpContent extends HttpContent {
|
||||
@Override
|
||||
LastHttpContent copy();
|
||||
|
||||
@Override
|
||||
LastHttpContent duplicate();
|
||||
|
||||
@Override
|
||||
LastHttpContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
LastHttpContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
LastHttpContent retain(int increment);
|
||||
|
||||
@ -122,7 +141,4 @@ public interface LastHttpContent extends HttpContent {
|
||||
|
||||
@Override
|
||||
LastHttpContent touch(Object hint);
|
||||
|
||||
@Override
|
||||
LastHttpContent duplicate();
|
||||
}
|
||||
|
@ -28,7 +28,10 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
||||
import static io.netty.buffer.Unpooled.buffer;
|
||||
import static io.netty.buffer.Unpooled.compositeBuffer;
|
||||
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
||||
|
||||
/**
|
||||
* Abstract Memory HttpData implementation
|
||||
@ -209,7 +212,7 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData {
|
||||
if (sizeLeft < length) {
|
||||
sliceLength = sizeLeft;
|
||||
}
|
||||
ByteBuf chunk = byteBuf.slice(chunkPosition, sliceLength).retain();
|
||||
ByteBuf chunk = byteBuf.retainedSlice(chunkPosition, sliceLength);
|
||||
chunkPosition += sliceLength;
|
||||
return chunk;
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@ -37,6 +39,12 @@ public interface Attribute extends HttpData {
|
||||
@Override
|
||||
Attribute duplicate();
|
||||
|
||||
@Override
|
||||
Attribute retainedDuplicate();
|
||||
|
||||
@Override
|
||||
Attribute replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
Attribute retain();
|
||||
|
||||
|
@ -22,7 +22,7 @@ import io.netty.handler.codec.http.HttpConstants;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
||||
|
||||
/**
|
||||
* Disk implementation of Attributes
|
||||
@ -162,27 +162,43 @@ public class DiskAttribute extends AbstractDiskHttpData implements Attribute {
|
||||
|
||||
@Override
|
||||
public Attribute copy() {
|
||||
DiskAttribute attr = new DiskAttribute(getName());
|
||||
attr.setCharset(getCharset());
|
||||
ByteBuf content = content();
|
||||
if (content != null) {
|
||||
try {
|
||||
attr.setContent(content.copy());
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
return attr;
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.copy() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute duplicate() {
|
||||
DiskAttribute attr = new DiskAttribute(getName());
|
||||
attr.setCharset(getCharset());
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.duplicate() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute retainedDuplicate() {
|
||||
ByteBuf content = content();
|
||||
if (content != null) {
|
||||
content = content.retainedDuplicate();
|
||||
boolean success = false;
|
||||
try {
|
||||
attr.setContent(content.duplicate());
|
||||
Attribute duplicate = replace(content);
|
||||
success = true;
|
||||
return duplicate;
|
||||
} finally {
|
||||
if (!success) {
|
||||
content.release();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return replace(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute replace(ByteBuf content) {
|
||||
DiskAttribute attr = new DiskAttribute(getName());
|
||||
attr.setCharset(getCharset());
|
||||
if (content != null) {
|
||||
try {
|
||||
attr.setContent(content);
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
|
@ -173,27 +173,43 @@ public class DiskFileUpload extends AbstractDiskHttpData implements FileUpload {
|
||||
|
||||
@Override
|
||||
public FileUpload copy() {
|
||||
DiskFileUpload upload = new DiskFileUpload(getName(),
|
||||
getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size);
|
||||
ByteBuf buf = content();
|
||||
if (buf != null) {
|
||||
try {
|
||||
upload.setContent(buf.copy());
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
return upload;
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.copy() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload duplicate() {
|
||||
DiskFileUpload upload = new DiskFileUpload(getName(),
|
||||
getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size);
|
||||
ByteBuf buf = content();
|
||||
if (buf != null) {
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.duplicate() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload retainedDuplicate() {
|
||||
ByteBuf content = content();
|
||||
if (content != null) {
|
||||
content = content.retainedDuplicate();
|
||||
boolean success = false;
|
||||
try {
|
||||
upload.setContent(buf.duplicate());
|
||||
FileUpload duplicate = replace(content);
|
||||
success = true;
|
||||
return duplicate;
|
||||
} finally {
|
||||
if (!success) {
|
||||
content.release();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return replace(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload replace(ByteBuf content) {
|
||||
DiskFileUpload upload = new DiskFileUpload(
|
||||
getName(), getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size);
|
||||
if (content != null) {
|
||||
try {
|
||||
upload.setContent(content);
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* FileUpload interface that could be in memory, on temporary file or any other implementations.
|
||||
*
|
||||
@ -62,6 +64,12 @@ public interface FileUpload extends HttpData {
|
||||
@Override
|
||||
FileUpload duplicate();
|
||||
|
||||
@Override
|
||||
FileUpload retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FileUpload replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FileUpload retain();
|
||||
|
||||
|
@ -219,6 +219,12 @@ public interface HttpData extends InterfaceHttpData, ByteBufHolder {
|
||||
@Override
|
||||
HttpData duplicate();
|
||||
|
||||
@Override
|
||||
HttpData retainedDuplicate();
|
||||
|
||||
@Override
|
||||
HttpData replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
HttpData retain();
|
||||
|
||||
|
@ -26,11 +26,11 @@ import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpConstants;
|
||||
import io.netty.handler.codec.http.HttpContent;
|
||||
import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import io.netty.handler.codec.http.HttpUtil;
|
||||
import io.netty.handler.codec.http.HttpHeaderValues;
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.HttpUtil;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.stream.ChunkedInput;
|
||||
@ -48,7 +48,7 @@ import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
||||
|
||||
/**
|
||||
* This encoder will help to encode Request for a FORM as POST.
|
||||
@ -836,7 +836,6 @@ public class HttpPostRequestEncoder implements ChunkedInput<HttpContent> {
|
||||
int length = currentBuffer.readableBytes();
|
||||
if (length > HttpPostBodyUtil.chunkSize) {
|
||||
ByteBuf slice = currentBuffer.slice(currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize);
|
||||
currentBuffer.retain();
|
||||
currentBuffer.skipBytes(HttpPostBodyUtil.chunkSize);
|
||||
return slice;
|
||||
} else {
|
||||
@ -1239,45 +1238,24 @@ public class HttpPostRequestEncoder implements ChunkedInput<HttpContent> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy this object
|
||||
*
|
||||
* @param copyContent
|
||||
* <ul>
|
||||
* <li>{@code true} if this object's {@link #content()} should be used to copy.</li>
|
||||
* <li>{@code false} if {@code newContent} should be used instead.</li>
|
||||
* </ul>
|
||||
* @param newContent
|
||||
* <ul>
|
||||
* <li>if {@code copyContent} is false then this will be used in the copy's content.</li>
|
||||
* <li>if {@code null} then a default buffer of 0 size will be selected</li>
|
||||
* </ul>
|
||||
* @return A copy of this object
|
||||
*/
|
||||
private FullHttpRequest copy(boolean copyContent, ByteBuf newContent) {
|
||||
DefaultFullHttpRequest copy = new DefaultFullHttpRequest(
|
||||
protocolVersion(), method(), uri(),
|
||||
copyContent ? content().copy() :
|
||||
newContent == null ? buffer(0) : newContent);
|
||||
copy.headers().set(headers());
|
||||
copy.trailingHeaders().set(trailingHeaders());
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest copy(ByteBuf newContent) {
|
||||
return copy(false, newContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest copy() {
|
||||
return copy(true, null);
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest duplicate() {
|
||||
DefaultFullHttpRequest duplicate = new DefaultFullHttpRequest(
|
||||
getProtocolVersion(), getMethod(), getUri(), content().duplicate());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullHttpRequest replace(ByteBuf content) {
|
||||
DefaultFullHttpRequest duplicate = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content);
|
||||
duplicate.headers().set(headers());
|
||||
duplicate.trailingHeaders().set(trailingHeaders());
|
||||
return duplicate;
|
||||
|
@ -122,27 +122,43 @@ public class MemoryAttribute extends AbstractMemoryHttpData implements Attribute
|
||||
|
||||
@Override
|
||||
public Attribute copy() {
|
||||
MemoryAttribute attr = new MemoryAttribute(getName());
|
||||
attr.setCharset(getCharset());
|
||||
ByteBuf content = content();
|
||||
if (content != null) {
|
||||
try {
|
||||
attr.setContent(content.copy());
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
return attr;
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.copy() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute duplicate() {
|
||||
MemoryAttribute attr = new MemoryAttribute(getName());
|
||||
attr.setCharset(getCharset());
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.duplicate() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute retainedDuplicate() {
|
||||
ByteBuf content = content();
|
||||
if (content != null) {
|
||||
content = content.retainedDuplicate();
|
||||
boolean success = false;
|
||||
try {
|
||||
attr.setContent(content.duplicate());
|
||||
Attribute duplicate = replace(content);
|
||||
success = true;
|
||||
return duplicate;
|
||||
} finally {
|
||||
if (!success) {
|
||||
content.release();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return replace(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute replace(ByteBuf content) {
|
||||
MemoryAttribute attr = new MemoryAttribute(getName());
|
||||
attr.setCharset(getCharset());
|
||||
if (content != null) {
|
||||
try {
|
||||
attr.setContent(content);
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
|
@ -132,12 +132,43 @@ public class MemoryFileUpload extends AbstractMemoryHttpData implements FileUplo
|
||||
|
||||
@Override
|
||||
public FileUpload copy() {
|
||||
MemoryFileUpload upload = new MemoryFileUpload(getName(), getFilename(), getContentType(),
|
||||
getContentTransferEncoding(), getCharset(), size);
|
||||
ByteBuf buf = content();
|
||||
if (buf != null) {
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.copy() : content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload duplicate() {
|
||||
final ByteBuf content = content();
|
||||
return replace(content != null ? content.duplicate() : content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload retainedDuplicate() {
|
||||
ByteBuf content = content();
|
||||
if (content != null) {
|
||||
content = content.retainedDuplicate();
|
||||
boolean success = false;
|
||||
try {
|
||||
upload.setContent(buf.copy());
|
||||
FileUpload duplicate = replace(content);
|
||||
success = true;
|
||||
return duplicate;
|
||||
} finally {
|
||||
if (!success) {
|
||||
content.release();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return replace(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload replace(ByteBuf content) {
|
||||
MemoryFileUpload upload = new MemoryFileUpload(
|
||||
getName(), getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size);
|
||||
if (content != null) {
|
||||
try {
|
||||
upload.setContent(content);
|
||||
return upload;
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
@ -146,21 +177,6 @@ public class MemoryFileUpload extends AbstractMemoryHttpData implements FileUplo
|
||||
return upload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload duplicate() {
|
||||
MemoryFileUpload upload = new MemoryFileUpload(getName(), getFilename(), getContentType(),
|
||||
getContentTransferEncoding(), getCharset(), size);
|
||||
ByteBuf buf = content();
|
||||
if (buf != null) {
|
||||
try {
|
||||
upload.setContent(buf.duplicate());
|
||||
return upload;
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
return upload;
|
||||
}
|
||||
@Override
|
||||
public FileUpload retain() {
|
||||
super.retain();
|
||||
|
@ -271,6 +271,16 @@ public class MixedAttribute implements Attribute {
|
||||
return attribute.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute retainedDuplicate() {
|
||||
return attribute.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute replace(ByteBuf content) {
|
||||
return attribute.replace(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf content() {
|
||||
return attribute.content();
|
||||
|
@ -293,6 +293,16 @@ public class MixedFileUpload implements FileUpload {
|
||||
return fileUpload.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload retainedDuplicate() {
|
||||
return fileUpload.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileUpload replace(ByteBuf content) {
|
||||
return fileUpload.replace(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf content() {
|
||||
return fileUpload.content();
|
||||
|
@ -56,12 +56,22 @@ public class BinaryWebSocketFrame extends WebSocketFrame {
|
||||
|
||||
@Override
|
||||
public BinaryWebSocketFrame copy() {
|
||||
return new BinaryWebSocketFrame(isFinalFragment(), rsv(), content().copy());
|
||||
return (BinaryWebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryWebSocketFrame duplicate() {
|
||||
return new BinaryWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
|
||||
return (BinaryWebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryWebSocketFrame retainedDuplicate() {
|
||||
return (BinaryWebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryWebSocketFrame replace(ByteBuf content) {
|
||||
return new BinaryWebSocketFrame(isFinalFragment(), rsv(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -140,12 +140,22 @@ public class CloseWebSocketFrame extends WebSocketFrame {
|
||||
|
||||
@Override
|
||||
public CloseWebSocketFrame copy() {
|
||||
return new CloseWebSocketFrame(isFinalFragment(), rsv(), content().copy());
|
||||
return (CloseWebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseWebSocketFrame duplicate() {
|
||||
return new CloseWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
|
||||
return (CloseWebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseWebSocketFrame retainedDuplicate() {
|
||||
return (CloseWebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseWebSocketFrame replace(ByteBuf content) {
|
||||
return new CloseWebSocketFrame(isFinalFragment(), rsv(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,12 +93,22 @@ public class ContinuationWebSocketFrame extends WebSocketFrame {
|
||||
|
||||
@Override
|
||||
public ContinuationWebSocketFrame copy() {
|
||||
return new ContinuationWebSocketFrame(isFinalFragment(), rsv(), content().copy());
|
||||
return (ContinuationWebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContinuationWebSocketFrame duplicate() {
|
||||
return new ContinuationWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
|
||||
return (ContinuationWebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContinuationWebSocketFrame retainedDuplicate() {
|
||||
return (ContinuationWebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContinuationWebSocketFrame replace(ByteBuf content) {
|
||||
return new ContinuationWebSocketFrame(isFinalFragment(), rsv(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,12 +56,22 @@ public class PingWebSocketFrame extends WebSocketFrame {
|
||||
|
||||
@Override
|
||||
public PingWebSocketFrame copy() {
|
||||
return new PingWebSocketFrame(isFinalFragment(), rsv(), content().copy());
|
||||
return (PingWebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingWebSocketFrame duplicate() {
|
||||
return new PingWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
|
||||
return (PingWebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingWebSocketFrame retainedDuplicate() {
|
||||
return (PingWebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingWebSocketFrame replace(ByteBuf content) {
|
||||
return new PingWebSocketFrame(isFinalFragment(), rsv(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,12 +56,22 @@ public class PongWebSocketFrame extends WebSocketFrame {
|
||||
|
||||
@Override
|
||||
public PongWebSocketFrame copy() {
|
||||
return new PongWebSocketFrame(isFinalFragment(), rsv(), content().copy());
|
||||
return (PongWebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PongWebSocketFrame duplicate() {
|
||||
return new PongWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
|
||||
return (PongWebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PongWebSocketFrame retainedDuplicate() {
|
||||
return (PongWebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PongWebSocketFrame replace(ByteBuf content) {
|
||||
return new PongWebSocketFrame(isFinalFragment(), rsv(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,12 +96,22 @@ public class TextWebSocketFrame extends WebSocketFrame {
|
||||
|
||||
@Override
|
||||
public TextWebSocketFrame copy() {
|
||||
return new TextWebSocketFrame(isFinalFragment(), rsv(), content().copy());
|
||||
return (TextWebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextWebSocketFrame duplicate() {
|
||||
return new TextWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
|
||||
return (TextWebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextWebSocketFrame retainedDuplicate() {
|
||||
return (TextWebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextWebSocketFrame replace(ByteBuf content) {
|
||||
return new TextWebSocketFrame(isFinalFragment(), rsv(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,10 +61,22 @@ public abstract class WebSocketFrame extends DefaultByteBufHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract WebSocketFrame copy();
|
||||
public WebSocketFrame copy() {
|
||||
return (WebSocketFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract WebSocketFrame duplicate();
|
||||
public WebSocketFrame duplicate() {
|
||||
return (WebSocketFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketFrame retainedDuplicate() {
|
||||
return (WebSocketFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract WebSocketFrame replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -80,14 +80,22 @@ public class DefaultSpdyDataFrame extends DefaultSpdyStreamFrame implements Spdy
|
||||
|
||||
@Override
|
||||
public SpdyDataFrame copy() {
|
||||
SpdyDataFrame frame = new DefaultSpdyDataFrame(streamId(), content().copy());
|
||||
frame.setLast(isLast());
|
||||
return frame;
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpdyDataFrame duplicate() {
|
||||
SpdyDataFrame frame = new DefaultSpdyDataFrame(streamId(), content().duplicate());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpdyDataFrame retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpdyDataFrame replace(ByteBuf content) {
|
||||
SpdyDataFrame frame = new DefaultSpdyDataFrame(streamId(), content);
|
||||
frame.setLast(isLast());
|
||||
return frame;
|
||||
}
|
||||
|
@ -45,6 +45,12 @@ public interface SpdyDataFrame extends ByteBufHolder, SpdyStreamFrame {
|
||||
@Override
|
||||
SpdyDataFrame duplicate();
|
||||
|
||||
@Override
|
||||
SpdyDataFrame retainedDuplicate();
|
||||
|
||||
@Override
|
||||
SpdyDataFrame replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
SpdyDataFrame retain();
|
||||
|
||||
|
@ -24,7 +24,8 @@ import io.netty.util.internal.EmptyArrays;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static io.netty.handler.codec.spdy.SpdyCodecUtil.*;
|
||||
import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SESSION_STREAM_ID;
|
||||
import static io.netty.handler.codec.spdy.SpdyCodecUtil.isServerId;
|
||||
|
||||
/**
|
||||
* Manages streams within a SPDY session.
|
||||
@ -190,8 +191,8 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
|
||||
// Send data frames upstream in initialReceiveWindowSize chunks
|
||||
if (newWindowSize < 0) {
|
||||
while (spdyDataFrame.content().readableBytes() > initialReceiveWindowSize) {
|
||||
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamId,
|
||||
spdyDataFrame.content().readSlice(initialReceiveWindowSize).retain());
|
||||
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(
|
||||
streamId, spdyDataFrame.content().readRetainedSlice(initialReceiveWindowSize));
|
||||
ctx.writeAndFlush(partialDataFrame);
|
||||
}
|
||||
}
|
||||
@ -497,8 +498,8 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
|
||||
spdySession.updateSendWindowSize(SPDY_SESSION_STREAM_ID, -1 * sendWindowSize);
|
||||
|
||||
// Create a partial data frame whose length is the current window size
|
||||
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamId,
|
||||
spdyDataFrame.content().readSlice(sendWindowSize).retain());
|
||||
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(
|
||||
streamId, spdyDataFrame.content().readRetainedSlice(sendWindowSize));
|
||||
|
||||
// Enqueue the remaining data (will be the first frame queued)
|
||||
spdySession.putPendingWrite(streamId, new SpdySession.PendingWrite(spdyDataFrame, promise));
|
||||
@ -778,8 +779,8 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
|
||||
spdySession.updateSendWindowSize(SPDY_SESSION_STREAM_ID, -1 * sendWindowSize);
|
||||
|
||||
// Create a partial data frame whose length is the current window size
|
||||
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(writeStreamId,
|
||||
spdyDataFrame.content().readSlice(sendWindowSize).retain());
|
||||
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(
|
||||
writeStreamId, spdyDataFrame.content().readRetainedSlice(sendWindowSize));
|
||||
|
||||
// The transfer window size is pre-decremented when sending a data frame downstream.
|
||||
// Close the session on write failures that leave the transfer window in a corrupt state.
|
||||
|
@ -74,22 +74,32 @@ public class AbstractMemoryHttpDataTest {
|
||||
|
||||
@Override
|
||||
public InterfaceHttpData.HttpDataType getHttpDataType() {
|
||||
throw new UnsupportedOperationException("Should never be called.");
|
||||
throw reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpData copy() {
|
||||
throw new UnsupportedOperationException("Should never be called.");
|
||||
throw reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpData duplicate() {
|
||||
throw new UnsupportedOperationException("Should never be called.");
|
||||
throw reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpData retainedDuplicate() {
|
||||
throw reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpData replace(ByteBuf content) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(InterfaceHttpData o) {
|
||||
throw new UnsupportedOperationException("Should never be called.");
|
||||
throw reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,5 +111,9 @@ public class AbstractMemoryHttpDataTest {
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
private static UnsupportedOperationException reject() {
|
||||
throw new UnsupportedOperationException("Should never be called.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +460,7 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
|
||||
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
|
||||
// Send an ack back to the remote client.
|
||||
// Need to retain the buffer here since it will be released after the write completes.
|
||||
encoder.writePing(ctx, true, data.slice().retain(), ctx.newPromise());
|
||||
encoder.writePing(ctx, true, data.retainedSlice(), ctx.newPromise());
|
||||
|
||||
listener.onPingRead(ctx, data);
|
||||
}
|
||||
|
@ -15,13 +15,13 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http2;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.IllegalReferenceCountException;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* The default {@link Http2DataFrame} implementation.
|
||||
*/
|
||||
@ -101,12 +101,22 @@ public final class DefaultHttp2DataFrame extends AbstractHttp2StreamFrame implem
|
||||
|
||||
@Override
|
||||
public DefaultHttp2DataFrame copy() {
|
||||
return new DefaultHttp2DataFrame(content().copy(), endStream, padding);
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2DataFrame duplicate() {
|
||||
return new DefaultHttp2DataFrame(content().duplicate(), endStream, padding);
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2DataFrame retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2DataFrame replace(ByteBuf content) {
|
||||
return new DefaultHttp2DataFrame(content, endStream, padding);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,14 @@
|
||||
|
||||
package io.netty.handler.codec.http2;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.handler.codec.http2.Http2CodecUtil.SimpleChannelPromiseAggregator;
|
||||
import io.netty.handler.codec.http2.Http2FrameWriter.Configuration;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import static io.netty.buffer.Unpooled.directBuffer;
|
||||
import static io.netty.buffer.Unpooled.unreleasableBuffer;
|
||||
import static io.netty.handler.codec.http2.Http2CodecUtil.CONTINUATION_FRAME_HEADER_LENGTH;
|
||||
@ -55,14 +63,6 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.handler.codec.http2.Http2CodecUtil.SimpleChannelPromiseAggregator;
|
||||
import io.netty.handler.codec.http2.Http2FrameWriter.Configuration;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
/**
|
||||
* A {@link Http2FrameWriter} that supports all frame types defined by the HTTP/2 specification.
|
||||
*/
|
||||
@ -304,8 +304,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
|
||||
// INT_FIELD_LENGTH is for the length of the promisedStreamId
|
||||
int nonFragmentLength = INT_FIELD_LENGTH + padding + flags.getPaddingPresenceFieldLength();
|
||||
int maxFragmentLength = maxFrameSize - nonFragmentLength;
|
||||
ByteBuf fragment =
|
||||
headerBlock.readSlice(min(headerBlock.readableBytes(), maxFragmentLength));
|
||||
ByteBuf fragment = headerBlock.readRetainedSlice(min(headerBlock.readableBytes(), maxFragmentLength));
|
||||
|
||||
flags.endOfHeaders(!headerBlock.isReadable());
|
||||
|
||||
@ -319,7 +318,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
|
||||
ctx.write(buf, promiseAggregator.newPromise());
|
||||
|
||||
// Write the first fragment.
|
||||
ctx.write(fragment.retain(), promiseAggregator.newPromise());
|
||||
ctx.write(fragment, promiseAggregator.newPromise());
|
||||
|
||||
if (padding > 0) { // Write out the padding, if any.
|
||||
ctx.write(ZERO_BUFFER.slice(0, padding), promiseAggregator.newPromise());
|
||||
@ -429,8 +428,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
|
||||
// Read the first fragment (possibly everything).
|
||||
int nonFragmentBytes = padding + flags.getNumPriorityBytes() + flags.getPaddingPresenceFieldLength();
|
||||
int maxFragmentLength = maxFrameSize - nonFragmentBytes;
|
||||
ByteBuf fragment =
|
||||
headerBlock.readSlice(min(headerBlock.readableBytes(), maxFragmentLength));
|
||||
ByteBuf fragment = headerBlock.readRetainedSlice(min(headerBlock.readableBytes(), maxFragmentLength));
|
||||
|
||||
// Set the end of headers flag for the first frame.
|
||||
flags.endOfHeaders(!headerBlock.isReadable());
|
||||
@ -450,7 +448,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
|
||||
ctx.write(buf, promiseAggregator.newPromise());
|
||||
|
||||
// Write the first fragment.
|
||||
ctx.write(fragment.retain(), promiseAggregator.newPromise());
|
||||
ctx.write(fragment, promiseAggregator.newPromise());
|
||||
|
||||
if (padding > 0) { // Write out the padding, if any.
|
||||
ctx.write(ZERO_BUFFER.slice(0, padding), promiseAggregator.newPromise());
|
||||
@ -493,7 +491,7 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize
|
||||
|
||||
do {
|
||||
fragmentReadableBytes = min(headerBlock.readableBytes(), maxFragmentLength);
|
||||
ByteBuf fragment = headerBlock.readSlice(fragmentReadableBytes).retain();
|
||||
ByteBuf fragment = headerBlock.readRetainedSlice(fragmentReadableBytes);
|
||||
|
||||
payloadLength = fragmentReadableBytes + nonFragmentLength;
|
||||
if (headerBlock.isReadable()) {
|
||||
|
@ -78,7 +78,7 @@ public final class DefaultHttp2GoAwayFrame extends DefaultByteBufHolder implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame setExtraStreamIds(int extraStreamIds) {
|
||||
public Http2GoAwayFrame setExtraStreamIds(int extraStreamIds) {
|
||||
if (extraStreamIds < 0) {
|
||||
throw new IllegalArgumentException("extraStreamIds must be non-negative");
|
||||
}
|
||||
@ -87,41 +87,45 @@ public final class DefaultHttp2GoAwayFrame extends DefaultByteBufHolder implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame copy() {
|
||||
return new DefaultHttp2GoAwayFrame(errorCode, content().copy()).setExtraStreamIds(extraStreamIds);
|
||||
public Http2GoAwayFrame copy() {
|
||||
return (Http2GoAwayFrame) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame duplicate() {
|
||||
return new DefaultHttp2GoAwayFrame(errorCode, content().duplicate()).setExtraStreamIds(extraStreamIds);
|
||||
public Http2GoAwayFrame duplicate() {
|
||||
return (Http2GoAwayFrame) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame retain() {
|
||||
public Http2GoAwayFrame retainedDuplicate() {
|
||||
return (Http2GoAwayFrame) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2GoAwayFrame replace(ByteBuf content) {
|
||||
return new DefaultHttp2GoAwayFrame(errorCode, content).setExtraStreamIds(extraStreamIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2GoAwayFrame retain() {
|
||||
super.retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame retain(int increment) {
|
||||
public Http2GoAwayFrame retain(int increment) {
|
||||
super.retain(increment);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DefaultHttp2GoAwayFrame(errorCode=" + errorCode + ", content=" + content()
|
||||
+ ", extraStreamIds=" + extraStreamIds + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame touch() {
|
||||
public Http2GoAwayFrame touch() {
|
||||
super.touch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHttp2GoAwayFrame touch(Object hint) {
|
||||
public Http2GoAwayFrame touch(Object hint) {
|
||||
super.touch(hint);
|
||||
return this;
|
||||
}
|
||||
@ -144,4 +148,10 @@ public final class DefaultHttp2GoAwayFrame extends DefaultByteBufHolder implemen
|
||||
hash = hash * 31 + extraStreamIds;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DefaultHttp2GoAwayFrame(errorCode=" + errorCode + ", content=" + content()
|
||||
+ ", extraStreamIds=" + extraStreamIds + ")";
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ public final class Http2CodecUtil {
|
||||
*/
|
||||
public static ByteBuf connectionPrefaceBuf() {
|
||||
// Return a duplicate so that modifications to the reader index will not affect the original buffer.
|
||||
return CONNECTION_PREFACE.duplicate().retain();
|
||||
return CONNECTION_PREFACE.retainedDuplicate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,7 +127,7 @@ public final class Http2CodecUtil {
|
||||
*/
|
||||
public static ByteBuf emptyPingBuf() {
|
||||
// Return a duplicate so that modifications to the reader index will not affect the original buffer.
|
||||
return EMPTY_PING.duplicate().retain();
|
||||
return EMPTY_PING.retainedDuplicate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,6 +49,12 @@ public interface Http2DataFrame extends Http2StreamFrame, ByteBufHolder {
|
||||
@Override
|
||||
Http2DataFrame duplicate();
|
||||
|
||||
@Override
|
||||
Http2DataFrame retainedDuplicate();
|
||||
|
||||
@Override
|
||||
Http2DataFrame replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
Http2DataFrame retain();
|
||||
|
||||
|
@ -58,6 +58,12 @@ public interface Http2GoAwayFrame extends Http2Frame, ByteBufHolder {
|
||||
@Override
|
||||
Http2GoAwayFrame duplicate();
|
||||
|
||||
@Override
|
||||
Http2GoAwayFrame retainedDuplicate();
|
||||
|
||||
@Override
|
||||
Http2GoAwayFrame replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
Http2GoAwayFrame retain();
|
||||
|
||||
|
@ -371,7 +371,7 @@ public final class Http2MultiplexCodec extends ChannelDuplexHandler {
|
||||
StreamInfo streamInfo = (StreamInfo) stream.getProperty(streamInfoKey);
|
||||
// TODO: Can we force a user interaction pattern that doesn't require us to duplicate()?
|
||||
// https://github.com/netty/netty/issues/4943
|
||||
streamInfo.childChannel.pipeline().fireUserEventTriggered(goAway.duplicate().retain());
|
||||
streamInfo.childChannel.pipeline().fireUserEventTriggered(goAway.retainedDuplicate());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -389,12 +389,12 @@ public final class Http2MultiplexCodec extends ChannelDuplexHandler {
|
||||
});
|
||||
}
|
||||
}
|
||||
ctx.fireUserEventTriggered(goAway.duplicate().retain());
|
||||
ctx.fireUserEventTriggered(goAway.retainedDuplicate());
|
||||
}
|
||||
}
|
||||
|
||||
class InternalHttp2ConnectionHandler extends Http2ConnectionHandler {
|
||||
public InternalHttp2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
|
||||
InternalHttp2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
|
||||
Http2Settings initialSettings) {
|
||||
super(decoder, encoder, initialSettings);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package io.netty.handler.codec.http2;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.FullHttpMessage;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
@ -53,7 +54,7 @@ public class InboundHttp2ToHttpAdapter extends Http2EventAdapter {
|
||||
@Override
|
||||
public FullHttpMessage copyIfNeeded(FullHttpMessage msg) {
|
||||
if (msg instanceof FullHttpRequest) {
|
||||
FullHttpRequest copy = ((FullHttpRequest) msg).copy(null);
|
||||
FullHttpRequest copy = ((FullHttpRequest) msg).replace(Unpooled.buffer(0));
|
||||
copy.headers().remove(HttpHeaderNames.EXPECT);
|
||||
return copy;
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ public class Http2ConnectionRoundtripTest {
|
||||
public void run() throws Http2Exception {
|
||||
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
|
||||
false, newPromise());
|
||||
http2Client.encoder().writeData(ctx(), 3, data.duplicate().retain(), 0, false, newPromise());
|
||||
http2Client.encoder().writeData(ctx(), 3, data.retainedDuplicate(), 0, false, newPromise());
|
||||
|
||||
// Write trailers.
|
||||
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
|
||||
@ -479,10 +479,10 @@ public class Http2ConnectionRoundtripTest {
|
||||
// Send a bunch of data on each stream.
|
||||
http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16,
|
||||
false, 0, false, newPromise());
|
||||
http2Client.encoder().writePing(ctx(), false, pingData.slice().retain(),
|
||||
http2Client.encoder().writePing(ctx(), false, pingData.retainedSlice(),
|
||||
newPromise());
|
||||
http2Client.encoder().writeData(ctx(), streamId, data.slice().retain(), 0,
|
||||
false, newPromise());
|
||||
http2Client.encoder().writeData(ctx(), streamId, data.retainedSlice(), 0,
|
||||
false, newPromise());
|
||||
// Write trailers.
|
||||
http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16,
|
||||
false, 0, true, newPromise());
|
||||
|
@ -267,7 +267,7 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
@Override
|
||||
public void run() {
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.duplicate().retain(), 0, true,
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true,
|
||||
newPromiseClient());
|
||||
clientChannel.flush();
|
||||
}
|
||||
@ -300,10 +300,11 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
@Override
|
||||
public void run() {
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.slice(0, midPoint).retain(), 0, false,
|
||||
newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 3,
|
||||
content.slice(midPoint, text.length() - midPoint).retain(), 0, true, newPromiseClient());
|
||||
clientHandler.encoder().writeData(
|
||||
ctxClient(), 3, content.retainedSlice(0, midPoint), 0, false, newPromiseClient());
|
||||
clientHandler.encoder().writeData(
|
||||
ctxClient(), 3, content.retainedSlice(midPoint, text.length() - midPoint),
|
||||
0, true, newPromiseClient());
|
||||
clientChannel.flush();
|
||||
}
|
||||
});
|
||||
@ -417,7 +418,7 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
@Override
|
||||
public void run() {
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.duplicate().retain(), 0, false,
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, false,
|
||||
newPromiseClient());
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers2, 0, true, newPromiseClient());
|
||||
clientChannel.flush();
|
||||
@ -464,9 +465,9 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 5, http2Headers2, 0, false, newPromiseClient());
|
||||
clientChannel.flush(); // Headers are queued in the flow controller and so flush them.
|
||||
clientHandler.encoder().writePriority(ctxClient(), 5, 3, (short) 123, true, newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.duplicate().retain(), 0, true,
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true,
|
||||
newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 5, content2.duplicate().retain(), 0, true,
|
||||
clientHandler.encoder().writeData(ctxClient(), 5, content2.retainedDuplicate(), 0, true,
|
||||
newPromiseClient());
|
||||
clientChannel.flush();
|
||||
}
|
||||
@ -518,9 +519,9 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
public void run() {
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
|
||||
clientHandler.encoder().writeHeaders(ctxClient(), 5, http2Headers2, 0, false, newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.duplicate().retain(), 0, true,
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true,
|
||||
newPromiseClient());
|
||||
clientHandler.encoder().writeData(ctxClient(), 5, content2.duplicate().retain(), 0, true,
|
||||
clientHandler.encoder().writeData(ctxClient(), 5, content2.retainedDuplicate(), 0, true,
|
||||
newPromiseClient());
|
||||
clientChannel.flush(); // headers and data are queued in the flow controller, so flush them.
|
||||
clientHandler.encoder().writePriority(ctxClient(), 5, 3, (short) 222, false, newPromiseClient());
|
||||
@ -592,9 +593,9 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
public void run() {
|
||||
serverHandler.encoder().writeHeaders(ctxServer(), 3, http2Headers, 0, false, newPromiseServer());
|
||||
serverHandler.encoder().writePushPromise(ctxServer(), 3, 2, http2Headers2, 0, newPromiseServer());
|
||||
serverHandler.encoder().writeData(ctxServer(), 3, content.duplicate().retain(), 0, true,
|
||||
serverHandler.encoder().writeData(ctxServer(), 3, content.retainedDuplicate(), 0, true,
|
||||
newPromiseServer());
|
||||
serverHandler.encoder().writeData(ctxServer(), 5, content2.duplicate().retain(), 0, true,
|
||||
serverHandler.encoder().writeData(ctxServer(), 5, content2.retainedDuplicate(), 0, true,
|
||||
newPromiseServer());
|
||||
serverConnectedChannel.flush();
|
||||
}
|
||||
@ -627,7 +628,7 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
final FullHttpMessage response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
|
||||
final String text = "a big payload";
|
||||
final ByteBuf payload = Unpooled.copiedBuffer(text.getBytes());
|
||||
final FullHttpMessage request2 = request.copy(payload);
|
||||
final FullHttpMessage request2 = request.replace(payload);
|
||||
final FullHttpMessage response2 = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
|
||||
|
||||
try {
|
||||
@ -660,7 +661,7 @@ public class InboundHttp2ToHttpAdapterTest {
|
||||
runInChannel(clientChannel, new Http2Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, payload.duplicate().retain(), 0, true,
|
||||
clientHandler.encoder().writeData(ctxClient(), 3, payload.retainedDuplicate(), 0, true,
|
||||
newPromiseClient());
|
||||
clientChannel.flush();
|
||||
}
|
||||
|
@ -60,11 +60,21 @@ public class DefaultLastMemcacheContent extends DefaultMemcacheContent implement
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent copy() {
|
||||
return new DefaultLastMemcacheContent(content().copy());
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent duplicate() {
|
||||
return new DefaultLastMemcacheContent(content().duplicate());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent replace(ByteBuf content) {
|
||||
return new DefaultLastMemcacheContent(content);
|
||||
}
|
||||
}
|
||||
|
@ -44,12 +44,22 @@ public class DefaultMemcacheContent extends AbstractMemcacheObject implements Me
|
||||
|
||||
@Override
|
||||
public MemcacheContent copy() {
|
||||
return new DefaultMemcacheContent(content.copy());
|
||||
return replace(content.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemcacheContent duplicate() {
|
||||
return new DefaultMemcacheContent(content.duplicate());
|
||||
return replace(content.duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemcacheContent retainedDuplicate() {
|
||||
return replace(content.retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemcacheContent replace(ByteBuf content) {
|
||||
return new DefaultMemcacheContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.memcache;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
/**
|
||||
@ -27,6 +28,15 @@ public interface FullMemcacheMessage extends MemcacheMessage, LastMemcacheConten
|
||||
@Override
|
||||
FullMemcacheMessage copy();
|
||||
|
||||
@Override
|
||||
FullMemcacheMessage duplicate();
|
||||
|
||||
@Override
|
||||
FullMemcacheMessage retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FullMemcacheMessage replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FullMemcacheMessage retain(int increment);
|
||||
|
||||
@ -38,7 +48,4 @@ public interface FullMemcacheMessage extends MemcacheMessage, LastMemcacheConten
|
||||
|
||||
@Override
|
||||
FullMemcacheMessage touch(Object hint);
|
||||
|
||||
@Override
|
||||
FullMemcacheMessage duplicate();
|
||||
}
|
||||
|
@ -37,6 +37,21 @@ public interface LastMemcacheContent extends MemcacheContent {
|
||||
return EMPTY_LAST_CONTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent duplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent replace(ByteBuf content) {
|
||||
return new DefaultLastMemcacheContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent retain(int increment) {
|
||||
return this;
|
||||
@ -57,11 +72,6 @@ public interface LastMemcacheContent extends MemcacheContent {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastMemcacheContent duplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf content() {
|
||||
return Unpooled.EMPTY_BUFFER;
|
||||
@ -96,6 +106,15 @@ public interface LastMemcacheContent extends MemcacheContent {
|
||||
@Override
|
||||
LastMemcacheContent copy();
|
||||
|
||||
@Override
|
||||
LastMemcacheContent duplicate();
|
||||
|
||||
@Override
|
||||
LastMemcacheContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
LastMemcacheContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
LastMemcacheContent retain(int increment);
|
||||
|
||||
@ -107,7 +126,4 @@ public interface LastMemcacheContent extends MemcacheContent {
|
||||
|
||||
@Override
|
||||
LastMemcacheContent touch(Object hint);
|
||||
|
||||
@Override
|
||||
LastMemcacheContent duplicate();
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.memcache;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
@ -36,6 +37,12 @@ public interface MemcacheContent extends MemcacheObject, ByteBufHolder {
|
||||
@Override
|
||||
MemcacheContent duplicate();
|
||||
|
||||
@Override
|
||||
MemcacheContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
MemcacheContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
MemcacheContent retain();
|
||||
|
||||
|
@ -89,7 +89,7 @@ public abstract class AbstractBinaryMemcacheDecoder<M extends BinaryMemcacheMess
|
||||
return;
|
||||
}
|
||||
|
||||
currentMessage.setExtras(in.readSlice(extrasLength).retain());
|
||||
currentMessage.setExtras(in.readRetainedSlice(extrasLength));
|
||||
}
|
||||
|
||||
state = State.READ_KEY;
|
||||
@ -105,7 +105,7 @@ public abstract class AbstractBinaryMemcacheDecoder<M extends BinaryMemcacheMess
|
||||
return;
|
||||
}
|
||||
|
||||
currentMessage.setKey(in.readSlice(keyLength).retain());
|
||||
currentMessage.setKey(in.readRetainedSlice(keyLength));
|
||||
}
|
||||
out.add(currentMessage.retain());
|
||||
state = State.READ_CONTENT;
|
||||
@ -133,7 +133,7 @@ public abstract class AbstractBinaryMemcacheDecoder<M extends BinaryMemcacheMess
|
||||
toRead = remainingLength;
|
||||
}
|
||||
|
||||
ByteBuf chunkBuffer = in.readSlice(toRead).retain();
|
||||
ByteBuf chunkBuffer = in.readRetainedSlice(toRead);
|
||||
|
||||
MemcacheContent chunk;
|
||||
if ((alreadyReadChunkSize += toRead) >= valueLength) {
|
||||
|
@ -117,4 +117,22 @@ public class DefaultFullBinaryMemcacheRequest extends DefaultBinaryMemcacheReque
|
||||
}
|
||||
return new DefaultFullBinaryMemcacheRequest(key, extras, content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBinaryMemcacheRequest retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBinaryMemcacheRequest replace(ByteBuf content) {
|
||||
ByteBuf key = key();
|
||||
if (key != null) {
|
||||
key = key.retainedDuplicate();
|
||||
}
|
||||
ByteBuf extras = extras();
|
||||
if (extras != null) {
|
||||
extras = extras.retainedDuplicate();
|
||||
}
|
||||
return new DefaultFullBinaryMemcacheRequest(key, extras, content);
|
||||
}
|
||||
}
|
||||
|
@ -117,4 +117,22 @@ public class DefaultFullBinaryMemcacheResponse extends DefaultBinaryMemcacheResp
|
||||
}
|
||||
return new DefaultFullBinaryMemcacheResponse(key, extras, content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBinaryMemcacheResponse retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBinaryMemcacheResponse replace(ByteBuf content) {
|
||||
ByteBuf key = key();
|
||||
if (key != null) {
|
||||
key = key.retainedDuplicate();
|
||||
}
|
||||
ByteBuf extras = extras();
|
||||
if (extras != null) {
|
||||
extras = extras.retainedDuplicate();
|
||||
}
|
||||
return new DefaultFullBinaryMemcacheResponse(key, extras, content);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.memcache.binary;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.memcache.FullMemcacheMessage;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
@ -27,6 +28,15 @@ public interface FullBinaryMemcacheRequest extends BinaryMemcacheRequest, FullMe
|
||||
@Override
|
||||
FullBinaryMemcacheRequest copy();
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheRequest duplicate();
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheRequest retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheRequest replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheRequest retain(int increment);
|
||||
|
||||
@ -38,7 +48,4 @@ public interface FullBinaryMemcacheRequest extends BinaryMemcacheRequest, FullMe
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheRequest touch(Object hint);
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheRequest duplicate();
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.memcache.binary;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.memcache.FullMemcacheMessage;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
@ -27,6 +28,15 @@ public interface FullBinaryMemcacheResponse extends BinaryMemcacheResponse, Full
|
||||
@Override
|
||||
FullBinaryMemcacheResponse copy();
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheResponse duplicate();
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheResponse retainedDuplicate();
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheResponse replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheResponse retain(int increment);
|
||||
|
||||
@ -38,7 +48,4 @@ public interface FullBinaryMemcacheResponse extends BinaryMemcacheResponse, Full
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheResponse touch(Object hint);
|
||||
|
||||
@Override
|
||||
FullBinaryMemcacheResponse duplicate();
|
||||
}
|
||||
|
@ -26,7 +26,11 @@ import io.netty.util.CharsetUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.handler.codec.mqtt.MqttCodecUtil.*;
|
||||
import static io.netty.handler.codec.mqtt.MqttCodecUtil.isValidClientId;
|
||||
import static io.netty.handler.codec.mqtt.MqttCodecUtil.isValidMessageId;
|
||||
import static io.netty.handler.codec.mqtt.MqttCodecUtil.isValidPublishTopicName;
|
||||
import static io.netty.handler.codec.mqtt.MqttCodecUtil.resetUnusedFields;
|
||||
import static io.netty.handler.codec.mqtt.MqttCodecUtil.validateFixedHeader;
|
||||
|
||||
/**
|
||||
* Decodes Mqtt messages from bytes, following
|
||||
@ -409,7 +413,7 @@ public final class MqttDecoder extends ReplayingDecoder<DecoderState> {
|
||||
}
|
||||
|
||||
private static Result<ByteBuf> decodePublishPayload(ByteBuf buffer, int bytesRemainingInVariablePart) {
|
||||
ByteBuf b = buffer.readSlice(bytesRemainingInVariablePart).retain();
|
||||
ByteBuf b = buffer.readRetainedSlice(bytesRemainingInVariablePart);
|
||||
return new Result<ByteBuf>(b, bytesRemainingInVariablePart);
|
||||
}
|
||||
|
||||
|
@ -53,12 +53,22 @@ public class MqttPublishMessage extends MqttMessage implements ByteBufHolder {
|
||||
|
||||
@Override
|
||||
public MqttPublishMessage copy() {
|
||||
return new MqttPublishMessage(fixedHeader(), variableHeader(), content().copy());
|
||||
return replace(content().copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttPublishMessage duplicate() {
|
||||
return new MqttPublishMessage(fixedHeader(), variableHeader(), content().duplicate());
|
||||
return replace(content().duplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttPublishMessage retainedDuplicate() {
|
||||
return replace(content().retainedDuplicate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttPublishMessage replace(ByteBuf content) {
|
||||
return new MqttPublishMessage(fixedHeader(), variableHeader(), content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
package io.netty.handler.codec.redis;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
@ -28,4 +29,28 @@ import io.netty.util.internal.UnstableApi;
|
||||
*/
|
||||
@UnstableApi
|
||||
public interface BulkStringRedisContent extends RedisMessage, ByteBufHolder {
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent copy();
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent duplicate();
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent retain();
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent retain(int increment);
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent touch();
|
||||
|
||||
@Override
|
||||
BulkStringRedisContent touch(Object hint);
|
||||
}
|
||||
|
@ -35,6 +35,50 @@ public class DefaultBulkStringRedisContent extends DefaultByteBufHolder implemen
|
||||
super(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent copy() {
|
||||
return (BulkStringRedisContent) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent duplicate() {
|
||||
return (BulkStringRedisContent) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent retainedDuplicate() {
|
||||
return (BulkStringRedisContent) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent replace(ByteBuf content) {
|
||||
return new DefaultBulkStringRedisContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent retain() {
|
||||
super.retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent retain(int increment) {
|
||||
super.retain(increment);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent touch() {
|
||||
super.touch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkStringRedisContent touch(Object hint) {
|
||||
super.touch(hint);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(StringUtil.simpleClassName(this))
|
||||
|
@ -32,4 +32,48 @@ public final class DefaultLastBulkStringRedisContent extends DefaultBulkStringRe
|
||||
public DefaultLastBulkStringRedisContent(ByteBuf content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent copy() {
|
||||
return (LastBulkStringRedisContent) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent duplicate() {
|
||||
return (LastBulkStringRedisContent) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent retainedDuplicate() {
|
||||
return (LastBulkStringRedisContent) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent replace(ByteBuf content) {
|
||||
return new DefaultLastBulkStringRedisContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent retain() {
|
||||
super.retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent retain(int increment) {
|
||||
super.retain(increment);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent touch() {
|
||||
super.touch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent touch(Object hint) {
|
||||
super.touch(hint);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,11 @@ public class FullBulkStringRedisMessage extends DefaultByteBufHolder implements
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int refCnt() {
|
||||
return 1;
|
||||
@ -131,7 +136,7 @@ public class FullBulkStringRedisMessage extends DefaultByteBufHolder implements
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage copy() {
|
||||
return EMPTY_INSTANCE;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,6 +144,11 @@ public class FullBulkStringRedisMessage extends DefaultByteBufHolder implements
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int refCnt() {
|
||||
return 1;
|
||||
@ -174,4 +184,48 @@ public class FullBulkStringRedisMessage extends DefaultByteBufHolder implements
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage copy() {
|
||||
return (FullBulkStringRedisMessage) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage duplicate() {
|
||||
return (FullBulkStringRedisMessage) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage retainedDuplicate() {
|
||||
return (FullBulkStringRedisMessage) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage replace(ByteBuf content) {
|
||||
return new FullBulkStringRedisMessage(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage retain() {
|
||||
super.retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage retain(int increment) {
|
||||
super.retain(increment);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage touch() {
|
||||
super.touch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullBulkStringRedisMessage touch(Object hint) {
|
||||
super.touch(hint);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.codec.redis;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
@ -37,17 +36,32 @@ public interface LastBulkStringRedisContent extends BulkStringRedisContent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufHolder copy() {
|
||||
public LastBulkStringRedisContent copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufHolder retain(int increment) {
|
||||
public LastBulkStringRedisContent duplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufHolder retain() {
|
||||
public LastBulkStringRedisContent retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent replace(ByteBuf content) {
|
||||
return new DefaultLastBulkStringRedisContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent retain(int increment) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastBulkStringRedisContent retain() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -57,12 +71,12 @@ public interface LastBulkStringRedisContent extends BulkStringRedisContent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufHolder touch() {
|
||||
public LastBulkStringRedisContent touch() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufHolder touch(Object hint) {
|
||||
public LastBulkStringRedisContent touch(Object hint) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -75,10 +89,29 @@ public interface LastBulkStringRedisContent extends BulkStringRedisContent {
|
||||
public boolean release(int decrement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufHolder duplicate() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent copy();
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent duplicate();
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent retain();
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent retain(int increment);
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent touch();
|
||||
|
||||
@Override
|
||||
LastBulkStringRedisContent touch(Object hint);
|
||||
}
|
||||
|
@ -33,34 +33,44 @@ public final class DefaultLastSmtpContent extends DefaultSmtpContent implements
|
||||
|
||||
@Override
|
||||
public LastSmtpContent copy() {
|
||||
return new DefaultLastSmtpContent(content().copy());
|
||||
return (LastSmtpContent) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent duplicate() {
|
||||
return new DefaultLastSmtpContent(content().duplicate());
|
||||
return (LastSmtpContent) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent retain() {
|
||||
public LastSmtpContent retainedDuplicate() {
|
||||
return (LastSmtpContent) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent replace(ByteBuf content) {
|
||||
return new DefaultLastSmtpContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultLastSmtpContent retain() {
|
||||
super.retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent retain(int increment) {
|
||||
public DefaultLastSmtpContent retain(int increment) {
|
||||
super.retain(increment);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent touch() {
|
||||
public DefaultLastSmtpContent touch() {
|
||||
super.touch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent touch(Object hint) {
|
||||
public DefaultLastSmtpContent touch(Object hint) {
|
||||
super.touch(hint);
|
||||
return this;
|
||||
}
|
||||
|
@ -34,12 +34,22 @@ public class DefaultSmtpContent extends DefaultByteBufHolder implements SmtpCont
|
||||
|
||||
@Override
|
||||
public SmtpContent copy() {
|
||||
return new DefaultSmtpContent(content().copy());
|
||||
return (SmtpContent) super.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmtpContent duplicate() {
|
||||
return new DefaultSmtpContent(content().duplicate());
|
||||
return (SmtpContent) super.duplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmtpContent retainedDuplicate() {
|
||||
return (SmtpContent) super.retainedDuplicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmtpContent replace(ByteBuf content) {
|
||||
return new DefaultSmtpContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,6 +42,16 @@ public interface LastSmtpContent extends SmtpContent {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent retainedDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent replace(ByteBuf content) {
|
||||
return new DefaultLastSmtpContent(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LastSmtpContent retain() {
|
||||
return this;
|
||||
@ -89,6 +99,12 @@ public interface LastSmtpContent extends SmtpContent {
|
||||
@Override
|
||||
LastSmtpContent duplicate();
|
||||
|
||||
@Override
|
||||
LastSmtpContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
LastSmtpContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
LastSmtpContent retain();
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.codec.smtp;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
@ -32,6 +33,12 @@ public interface SmtpContent extends ByteBufHolder {
|
||||
@Override
|
||||
SmtpContent duplicate();
|
||||
|
||||
@Override
|
||||
SmtpContent retainedDuplicate();
|
||||
|
||||
@Override
|
||||
SmtpContent replace(ByteBuf content);
|
||||
|
||||
@Override
|
||||
SmtpContent retain();
|
||||
|
||||
|
@ -76,7 +76,7 @@ public final class SmtpRequestEncoder extends MessageToMessageEncoder<Object> {
|
||||
final ByteBuf content = ((SmtpContent) msg).content();
|
||||
out.add(content.retain());
|
||||
if (msg instanceof LastSmtpContent) {
|
||||
out.add(DOT_CRLF_BUFFER.duplicate().retain());
|
||||
out.add(DOT_CRLF_BUFFER.retainedDuplicate());
|
||||
contentExpected = false;
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class Socks4ClientDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ public class Socks4ServerDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ public class Socks5CommandRequestDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class Socks5CommandResponseDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class Socks5InitialRequestDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class Socks5InitialResponseDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class Socks5PasswordAuthRequestDecoder extends ReplayingDecoder<State> {
|
||||
case SUCCESS: {
|
||||
int readableBytes = actualReadableBytes();
|
||||
if (readableBytes > 0) {
|
||||
out.add(in.readSlice(readableBytes).retain());
|
||||
out.add(in.readRetainedSlice(readableBytes));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user