/** * Continues the decoding of a staged buffer after a buffer has become available again. * * <p>This task is executed by the network I/O thread. */ @Override public void run() { boolean success = false; Buffer buffer = null; try { if ((buffer = availableBuffer.getAndSet(null)) == null) { throw new IllegalStateException("Running buffer availability task w/o a buffer."); } buffer.setSize(stagedBufferResponse.getSize()); stagedBufferResponse.getNettyBuffer().readBytes(buffer.getNioBuffer()); stagedBufferResponse.releaseBuffer(); RemoteInputChannel inputChannel = inputChannels.get(stagedBufferResponse.receiverId); if (inputChannel != null) { inputChannel.onBuffer(buffer, stagedBufferResponse.sequenceNumber); success = true; } else { cancelRequestFor(stagedBufferResponse.receiverId); } stagedBufferResponse = null; if (stagedMessages.isEmpty()) { ctx.channel().config().setAutoRead(true); ctx.channel().read(); } else { ctx.channel().eventLoop().execute(stagedMessagesHandler); } } catch (Throwable t) { notifyAllChannelsOfErrorAndClose(t); } finally { if (!success) { if (buffer != null) { buffer.recycle(); } } } }
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(); } } }