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