use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.
the class BlockingSenderImpl method writeBuffer.
private boolean writeBuffer(final ByteBuffer[] buffers, final IoCallback callback) {
if (outputStream instanceof BufferWritableOutputStream) {
//fast path, if the stream can take a buffer directly just write to it
try {
((BufferWritableOutputStream) outputStream).write(buffers);
return true;
} catch (IOException e) {
callback.onException(exchange, this, e);
return false;
}
}
for (ByteBuffer buffer : buffers) {
if (buffer.hasArray()) {
try {
outputStream.write(buffer.array(), buffer.arrayOffset(), buffer.remaining());
} catch (IOException e) {
callback.onException(exchange, this, e);
return false;
}
} else {
try (PooledByteBuffer pooled = exchange.getConnection().getByteBufferPool().getArrayBackedPool().allocate()) {
while (buffer.hasRemaining()) {
int toRead = Math.min(buffer.remaining(), pooled.getBuffer().remaining());
buffer.get(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), toRead);
try {
outputStream.write(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), toRead);
} catch (IOException e) {
callback.onException(exchange, this, e);
return false;
}
}
}
}
}
return true;
}
use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.
the class UndertowOutputStream method write.
/**
* {@inheritDoc}
*/
public void write(final byte[] b, final int off, final int len) throws IOException {
if (len < 1) {
return;
}
if (Thread.currentThread() == exchange.getIoThread()) {
throw UndertowMessages.MESSAGES.blockingIoFromIOThread();
}
if (anyAreSet(state, FLAG_CLOSED)) {
throw UndertowMessages.MESSAGES.streamIsClosed();
}
//if this is the last of the content
ByteBuffer buffer = buffer();
if (len == contentLength - written || buffer.remaining() < len) {
if (buffer.remaining() < len) {
//so what we have will not fit.
//We allocate multiple buffers up to MAX_BUFFERS_TO_ALLOCATE
//and put it in them
//if it still dopes not fit we loop, re-using these buffers
StreamSinkChannel channel = this.channel;
if (channel == null) {
this.channel = channel = exchange.getResponseChannel();
}
final ByteBufferPool bufferPool = exchange.getConnection().getByteBufferPool();
ByteBuffer[] buffers = new ByteBuffer[MAX_BUFFERS_TO_ALLOCATE + 1];
PooledByteBuffer[] pooledBuffers = new PooledByteBuffer[MAX_BUFFERS_TO_ALLOCATE];
try {
buffers[0] = buffer;
int bytesWritten = 0;
int rem = buffer.remaining();
buffer.put(b, bytesWritten + off, rem);
buffer.flip();
bytesWritten += rem;
int bufferCount = 1;
for (int i = 0; i < MAX_BUFFERS_TO_ALLOCATE; ++i) {
PooledByteBuffer pooled = bufferPool.allocate();
pooledBuffers[bufferCount - 1] = pooled;
buffers[bufferCount++] = pooled.getBuffer();
ByteBuffer cb = pooled.getBuffer();
int toWrite = len - bytesWritten;
if (toWrite > cb.remaining()) {
rem = cb.remaining();
cb.put(b, bytesWritten + off, rem);
cb.flip();
bytesWritten += rem;
} else {
cb.put(b, bytesWritten + off, len - bytesWritten);
bytesWritten = len;
cb.flip();
break;
}
}
Channels.writeBlocking(channel, buffers, 0, bufferCount);
while (bytesWritten < len) {
//ok, it did not fit, loop and loop and loop until it is done
bufferCount = 0;
for (int i = 0; i < MAX_BUFFERS_TO_ALLOCATE + 1; ++i) {
ByteBuffer cb = buffers[i];
cb.clear();
bufferCount++;
int toWrite = len - bytesWritten;
if (toWrite > cb.remaining()) {
rem = cb.remaining();
cb.put(b, bytesWritten + off, rem);
cb.flip();
bytesWritten += rem;
} else {
cb.put(b, bytesWritten + off, len - bytesWritten);
bytesWritten = len;
cb.flip();
break;
}
}
Channels.writeBlocking(channel, buffers, 0, bufferCount);
}
buffer.clear();
} finally {
for (int i = 0; i < pooledBuffers.length; ++i) {
PooledByteBuffer p = pooledBuffers[i];
if (p == null) {
break;
}
p.close();
}
}
} else {
buffer.put(b, off, len);
if (buffer.remaining() == 0) {
writeBufferBlocking(false);
}
}
} else {
buffer.put(b, off, len);
if (buffer.remaining() == 0) {
writeBufferBlocking(false);
}
}
updateWritten(len);
}
use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.
the class Http2StreamSinkChannel method allocateAll.
protected PooledByteBuffer[] allocateAll(PooledByteBuffer[] allHeaderBuffers, PooledByteBuffer currentBuffer) {
PooledByteBuffer[] ret;
if (allHeaderBuffers == null) {
ret = new PooledByteBuffer[2];
ret[0] = currentBuffer;
ret[1] = getChannel().getBufferPool().allocate();
ByteBuffer newBuffer = ret[1].getBuffer();
if (newBuffer.remaining() > getChannel().getSendMaxFrameSize()) {
//make sure the buffers are not too large to go over the max frame size
newBuffer.limit(newBuffer.position() + getChannel().getSendMaxFrameSize());
}
} else {
ret = new PooledByteBuffer[allHeaderBuffers.length + 1];
System.arraycopy(allHeaderBuffers, 0, ret, 0, allHeaderBuffers.length);
ret[ret.length - 1] = getChannel().getBufferPool().allocate();
ByteBuffer newBuffer = ret[ret.length - 1].getBuffer();
if (newBuffer.remaining() > getChannel().getSendMaxFrameSize()) {
newBuffer.limit(newBuffer.position() + getChannel().getSendMaxFrameSize());
}
}
return ret;
}
use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.
the class AbstractFramedStreamSourceChannel method beforeRead.
private void beforeRead() throws IOException {
if (anyAreSet(state, STATE_STREAM_BROKEN)) {
throw UndertowMessages.MESSAGES.channelIsClosed();
}
if (data == null) {
synchronized (lock) {
FrameData pending = pendingFrameData.poll();
if (pending != null) {
PooledByteBuffer frameData = pending.getFrameData();
boolean hasData = true;
if (!frameData.getBuffer().hasRemaining()) {
frameData.close();
hasData = false;
}
if (pending.getFrameHeaderData() != null) {
this.frameDataRemaining = pending.getFrameHeaderData().getFrameLength();
handleHeaderData(pending.getFrameHeaderData());
}
if (hasData) {
this.frameDataRemaining = updateFrameDataRemaining(frameData, frameDataRemaining);
this.currentDataOriginalSize = frameData.getBuffer().remaining();
try {
this.data = processFrameData(frameData, frameDataRemaining - currentDataOriginalSize == 0);
} catch (Exception e) {
frameData.close();
UndertowLogger.REQUEST_IO_LOGGER.ioException(new IOException(e));
markStreamBroken();
}
}
}
}
}
}
use of io.undertow.connector.PooledByteBuffer in project undertow by undertow-io.
the class HttpReadListener method handleHttp2PriorKnowledge.
private void handleHttp2PriorKnowledge(final StreamConnection connection, final HttpServerConnection serverConnection, PooledByteBuffer readData) throws IOException {
final ConduitStreamSourceChannel request = connection.getSourceChannel();
byte[] data = new byte[PRI_EXPECTED.length];
final ByteBuffer buffer = ByteBuffer.wrap(data);
if (readData.getBuffer().hasRemaining()) {
while (readData.getBuffer().hasRemaining() && buffer.hasRemaining()) {
buffer.put(readData.getBuffer().get());
}
}
final PooledByteBuffer extraData;
if (readData.getBuffer().hasRemaining()) {
extraData = readData;
} else {
readData.close();
extraData = null;
}
if (!doHttp2PriRead(connection, buffer, serverConnection, extraData)) {
request.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
@Override
public void handleEvent(StreamSourceChannel channel) {
try {
doHttp2PriRead(connection, buffer, serverConnection, extraData);
} catch (IOException e) {
UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
IoUtils.safeClose(connection);
}
}
});
request.resumeReads();
}
}
Aggregations