Search in sources :

Example 1 with BufferResponse

use of org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse in project flink by apache.

the class PartitionRequestClientHandlerTest method createBufferResponse.

/**
	 * Returns a deserialized buffer message as it would be received during runtime.
	 */
private BufferResponse createBufferResponse(Buffer buffer, int sequenceNumber, InputChannelID receivingChannelId) throws IOException {
    // Mock buffer to serialize
    BufferResponse resp = new BufferResponse(buffer, sequenceNumber, receivingChannelId);
    ByteBuf serialized = resp.write(UnpooledByteBufAllocator.DEFAULT);
    // Skip general header bytes
    serialized.readBytes(NettyMessage.HEADER_LENGTH);
    BufferResponse deserialized = new BufferResponse();
    // Deserialize the bytes again. We have to go this way, because we only partly deserialize
    // the header of the response and wait for a buffer from the buffer pool to copy the payload
    // data into.
    deserialized.readFrom(serialized);
    return deserialized;
}
Also used : BufferResponse(org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse) ByteBuf(io.netty.buffer.ByteBuf)

Example 2 with BufferResponse

use of org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse in project flink by apache.

the class PartitionRequestClientHandlerTest method testReceiveEmptyBuffer.

/**
	 * Tests a fix for FLINK-1761.
	 *
	 * <p> FLINK-1761 discovered an IndexOutOfBoundsException, when receiving buffers of size 0.
	 */
@Test
public void testReceiveEmptyBuffer() throws Exception {
    // Minimal mock of a remote input channel
    final BufferProvider bufferProvider = mock(BufferProvider.class);
    when(bufferProvider.requestBuffer()).thenReturn(TestBufferFactory.createBuffer());
    final RemoteInputChannel inputChannel = mock(RemoteInputChannel.class);
    when(inputChannel.getInputChannelId()).thenReturn(new InputChannelID());
    when(inputChannel.getBufferProvider()).thenReturn(bufferProvider);
    // An empty buffer of size 0
    final Buffer emptyBuffer = TestBufferFactory.createBuffer();
    emptyBuffer.setSize(0);
    final BufferResponse receivedBuffer = createBufferResponse(emptyBuffer, 0, inputChannel.getInputChannelId());
    final PartitionRequestClientHandler client = new PartitionRequestClientHandler();
    client.addInputChannel(inputChannel);
    // Read the empty buffer
    client.channelRead(mock(ChannelHandlerContext.class), receivedBuffer);
    // This should not throw an exception
    verify(inputChannel, never()).onError(any(Throwable.class));
}
Also used : Buffer(org.apache.flink.runtime.io.network.buffer.Buffer) InputChannelID(org.apache.flink.runtime.io.network.partition.consumer.InputChannelID) BufferProvider(org.apache.flink.runtime.io.network.buffer.BufferProvider) BufferResponse(org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) RemoteInputChannel(org.apache.flink.runtime.io.network.partition.consumer.RemoteInputChannel) Test(org.junit.Test)

Example 3 with BufferResponse

use of org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse in project flink by apache.

the class PartitionRequestQueue method writeAndFlushNextMessageIfPossible.

