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