View Javadoc
1   /*
2    * Copyright 2017 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel;
17  
18  import io.netty.util.internal.ObjectUtil;
19  
20  abstract class PendingBytesTracker implements MessageSizeEstimator.Handle {
21      private final MessageSizeEstimator.Handle estimatorHandle;
22  
23      private PendingBytesTracker(MessageSizeEstimator.Handle estimatorHandle) {
24          this.estimatorHandle = ObjectUtil.checkNotNull(estimatorHandle, "estimatorHandle");
25      }
26  
27      @Override
28      public final int size(Object msg) {
29          return estimatorHandle.size(msg);
30      }
31  
32      public abstract void incrementPendingOutboundBytes(long bytes);
33      public abstract void decrementPendingOutboundBytes(long bytes);
34  
35      static PendingBytesTracker newTracker(Channel channel) {
36          if (channel.pipeline() instanceof DefaultChannelPipeline) {
37              return new DefaultChannelPipelinePendingBytesTracker((DefaultChannelPipeline) channel.pipeline());
38          } else {
39              ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();
40              MessageSizeEstimator.Handle handle = channel.config().getMessageSizeEstimator().newHandle();
41              // We need to guard against null as channel.unsafe().outboundBuffer() may returned null
42              // if the channel was already closed when constructing the PendingBytesTracker.
43              // See https://github.com/netty/netty/issues/3967
44              return buffer == null ?
45                      new NoopPendingBytesTracker(handle) : new ChannelOutboundBufferPendingBytesTracker(buffer, handle);
46          }
47      }
48  
49      private static final class DefaultChannelPipelinePendingBytesTracker extends PendingBytesTracker {
50          private final DefaultChannelPipeline pipeline;
51  
52          DefaultChannelPipelinePendingBytesTracker(DefaultChannelPipeline pipeline) {
53              super(pipeline.estimatorHandle());
54              this.pipeline = pipeline;
55          }
56  
57          @Override
58          public void incrementPendingOutboundBytes(long bytes) {
59              pipeline.incrementPendingOutboundBytes(bytes);
60          }
61  
62          @Override
63          public void decrementPendingOutboundBytes(long bytes) {
64              pipeline.decrementPendingOutboundBytes(bytes);
65          }
66      }
67  
68      private static final class ChannelOutboundBufferPendingBytesTracker extends PendingBytesTracker {
69          private final ChannelOutboundBuffer buffer;
70  
71          ChannelOutboundBufferPendingBytesTracker(
72                  ChannelOutboundBuffer buffer, MessageSizeEstimator.Handle estimatorHandle) {
73              super(estimatorHandle);
74              this.buffer = buffer;
75          }
76  
77          @Override
78          public void incrementPendingOutboundBytes(long bytes) {
79              buffer.incrementPendingOutboundBytes(bytes);
80          }
81  
82          @Override
83          public void decrementPendingOutboundBytes(long bytes) {
84              buffer.decrementPendingOutboundBytes(bytes);
85          }
86      }
87  
88      private static final class NoopPendingBytesTracker extends PendingBytesTracker {
89  
90          NoopPendingBytesTracker(MessageSizeEstimator.Handle estimatorHandle) {
91              super(estimatorHandle);
92          }
93  
94          @Override
95          public void incrementPendingOutboundBytes(long bytes) {
96              // Noop
97          }
98  
99          @Override
100         public void decrementPendingOutboundBytes(long bytes) {
101             // Noop
102         }
103     }
104 }