View Javadoc
1   /*
2    * Copyright 2015 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    *   https://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.netty5.channel;
17  
18  import io.netty5.buffer.api.Buffer;
19  import io.netty5.buffer.api.BufferAllocator;
20  
21  import java.util.function.Predicate;
22  
23  import static io.netty5.util.internal.ObjectUtil.checkPositive;
24  
25  /**
26   * Default implementation of {@link MaxMessagesRecvBufferAllocator} which respects {@link ChannelOption#AUTO_READ}
27   * and also prevents overflow.
28   */
29  public abstract class DefaultMaxMessagesRecvBufferAllocator implements MaxMessagesRecvBufferAllocator {
30      private final boolean ignoreBytesRead;
31      private volatile int maxMessagesPerRead;
32      private volatile boolean respectMaybeMoreData = true;
33  
34      protected DefaultMaxMessagesRecvBufferAllocator() {
35          this(1);
36      }
37  
38      protected DefaultMaxMessagesRecvBufferAllocator(int maxMessagesPerRead) {
39          this(maxMessagesPerRead, false);
40      }
41  
42      DefaultMaxMessagesRecvBufferAllocator(int maxMessagesPerRead, boolean ignoreBytesRead) {
43          this.ignoreBytesRead = ignoreBytesRead;
44          maxMessagesPerRead(maxMessagesPerRead);
45      }
46  
47      @Override
48      public int maxMessagesPerRead() {
49          return maxMessagesPerRead;
50      }
51  
52      @Override
53      public MaxMessagesRecvBufferAllocator maxMessagesPerRead(int maxMessagesPerRead) {
54          checkPositive(maxMessagesPerRead, "maxMessagesPerRead");
55          this.maxMessagesPerRead = maxMessagesPerRead;
56          return this;
57      }
58  
59      /**
60       * Focuses on enforcing the maximum messages per read condition for {@link #continueReading(boolean)}.
61       */
62      public abstract class MaxMessageHandle implements Handle {
63          private int maxMessagePerRead;
64          private int totalMessages;
65          private int totalBytesRead;
66          private int attemptedBytesRead;
67          private int lastBytesRead;
68  
69          private final Predicate<Handle> defaultMaybeMoreSupplier = h -> attemptedBytesRead == lastBytesRead;
70  
71          /**
72           * Only {@link ChannelOption#MAX_MESSAGES_PER_READ} is used.
73           */
74          @Override
75          public void reset() {
76              maxMessagePerRead = maxMessagesPerRead();
77              totalMessages = totalBytesRead = 0;
78          }
79  
80          @Override
81          public Buffer allocate(BufferAllocator alloc) {
82              return alloc.allocate(guess());
83          }
84  
85          @Override
86          public final void incMessagesRead(int amt) {
87              totalMessages += amt;
88          }
89  
90          @Override
91          public void lastBytesRead(int bytes) {
92              lastBytesRead = bytes;
93              if (bytes > 0) {
94                  totalBytesRead += bytes;
95              }
96          }
97  
98          @Override
99          public final int lastBytesRead() {
100             return lastBytesRead;
101         }
102 
103         @Override
104         public boolean continueReading(boolean autoRead) {
105             return continueReading(autoRead, defaultMaybeMoreSupplier);
106         }
107 
108         @Override
109         public boolean continueReading(boolean autoRead, Predicate<Handle> maybeMoreDataSupplier) {
110             return autoRead && maybeMoreDataSupplier.test(this) &&
111                    totalMessages < maxMessagePerRead && (ignoreBytesRead || totalBytesRead > 0);
112         }
113 
114         @Override
115         public void readComplete() {
116         }
117 
118         @Override
119         public int attemptedBytesRead() {
120             return attemptedBytesRead;
121         }
122 
123         @Override
124         public void attemptedBytesRead(int bytes) {
125             attemptedBytesRead = bytes;
126         }
127 
128         protected final int totalBytesRead() {
129             return totalBytesRead < 0 ? Integer.MAX_VALUE : totalBytesRead;
130         }
131     }
132 }