public class ByteBufferByteSink extends AbstractByteSink
Byte sink that is backed by a list of byte buffers. This byte sink allows for accessing a sequence of buffers like they were one contiguous buffer.
Attention: Special care must be taken to ensure that all
byte buffers added to an instance of this class have the same
ByteOrder
. Otherwise the put methods that return multi-byte
data-types might have unexpected results.
The put*Array
methods are optimized to only use one copy
operation for transferring data. An extra copy operation is necessary for
elements that span across two of the backing ByteBuffer
s, however all
other elements are written with only a single copy operation. If the
ByteBuffer
's ByteOrder
is the platforms native byte order,
array writes can be expected to be very efficient, because complete blocks of
memory are copied.
Sub-classes can override requestAdditionalBuffer(int)
in order to
provide an additional buffer if this byte sink runs out of space.
Instances of this class are not thread-safe. If multiple threads are going to access an instance of this class, access to it must be synchronized. This also applies to both simple put operations as well as "atomic" put operations.
This implementation guarantees that if a put operation finished successfully, the whole data will have been written to the backing byte-buffers.
ByteSink.AtomicPutOperation<T>
SIZE_OF_BYTE, SIZE_OF_DOUBLE, SIZE_OF_FLOAT, SIZE_OF_INT, SIZE_OF_LONG, SIZE_OF_SHORT
Constructor and Description |
---|
ByteBufferByteSink()
Creates a new byte sink that initially does not contain any buffers.
|
Modifier and Type | Method and Description |
---|---|
ByteBufferByteSink |
addBuffer(ByteBuffer byteBuffer)
Adds a byte buffer to the list of available byte-buffers.
|
void |
addBufferFirst(ByteBuffer byteBuffer)
Adds a byte buffer to the head of the list of available byte buffers.
|
ByteBufferByteSink |
addBuffers(ByteBuffer[] byteBuffers)
Adds byte buffers to the list of available byte-buffers.
|
ByteBufferByteSink |
addBuffers(Iterable<? extends ByteBuffer> byteBuffers)
Adds byte buffers to the list of available byte-buffers.
|
<T> T |
atomicPut(ByteSink.AtomicPutOperation<? extends T> atomicPutOperation)
Starts an atomic put operation.
|
protected void |
dataWritten()
Called when data has been committed to the byte buffers backing this byte
sink.
|
ByteBuffer[] |
getWrittenData()
Returns all byte buffers to which data has been written and removes them
from the internal list.
|
long |
getWrittenDataSizeInBytes()
Returns the number of bytes that have been written to this byte sink and
are stored in buffers that have not been removed yet.
|
ByteBufferByteSink |
putByteArray(byte[] source,
int offset,
int length)
Writes a slice of an array of bytes to this byte sink.
|
ByteSink |
putDoubleArray(double[] source,
int offset,
int length)
Writes a slice of an array of double values to this byte sink.
|
ByteSink |
putFloatArray(float[] source,
int offset,
int length)
Writes a slice of an array of float values to this byte sink.
|
ByteSink |
putIntArray(int[] source,
int offset,
int length)
Writes a slice of an array of int values to this byte sink.
|
ByteSink |
putLongArray(long[] source,
int offset,
int length)
Writes a slice of an array of long values to this byte sink.
|
ByteSink |
putShortArray(short[] source,
int offset,
int length)
Writes a slice of an array of short values to this byte sink.
|
protected ByteBuffer |
requestAdditionalBuffer(int requiredSpaceInBytes)
This method is called if the space remaining in the available
byte-buffers is not sufficient for a put operation.
|
String |
toString()
Returns a string representation of this byte sink.
|
putByte, putByteArray, putDouble, putDoubleArray, putFloat, putFloatArray, putInt, putIntArray, putLong, putLongArray, putShort, putShortArray
public ByteBufferByteSink()
BufferOverflowException
until at least one usable buffer is added to this sink.public ByteBufferByteSink addBuffer(ByteBuffer byteBuffer)
byteBuffer
- byte buffer that shall be used to store data.IllegalArgumentException
- if the byte buffer's position is not zero (there is already
data in the byte buffer). The byte buffer is not added to the
list of available buffers.public ByteBufferByteSink addBuffers(ByteBuffer[] byteBuffers)
byteBuffers
- byte buffers that shall be used to store data.IllegalArgumentException
- if one of the byte buffers' positions is not zero (there is
already data in the byte buffer). The byte buffers are not
added to the list of available buffers.public ByteBufferByteSink addBuffers(Iterable<? extends ByteBuffer> byteBuffers)
byteBuffers
- byte buffers that shall be used to store data.IllegalArgumentException
- if one of the byte buffers' positions is not zero (there is
already data in the byte buffer). The byte buffers are not
added to the list of available buffers.public void addBufferFirst(ByteBuffer byteBuffer)
Adds a byte buffer to the head of the list of available byte buffers.
This method may only be called when no atomic put operation is in
progress and no data is in the byte sink (no data has been written since
the last call to getWrittenData()
). The byte buffer that is
added may contain data. This data is treated like it had been written to
this byte sink. In particular, a call too
getWrittenDataSizeInBytes()
right after adding the buffer will
return a number equal to the buffer's position.
This method can be used to add a partially filled buffer that has been
removed using getWrittenData()
but could not be passed on (e.g.
because the channel it was supposed to be written to did not accept more
data). It is important that the buffer only contains data that should be
used, because all data from zero up to its current position is going to
be used. If the buffer contains data that should not be used, it should
first be prepared, e.g. by calling its compact
method.
byteBuffer
- byte buffer that should be added to the list of available
buffers before all other buffers (never null
).
The buffer may contain data, which is implicitly added to this
byte sink.IllegalStateException
- if an atomic put operation is in progress or this byte sink
already contains data.public ByteBuffer[] getWrittenData()
Channel
.IllegalStateException
- if an atomic put operation is in progress.public long getWrittenDataSizeInBytes()
getWrittenData()
will return byte buffers that in total contain
this number of bytes.protected ByteBuffer requestAdditionalBuffer(int requiredSpaceInBytes)
null
in this case the write operation will fail
with an BufferOverflowException
. The default implementation
always returns null
, limiting the amount of data that can be
written to the space in the byte buffers that have been added to this
byte sink.requiredSpaceInBytes
- number of bytes that are needed to complete the put operation.
This information can be used to decide on the size that the
buffer should have. However, the returned buffer may be larger
or smaller than this size. If it is larger, the remaining
space will be used for future put operations. If it is
smaller, this method will be called again, requesting another
buffer.null
no additional
buffer is provided and the put operation in progress will fail
with an BufferOverflowException
. The default
implementation always returns null
.protected void dataWritten()
Called when data has been committed to the byte buffers backing this byte
sink. This method is called every time an atomic put operation finishes
successfully (or a simple put operation outside an atomic put finishes).
It is called after the data has been committed, so a call to
getWrittenData()
returns the data that has just been written.
Derived classes can override this method when they want to be notified each time data is written. The base implementation is empty, so this method does not have to be called by overriding implementations.
public <T> T atomicPut(ByteSink.AtomicPutOperation<? extends T> atomicPutOperation)
ByteSink
ByteSink.AtomicPutOperation.put()
method of atomicPutOperation
throws an exception) all data
written within the transaction is discarded. This method will throw any
exception thrown by ByteSink.AtomicPutOperation.put()
. Atomic put
operations may be nested (see ByteSink.AtomicPutOperation.put()
for
details). Despite its name, this method should not be considered to be
thread-safe.T
- type of the return value of the atomic operation.atomicPutOperation
- put operation that shall be performed atomically.ByteSink.AtomicPutOperation.put()
.public ByteBufferByteSink putByteArray(byte[] source, int offset, int length)
ByteSink
source
- array of bytes that should be partially written to this byte
sink.offset
- offset into source
. Data will be read from the
array starting at this index.length
- number of bytes to be written.public ByteSink putDoubleArray(double[] source, int offset, int length)
ByteSink
putDoubleArray
in interface ByteSink
putDoubleArray
in class AbstractByteSink
source
- array of double values that should be partially written to
this byte sink.offset
- offset into source
. Data will be read from the
array starting at this index.length
- number of values to be written.public ByteSink putFloatArray(float[] source, int offset, int length)
ByteSink
putFloatArray
in interface ByteSink
putFloatArray
in class AbstractByteSink
source
- array of float values that should be partially written to this
byte sink.offset
- offset into source
. Data will be read from the
array starting at this index.length
- number of values to be written.public ByteSink putIntArray(int[] source, int offset, int length)
ByteSink
putIntArray
in interface ByteSink
putIntArray
in class AbstractByteSink
source
- array of int values that should be partially written to this
byte sink.offset
- offset into source
. Data will be read from the
array starting at this index.length
- number of values to be written.public ByteSink putShortArray(short[] source, int offset, int length)
ByteSink
putShortArray
in interface ByteSink
putShortArray
in class AbstractByteSink
source
- array of short values that should be partially written to this
byte sink.offset
- offset into source
. Data will be read from the
array starting at this index.length
- number of values to be written.public ByteSink putLongArray(long[] source, int offset, int length)
ByteSink
putLongArray
in interface ByteSink
putLongArray
in class AbstractByteSink
source
- array of long values that should be partially written to this
byte sink.offset
- offset into source
. Data will be read from the
array starting at this index.length
- number of values to be written.public String toString()
Copyright © 2014–2016 aquenos GmbH. All rights reserved.