/** * Requests buffers from the buffer provider and triggers asynchronous read requests to fill them. * * <p>The number of requested buffers/triggered I/O read requests per call depends on the * configured size of batch reads. */ private void readNextBatchAsync() throws IOException { // This does not need to be fully synchronized with actually reaching EOF as long as // we eventually notice it. In the worst case, we trigger some discarded reads and // notice it when the buffers are returned. // // We only trigger reads if the current batch size is 0. if (hasReachedEndOfFile || currentBatchSize.get() != 0) { return; } // Number of successful buffer requests or callback registrations. The call back will // trigger the read as soon as a buffer becomes available again. int i = 0; while (i < readBatchSize) { final Buffer buffer = bufferProvider.requestBuffer(); if (buffer == null) { // Listen for buffer availability. currentBatchSize.incrementAndGet(); if (bufferProvider.addListener(bufferAvailabilityListener)) { i++; } else if (bufferProvider.isDestroyed()) { currentBatchSize.decrementAndGet(); return; } else { // Buffer available again currentBatchSize.decrementAndGet(); } } else { currentBatchSize.incrementAndGet(); asyncFileReader.readInto(buffer); } } }
private boolean waitForBuffer( BufferProvider bufferProvider, NettyMessage.BufferResponse bufferResponse) { stagedBufferResponse = bufferResponse; if (bufferProvider.addListener(this)) { if (ctx.channel().config().isAutoRead()) { ctx.channel().config().setAutoRead(false); } return true; } else { stagedBufferResponse = null; return false; } }
private boolean decodeBufferOrEvent( RemoteInputChannel inputChannel, NettyMessage.BufferResponse bufferOrEvent) throws Throwable { boolean releaseNettyBuffer = true; try { if (bufferOrEvent.isBuffer()) { // ---- Buffer ------------------------------------------------ // Early return for empty buffers. Otherwise Netty's readBytes() throws an // IndexOutOfBoundsException. if (bufferOrEvent.getSize() == 0) { inputChannel.onEmptyBuffer(bufferOrEvent.sequenceNumber); return true; } BufferProvider bufferProvider = inputChannel.getBufferProvider(); if (bufferProvider == null) { cancelRequestFor(bufferOrEvent.receiverId); return false; // receiver has been cancelled/failed } while (true) { Buffer buffer = bufferProvider.requestBuffer(); if (buffer != null) { buffer.setSize(bufferOrEvent.getSize()); bufferOrEvent.getNettyBuffer().readBytes(buffer.getNioBuffer()); inputChannel.onBuffer(buffer, bufferOrEvent.sequenceNumber); return true; } else if (bufferListener.waitForBuffer(bufferProvider, bufferOrEvent)) { releaseNettyBuffer = false; return false; } else if (bufferProvider.isDestroyed()) { return false; } } } else { // ---- Event ------------------------------------------------- // TODO We can just keep the serialized data in the Netty buffer and release it later at the // reader byte[] byteArray = new byte[bufferOrEvent.getSize()]; bufferOrEvent.getNettyBuffer().readBytes(byteArray); Buffer buffer = new Buffer(new MemorySegment(byteArray), FreeingBufferRecycler.INSTANCE, false); inputChannel.onBuffer(buffer, bufferOrEvent.sequenceNumber); return true; } } finally { if (releaseNettyBuffer) { bufferOrEvent.releaseBuffer(); } } }