private void writeAndFlushNextMessageIfPossible(final Channel channel) throws IOException {
    if (fatalError) {
        return;
    }
    // The logic here is very similar to the combined input gate and local
    // input channel logic. You can think of this class acting as the input
    // gate and the consumed views as the local input channels.
    BufferAndAvailability next = null;
    try {
        if (channel.isWritable()) {
            while (true) {
                SequenceNumberingViewReader reader = nonEmptyReader.poll();
                // of the write callbacks that are executed after each write.
                if (reader == null) {
                    return;
                }
                next = reader.getNextBuffer();
                if (next == null) {
                    if (reader.isReleased()) {
                        markAsReleased(reader.getReceiverId());
                        Throwable cause = reader.getFailureCause();
                        if (cause != null) {
                            ErrorResponse msg = new ErrorResponse(new ProducerFailedException(cause), reader.getReceiverId());
                            ctx.writeAndFlush(msg);
                        }
                    } else {
                        IllegalStateException err = new IllegalStateException("Bug in Netty consumer logic: reader queue got notified by partition " + "about available data, but none was available.");
                        handleException(ctx.channel(), err);
                        return;
                    }
                } else {
                    // "non-empty" notification will come for that reader from the queue.
                    if (next.moreAvailable()) {
                        nonEmptyReader.add(reader);
                    }
                    BufferResponse msg = new BufferResponse(next.buffer(), reader.getSequenceNumber(), reader.getReceiverId());
                    if (isEndOfPartitionEvent(next.buffer())) {
                        reader.notifySubpartitionConsumed();
                        reader.releaseAllResources();
                        markAsReleased(reader.getReceiverId());
                    }
                    // Write and flush and wait until this is done before
                    // trying to continue with the next buffer.
                    channel.writeAndFlush(msg).addListener(writeListener);
                    return;
                }
            }
        }
    } catch (Throwable t) {
        if (next != null) {
            next.buffer().recycle();
        }
        throw new IOException(t.getMessage(), t);
    }
}
Also used : BufferResponse(org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse) IOException(java.io.IOException) BufferAndAvailability(org.apache.flink.runtime.io.network.partition.consumer.InputChannel.BufferAndAvailability) ProducerFailedException(org.apache.flink.runtime.io.network.partition.ProducerFailedException) ErrorResponse(org.apache.flink.runtime.io.network.netty.NettyMessage.ErrorResponse)

Example 4 with BufferResponse

use of org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse in project flink by apache.

the class PartitionRequestClientHandlerTest method testAutoReadAfterUnsuccessfulStagedMessage.

/**
	 * Tests that an unsuccessful message decode call for a staged message
	 * does not leave the channel with auto read set to false.
	 */
@Test
@SuppressWarnings("unchecked")
public void testAutoReadAfterUnsuccessfulStagedMessage() throws Exception {
    PartitionRequestClientHandler handler = new PartitionRequestClientHandler();
    EmbeddedChannel channel = new EmbeddedChannel(handler);
    final AtomicReference<EventListener<Buffer>> listener = new AtomicReference<>();
    BufferProvider bufferProvider = mock(BufferProvider.class);
    when(bufferProvider.addListener(any(EventListener.class))).thenAnswer(new Answer<Boolean>() {

        @Override
        @SuppressWarnings("unchecked")
        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            listener.set((EventListener<Buffer>) invocation.getArguments()[0]);
            return true;
        }
    });
    when(bufferProvider.requestBuffer()).thenReturn(null);
    InputChannelID channelId = new InputChannelID(0, 0);
    RemoteInputChannel inputChannel = mock(RemoteInputChannel.class);
    when(inputChannel.getInputChannelId()).thenReturn(channelId);
    // The 3rd staged msg has a null buffer provider
    when(inputChannel.getBufferProvider()).thenReturn(bufferProvider, bufferProvider, null);
    handler.addInputChannel(inputChannel);
    BufferResponse msg = createBufferResponse(createBuffer(true), 0, channelId);
    // Write 1st buffer msg. No buffer is available, therefore the buffer
    // should be staged and auto read should be set to false.
    assertTrue(channel.config().isAutoRead());
    channel.writeInbound(msg);
    // No buffer available, auto read false
    assertFalse(channel.config().isAutoRead());
    // Write more buffers... all staged.
    msg = createBufferResponse(createBuffer(true), 1, channelId);
    channel.writeInbound(msg);
    msg = createBufferResponse(createBuffer(true), 2, channelId);
    channel.writeInbound(msg);
    // Notify about buffer => handle 1st msg
    Buffer availableBuffer = createBuffer(false);
    listener.get().onEvent(availableBuffer);
    // Start processing of staged buffers (in run pending tasks). Make
    // sure that the buffer provider acts like it's destroyed.
    when(bufferProvider.addListener(any(EventListener.class))).thenReturn(false);
    when(bufferProvider.isDestroyed()).thenReturn(true);
    // Execute all tasks that are scheduled in the event loop. Further
    // eventLoop().execute() calls are directly executed, if they are
    // called in the scope of this call.
    channel.runPendingTasks();
    assertTrue(channel.config().isAutoRead());
}
Also used : Buffer(org.apache.flink.runtime.io.network.buffer.Buffer) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) AtomicReference(java.util.concurrent.atomic.AtomicReference) RemoteInputChannel(org.apache.flink.runtime.io.network.partition.consumer.RemoteInputChannel) InvocationOnMock(org.mockito.invocation.InvocationOnMock) InputChannelID(org.apache.flink.runtime.io.network.partition.consumer.InputChannelID) BufferProvider(org.apache.flink.runtime.io.network.buffer.BufferProvider) BufferResponse(org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse) EventListener(org.apache.flink.runtime.util.event.EventListener) Test(org.junit.Test)

