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    *   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.epoll;
17  
18  import io.netty.buffer.ByteBufAllocator;
19  import io.netty.channel.ChannelException;
20  import io.netty.channel.ChannelOption;
21  import io.netty.channel.DefaultChannelConfig;
22  import io.netty.channel.MessageSizeEstimator;
23  import io.netty.channel.RecvByteBufAllocator;
24  import io.netty.channel.WriteBufferWaterMark;
25  
26  import java.io.IOException;
27  import java.util.Map;
28  
29  import static io.netty.channel.unix.Limits.SSIZE_MAX;
30  
31  public class EpollChannelConfig extends DefaultChannelConfig {
32      final AbstractEpollChannel channel;
33      private volatile long maxBytesPerGatheringWrite = SSIZE_MAX;
34  
35      EpollChannelConfig(AbstractEpollChannel channel) {
36          super(channel);
37          this.channel = channel;
38      }
39  
40      @Override
41      public Map<ChannelOption<?>, Object> getOptions() {
42          return getOptions(super.getOptions(), EpollChannelOption.EPOLL_MODE);
43      }
44  
45      @SuppressWarnings("unchecked")
46      @Override
47      public <T> T getOption(ChannelOption<T> option) {
48          if (option == EpollChannelOption.EPOLL_MODE) {
49              return (T) getEpollMode();
50          }
51          return super.getOption(option);
52      }
53  
54      @Override
55      public <T> boolean setOption(ChannelOption<T> option, T value) {
56          validate(option, value);
57          if (option == EpollChannelOption.EPOLL_MODE) {
58              setEpollMode((EpollMode) value);
59          } else {
60              return super.setOption(option, value);
61          }
62          return true;
63      }
64  
65      @Override
66      public EpollChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
67          super.setConnectTimeoutMillis(connectTimeoutMillis);
68          return this;
69      }
70  
71      @Override
72      @Deprecated
73      public EpollChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
74          super.setMaxMessagesPerRead(maxMessagesPerRead);
75          return this;
76      }
77  
78      @Override
79      public EpollChannelConfig setWriteSpinCount(int writeSpinCount) {
80          super.setWriteSpinCount(writeSpinCount);
81          return this;
82      }
83  
84      @Override
85      public EpollChannelConfig setAllocator(ByteBufAllocator allocator) {
86          super.setAllocator(allocator);
87          return this;
88      }
89  
90      @Override
91      public EpollChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
92          if (!(allocator.newHandle() instanceof RecvByteBufAllocator.ExtendedHandle)) {
93              throw new IllegalArgumentException("allocator.newHandle() must return an object of type: " +
94                      RecvByteBufAllocator.ExtendedHandle.class);
95          }
96          super.setRecvByteBufAllocator(allocator);
97          return this;
98      }
99  
100     @Override
101     public EpollChannelConfig setAutoRead(boolean autoRead) {
102         super.setAutoRead(autoRead);
103         return this;
104     }
105 
106     @Override
107     @Deprecated
108     public EpollChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
109         super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
110         return this;
111     }
112 
113     @Override
114     @Deprecated
115     public EpollChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
116         super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
117         return this;
118     }
119 
120     @Override
121     public EpollChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
122         super.setWriteBufferWaterMark(writeBufferWaterMark);
123         return this;
124     }
125 
126     @Override
127     public EpollChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
128         super.setMessageSizeEstimator(estimator);
129         return this;
130     }
131 
132     /**
133      * Return the {@link EpollMode} used. Default is
134      * {@link EpollMode#EDGE_TRIGGERED}. If you want to use {@link #isAutoRead()} {@code false} or
135      * {@link #getMaxMessagesPerRead()} and have an accurate behaviour you should use
136      * {@link EpollMode#LEVEL_TRIGGERED}.
137      */
138     public EpollMode getEpollMode() {
139         return channel.isFlagSet(Native.EPOLLET)
140                 ? EpollMode.EDGE_TRIGGERED : EpollMode.LEVEL_TRIGGERED;
141     }
142 
143     /**
144      * Set the {@link EpollMode} used. Default is
145      * {@link EpollMode#EDGE_TRIGGERED}. If you want to use {@link #isAutoRead()} {@code false} or
146      * {@link #getMaxMessagesPerRead()} and have an accurate behaviour you should use
147      * {@link EpollMode#LEVEL_TRIGGERED}.
148      *
149      * <strong>Be aware this config setting can only be adjusted before the channel was registered.</strong>
150      */
151     public EpollChannelConfig setEpollMode(EpollMode mode) {
152         if (mode == null) {
153             throw new NullPointerException("mode");
154         }
155         try {
156             switch (mode) {
157             case EDGE_TRIGGERED:
158                 checkChannelNotRegistered();
159                 channel.setFlag(Native.EPOLLET);
160                 break;
161             case LEVEL_TRIGGERED:
162                 checkChannelNotRegistered();
163                 channel.clearFlag(Native.EPOLLET);
164                 break;
165             default:
166                 throw new Error();
167             }
168         } catch (IOException e) {
169             throw new ChannelException(e);
170         }
171         return this;
172     }
173 
174     private void checkChannelNotRegistered() {
175         if (channel.isRegistered()) {
176             throw new IllegalStateException("EpollMode can only be changed before channel is registered");
177         }
178     }
179 
180     @Override
181     protected final void autoReadCleared() {
182         channel.clearEpollIn();
183     }
184 
185     final void setMaxBytesPerGatheringWrite(long maxBytesPerGatheringWrite) {
186         this.maxBytesPerGatheringWrite = maxBytesPerGatheringWrite;
187     }
188 
189     final long getMaxBytesPerGatheringWrite() {
190         return maxBytesPerGatheringWrite;
191     }
192 }