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 }
105