Example 5 with BufferResponse

use of org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse in project flink by apache.

the class PartitionRequestClientHandlerTest method testReleaseInputChannelDuringDecode.

/**
	 * Tests a fix for FLINK-1627.
	 *
	 * <p> FLINK-1627 discovered a race condition, which could lead to an infinite loop when a
	 * receiver was cancelled during a certain time of decoding a message. The test reproduces the
	 * input, which lead to the infinite loop: when the handler gets a reference to the buffer
	 * provider of the receiving input channel, but the respective input channel is released (and
	 * the corresponding buffer provider destroyed), the handler did not notice this.
	 *
	 * @see <a href="https://issues.apache.org/jira/browse/FLINK-1627">FLINK-1627</a>
	 */
@Test(timeout = 60000)
@SuppressWarnings("unchecked")
public void testReleaseInputChannelDuringDecode() throws Exception {
    // Mocks an input channel in a state as it was released during a decode.
    final BufferProvider bufferProvider = mock(BufferProvider.class);
    when(bufferProvider.requestBuffer()).thenReturn(null);
    when(bufferProvider.isDestroyed()).thenReturn(true);
    when(bufferProvider.addListener(any(EventListener.class))).thenReturn(false);
    final RemoteInputChannel inputChannel = mock(RemoteInputChannel.class);
    when(inputChannel.getInputChannelId()).thenReturn(new InputChannelID());
    when(inputChannel.getBufferProvider()).thenReturn(bufferProvider);
    final BufferResponse ReceivedBuffer = createBufferResponse(TestBufferFactory.createBuffer(), 0, inputChannel.getInputChannelId());
    final PartitionRequestClientHandler client = new PartitionRequestClientHandler();
    client.addInputChannel(inputChannel);
    client.channelRead(mock(ChannelHandlerContext.class), ReceivedBuffer);
}
Also used : InputChannelID(org.apache.flink.runtime.io.network.partition.consumer.InputChannelID) BufferProvider(org.apache.flink.runtime.io.network.buffer.BufferProvider) BufferResponse(org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) EventListener(org.apache.flink.runtime.util.event.EventListener) RemoteInputChannel(org.apache.flink.runtime.io.network.partition.consumer.RemoteInputChannel) Test(org.junit.Test)

Aggregations

BufferResponse (org.apache.flink.runtime.io.network.netty.NettyMessage.BufferResponse)5 BufferProvider (org.apache.flink.runtime.io.network.buffer.BufferProvider)3 InputChannelID (org.apache.flink.runtime.io.network.partition.consumer.InputChannelID)3 RemoteInputChannel (org.apache.flink.runtime.io.network.partition.consumer.RemoteInputChannel)3 Test (org.junit.Test)3 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 Buffer (org.apache.flink.runtime.io.network.buffer.Buffer)2 EventListener (org.apache.flink.runtime.util.event.EventListener)2 ByteBuf (io.netty.buffer.ByteBuf)1 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)1 IOException (java.io.IOException)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 ErrorResponse (org.apache.flink.runtime.io.network.netty.NettyMessage.ErrorResponse)1 ProducerFailedException (org.apache.flink.runtime.io.network.partition.ProducerFailedException)1 BufferAndAvailability (org.apache.flink.runtime.io.network.partition.consumer.InputChannel.BufferAndAvailability)1 InvocationOnMock (org.mockito.invocation.InvocationOnMock)1