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.netty.channel.epoll;
17  
18  import io.netty.buffer.ByteBufAllocator;
19  import io.netty.channel.Channel;
20  import io.netty.channel.ChannelException;
21  import io.netty.channel.ChannelOption;
22  import io.netty.channel.DefaultChannelConfig;
23  import io.netty.channel.MessageSizeEstimator;
24  import io.netty.channel.RecvByteBufAllocator;
25  import io.netty.channel.WriteBufferWaterMark;
26  import io.netty.channel.unix.IntegerUnixChannelOption;
27  import io.netty.channel.unix.RawUnixChannelOption;
28  import io.netty.util.internal.logging.InternalLogger;
29  import io.netty.util.internal.logging.InternalLoggerFactory;
30  
31  import java.io.IOException;
32  import java.nio.ByteBuffer;
33  import java.util.Map;
34  
35  import static io.netty.channel.unix.Limits.SSIZE_MAX;
36  
37  public class EpollChannelConfig extends DefaultChannelConfig {
38  
39      private static final InternalLogger LOGGER = InternalLoggerFactory.getInstance(EpollChannelConfig.class);
40  
41      private volatile long maxBytesPerGatheringWrite = SSIZE_MAX;
42  
43      protected EpollChannelConfig(Channel channel) {
44          super(checkAbstractEpollChannel(channel));
45      }
46  
47      protected EpollChannelConfig(Channel channel, RecvByteBufAllocator recvByteBufAllocator) {
48          super(checkAbstractEpollChannel(channel), recvByteBufAllocator);
49      }
50  
51      protected LinuxSocket socket() {
52          return ((AbstractEpollChannel) channel).socket;
53      }
54  
55      private static Channel checkAbstractEpollChannel(Channel channel) {
56          if (!(channel instanceof AbstractEpollChannel)) {
57              throw new IllegalArgumentException("channel is not AbstractEpollChannel: " + channel.getClass());
58          }
59          return channel;
60      }
61  
62      @Override
63      public Map<ChannelOption<?>, Object> getOptions() {
64          return getOptions(super.getOptions(), EpollChannelOption.EPOLL_MODE);
65      }
66  
67      @SuppressWarnings("unchecked")
68      @Override
69      public <T> T getOption(ChannelOption<T> option) {
70          if (option == EpollChannelOption.EPOLL_MODE) {
71              return (T) getEpollMode();
72          }
73          try {
74              if (option instanceof IntegerUnixChannelOption) {
75                  IntegerUnixChannelOption opt = (IntegerUnixChannelOption) option;
76                  return (T) Integer.valueOf(((AbstractEpollChannel) channel).socket.getIntOpt(
77                          opt.level(), opt.optname()));
78              }
79              if (option instanceof RawUnixChannelOption) {
80                  RawUnixChannelOption opt = (RawUnixChannelOption) option;
81                  ByteBuffer out = ByteBuffer.allocate(opt.length());
82                  ((AbstractEpollChannel) channel).socket.getRawOpt(opt.level(), opt.optname(), out);
83                  return (T) out.flip();
84              }
85          } catch (IOException e) {
86              throw new ChannelException(e);
87          }
88          return super.getOption(option);
89      }
90  
91      @Override
92      public <T> boolean setOption(ChannelOption<T> option, T value) {
93          validate(option, value);
94          if (option == EpollChannelOption.EPOLL_MODE) {
95              setEpollMode((EpollMode) value);
96          } else {
97              try {
98                  if (option instanceof IntegerUnixChannelOption) {
99                      IntegerUnixChannelOption opt = (IntegerUnixChannelOption) option;
100                     ((AbstractEpollChannel) channel).socket.setIntOpt(opt.level(), opt.optname(), (Integer) value);
101                     return true;
102                 } else if (option instanceof RawUnixChannelOption) {
103                     RawUnixChannelOption opt = (RawUnixChannelOption) option;
104                     ((AbstractEpollChannel) channel).socket.setRawOpt(opt.level(), opt.optname(), (ByteBuffer) value);
105                     return true;
106                 }
107             } catch (IOException e) {
108                 throw new ChannelException(e);
109             }
110             return super.setOption(option, value);
111         }
112         return true;
113     }
114 
115     @Override
116     public EpollChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
117         super.setConnectTimeoutMillis(connectTimeoutMillis);
118         return this;
119     }
120 
121     @Override
122     @Deprecated
123     public EpollChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
124         super.setMaxMessagesPerRead(maxMessagesPerRead);
125         return this;
126     }
127 
128     @Override
129     public EpollChannelConfig setWriteSpinCount(int writeSpinCount) {
130         super.setWriteSpinCount(writeSpinCount);
131         return this;
132     }
133 
134     @Override
135     public EpollChannelConfig setAllocator(ByteBufAllocator allocator) {
136         super.setAllocator(allocator);
137         return this;
138     }
139 
140     @Override
141     public EpollChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
142         if (!(allocator.newHandle() instanceof RecvByteBufAllocator.ExtendedHandle)) {
143             throw new IllegalArgumentException("allocator.newHandle() must return an object of type: " +
144                     RecvByteBufAllocator.ExtendedHandle.class);
145         }
146         super.setRecvByteBufAllocator(allocator);
147         return this;
148     }
149 
150     @Override
151     public EpollChannelConfig setAutoRead(boolean autoRead) {
152         super.setAutoRead(autoRead);
153         return this;
154     }
155 
156     @Override
157     @Deprecated
158     public EpollChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
159         super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
160         return this;
161     }
162 
163     @Override
164     @Deprecated
165     public EpollChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
166         super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
167         return this;
168     }
169 
170     @Override
171     public EpollChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
172         super.setWriteBufferWaterMark(writeBufferWaterMark);
173         return this;
174     }
175 
176     @Override
177     public EpollChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
178         super.setMessageSizeEstimator(estimator);
179         return this;
180     }
181 
182     /**
183      * Return the {@link EpollMode} used. Default is
184      * {@link EpollMode#EDGE_TRIGGERED}. If you want to use {@link #isAutoRead()} {@code false} or
185      * {@link #getMaxMessagesPerRead()} and have an accurate behaviour you should use
186      * {@link EpollMode#LEVEL_TRIGGERED}.
187      *
188      * @deprecated Netty always uses level-triggered mode and so this method is just a no-op.
189      */
190     @Deprecated
191     public EpollMode getEpollMode() {
192         return EpollMode.LEVEL_TRIGGERED;
193     }
194 
195     /**
196      * Set the {@link EpollMode} used. Default is
197      * {@link EpollMode#EDGE_TRIGGERED}. If you want to use {@link #isAutoRead()} {@code false} or
198      * {@link #getMaxMessagesPerRead()} and have an accurate behaviour you should use
199      * {@link EpollMode#LEVEL_TRIGGERED}.
200      *
201      * <strong>Be aware this config setting can only be adjusted before the channel was registered.</strong>
202      *
203      * @deprecated Netty always uses level-triggered mode and so this method is just a no-op.
204      */
205     @Deprecated
206     public EpollChannelConfig setEpollMode(EpollMode mode) {
207         LOGGER.debug("Changing the EpollMode is not supported anymore, this is just a no-op");
208         return this;
209     }
210 
211     private void checkChannelNotRegistered() {
212         if (channel.isRegistered()) {
213             throw new IllegalStateException("EpollMode can only be changed before channel is registered");
214         }
215     }
216 
217     @Override
218     protected final void autoReadCleared() {
219         ((AbstractEpollChannel) channel).clearEpollIn();
220     }
221 
222     protected final void setMaxBytesPerGatheringWrite(long maxBytesPerGatheringWrite) {
223         this.maxBytesPerGatheringWrite = maxBytesPerGatheringWrite;
224     }
225 
226     protected final long getMaxBytesPerGatheringWrite() {
227         return maxBytesPerGatheringWrite;
228     }
229 }