Home / Class/ FlowControlledData Class — netty Architecture

FlowControlledData Class — netty Architecture

Architecture documentation for the FlowControlledData class in DefaultHttp2ConnectionEncoder.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  3f967aaa_cd4e_4486_0912_7a9f57cfa847["FlowControlledData"]
  6ee2373c_9254_f504_1a3e_e58265550287["DefaultHttp2ConnectionEncoder.java"]
  3f967aaa_cd4e_4486_0912_7a9f57cfa847 -->|defined in| 6ee2373c_9254_f504_1a3e_e58265550287
  192a7df9_e57e_16a9_360a_44ba8f82d3d9["FlowControlledData()"]
  3f967aaa_cd4e_4486_0912_7a9f57cfa847 -->|method| 192a7df9_e57e_16a9_360a_44ba8f82d3d9
  056b4816_0b1f_9d07_6136_4efe950e0c59["size()"]
  3f967aaa_cd4e_4486_0912_7a9f57cfa847 -->|method| 056b4816_0b1f_9d07_6136_4efe950e0c59
  477efeff_1ae4_5595_d4ec_eae3cb151ba9["error()"]
  3f967aaa_cd4e_4486_0912_7a9f57cfa847 -->|method| 477efeff_1ae4_5595_d4ec_eae3cb151ba9
  00bd83d0_dcec_5387_7a17_1c0f317ff485["write()"]
  3f967aaa_cd4e_4486_0912_7a9f57cfa847 -->|method| 00bd83d0_dcec_5387_7a17_1c0f317ff485
  acd09d1f_be33_102c_8dd0_79251a29cf5f["merge()"]
  3f967aaa_cd4e_4486_0912_7a9f57cfa847 -->|method| acd09d1f_be33_102c_8dd0_79251a29cf5f

Relationship Graph

Source Code

codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java lines 440–525

    private final class FlowControlledData extends FlowControlledBase {
        private final CoalescingBufferQueue queue;
        private int dataSize;

        FlowControlledData(Http2Stream stream, ByteBuf buf, int padding, boolean endOfStream,
                                   ChannelPromise promise) {
            super(stream, padding, endOfStream, promise);
            queue = new CoalescingBufferQueue(promise.channel());
            queue.add(buf, promise);
            dataSize = queue.readableBytes();
        }

        @Override
        public int size() {
            return dataSize + padding;
        }

        @Override
        public void error(ChannelHandlerContext ctx, Throwable cause) {
            queue.releaseAndFailAll(cause);
            // Don't update dataSize because we need to ensure the size() method returns a consistent size even after
            // error so we don't invalidate flow control when returning bytes to flow control.
            //
            // That said we will set dataSize and padding to 0 in the write(...) method if we cleared the queue
            // because of an error.
            lifecycleManager.onError(ctx, true, cause);
        }

        @Override
        public void write(ChannelHandlerContext ctx, int allowedBytes) {
            int queuedData = queue.readableBytes();
            if (!endOfStream) {
                if (queuedData == 0) {
                    if (queue.isEmpty()) {
                        // When the queue is empty it means we did clear it because of an error(...) call
                        // (as otherwise we will have at least 1 entry in there), which will happen either when called
                        // explicit or when the write itself fails. In this case just set dataSize and padding to 0
                        // which will signal back that the whole frame was consumed.
                        //
                        // See https://github.com/netty/netty/issues/8707.
                        padding = dataSize = 0;
                    } else {
                        // There's no need to write any data frames because there are only empty data frames in the
                        // queue and it is not end of stream yet. Just complete their promises by getting the buffer
                        // corresponding to 0 bytes and writing it to the channel (to preserve notification order).
                        ChannelPromise writePromise = ctx.newPromise().addListener(this);
                        ctx.write(queue.remove(0, writePromise), writePromise);
                    }
                    return;
                }

                if (allowedBytes == 0) {
                    return;
                }
            }

            // Determine how much data to write.
            int writableData = min(queuedData, allowedBytes);
            ChannelPromise writePromise = ctx.newPromise().addListener(this);
            ByteBuf toWrite = queue.remove(writableData, writePromise);
            dataSize = queue.readableBytes();

            // Determine how much padding to write.
            int writablePadding = min(allowedBytes - writableData, padding);
            padding -= writablePadding;

            // Write the frame(s).
            frameWriter().writeData(ctx, stream.id(), toWrite, writablePadding,
                    endOfStream && size() == 0, writePromise);
        }

        @Override
        public boolean merge(ChannelHandlerContext ctx, Http2RemoteFlowController.FlowControlled next) {
            FlowControlledData nextData;
            if (FlowControlledData.class != next.getClass() ||
                MAX_VALUE - (nextData = (FlowControlledData) next).size() < size()) {
                return false;
            }
            nextData.queue.copyTo(queue);
            dataSize = queue.readableBytes();
            // Given that we're merging data into a frame it doesn't really make sense to accumulate padding.

Frequently Asked Questions

What is the FlowControlledData class?
FlowControlledData is a class in the netty codebase, defined in codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java.
Where is FlowControlledData defined?
FlowControlledData is defined in codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java at line 440.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free