View Javadoc
1   /*
2    * Copyright 2016 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.kqueue;
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.UnstableApi;
28  
29  import java.io.IOException;
30  import java.nio.ByteBuffer;
31  import java.util.Map;
32  
33  import static io.netty.channel.kqueue.KQueueChannelOption.RCV_ALLOC_TRANSPORT_PROVIDES_GUESS;
34  import static io.netty.channel.unix.Limits.SSIZE_MAX;
35  import static java.lang.Math.min;
36  
37  @UnstableApi
38  public class KQueueChannelConfig extends DefaultChannelConfig {
39      private volatile boolean transportProvidesGuess;
40      private volatile long maxBytesPerGatheringWrite = SSIZE_MAX;
41  
42      KQueueChannelConfig(AbstractKQueueChannel channel) {
43          super(channel);
44      }
45  
46      KQueueChannelConfig(AbstractKQueueChannel channel, RecvByteBufAllocator recvByteBufAllocator) {
47          super(channel, recvByteBufAllocator);
48      }
49  
50      @Override
51      @SuppressWarnings("deprecation")
52      public Map<ChannelOption<?>, Object> getOptions() {
53          return getOptions(super.getOptions(), RCV_ALLOC_TRANSPORT_PROVIDES_GUESS);
54      }
55  
56      @SuppressWarnings("unchecked")
57      @Override
58      public <T> T getOption(ChannelOption<T> option) {
59          if (option == RCV_ALLOC_TRANSPORT_PROVIDES_GUESS) {
60              return (T) Boolean.valueOf(getRcvAllocTransportProvidesGuess());
61          }
62          try {
63              if (option instanceof IntegerUnixChannelOption) {
64                  IntegerUnixChannelOption opt = (IntegerUnixChannelOption) option;
65                  return (T) Integer.valueOf(((AbstractKQueueChannel) channel).socket.getIntOpt(
66                          opt.level(), opt.optname()));
67              }
68              if (option instanceof RawUnixChannelOption) {
69                  RawUnixChannelOption opt = (RawUnixChannelOption) option;
70                  ByteBuffer out = ByteBuffer.allocate(opt.level());
71                  ((AbstractKQueueChannel) channel).socket.getRawOpt(opt.level(), opt.optname(), out);
72                  return (T) out.flip();
73              }
74          } catch (IOException e) {
75              throw new ChannelException(e);
76          }
77          return super.getOption(option);
78      }
79  
80      @Override
81      public <T> boolean setOption(ChannelOption<T> option, T value) {
82          validate(option, value);
83  
84          if (option == RCV_ALLOC_TRANSPORT_PROVIDES_GUESS) {
85              setRcvAllocTransportProvidesGuess((Boolean) value);
86          } else {
87              try {
88                  if (option instanceof IntegerUnixChannelOption) {
89                      IntegerUnixChannelOption opt = (IntegerUnixChannelOption) option;
90                      ((AbstractKQueueChannel) channel).socket.setIntOpt(opt.level(), opt.optname(), (Integer) value);
91                      return true;
92                  } else if (option instanceof RawUnixChannelOption) {
93                      RawUnixChannelOption opt = (RawUnixChannelOption) option;
94                      ((AbstractKQueueChannel) channel).socket.setRawOpt(opt.level(), opt.optname(), (ByteBuffer) value);
95                      return true;
96                  }
97              } catch (IOException e) {
98                  throw new ChannelException(e);
99              }
100             return super.setOption(option, value);
101         }
102 
103         return true;
104     }
105 
106     /**
107      * If this is {@code true} then the {@link RecvByteBufAllocator.Handle#guess()} will be overridden to always attempt
108      * to read as many bytes as kqueue says are available.
109      */
110     public KQueueChannelConfig setRcvAllocTransportProvidesGuess(boolean transportProvidesGuess) {
111         this.transportProvidesGuess = transportProvidesGuess;
112         return this;
113     }
114 
115     /**
116      * If this is {@code true} then the {@link RecvByteBufAllocator.Handle#guess()} will be overridden to always attempt
117      * to read as many bytes as kqueue says are available.
118      */
119     public boolean getRcvAllocTransportProvidesGuess() {
120         return transportProvidesGuess;
121     }
122 
123     @Override
124     public KQueueChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
125         super.setConnectTimeoutMillis(connectTimeoutMillis);
126         return this;
127     }
128 
129     @Override
130     @Deprecated
131     public KQueueChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
132         super.setMaxMessagesPerRead(maxMessagesPerRead);
133         return this;
134     }
135 
136     @Override
137     public KQueueChannelConfig setWriteSpinCount(int writeSpinCount) {
138         super.setWriteSpinCount(writeSpinCount);
139         return this;
140     }
141 
142     @Override
143     public KQueueChannelConfig setAllocator(ByteBufAllocator allocator) {
144         super.setAllocator(allocator);
145         return this;
146     }
147 
148     @Override
149     public KQueueChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
150         if (!(allocator.newHandle() instanceof RecvByteBufAllocator.ExtendedHandle)) {
151             throw new IllegalArgumentException("allocator.newHandle() must return an object of type: " +
152                     RecvByteBufAllocator.ExtendedHandle.class);
153         }
154         super.setRecvByteBufAllocator(allocator);
155         return this;
156     }
157 
158     @Override
159     public KQueueChannelConfig setAutoRead(boolean autoRead) {
160         super.setAutoRead(autoRead);
161         return this;
162     }
163 
164     @Override
165     @Deprecated
166     public KQueueChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
167         super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
168         return this;
169     }
170 
171     @Override
172     @Deprecated
173     public KQueueChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
174         super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
175         return this;
176     }
177 
178     @Override
179     public KQueueChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
180         super.setWriteBufferWaterMark(writeBufferWaterMark);
181         return this;
182     }
183 
184     @Override
185     public KQueueChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
186         super.setMessageSizeEstimator(estimator);
187         return this;
188     }
189 
190     @Override
191     protected final void autoReadCleared() {
192         ((AbstractKQueueChannel) channel).clearReadFilter();
193     }
194 
195     final void setMaxBytesPerGatheringWrite(long maxBytesPerGatheringWrite) {
196         this.maxBytesPerGatheringWrite = min(SSIZE_MAX, maxBytesPerGatheringWrite);
197     }
198 
199     final long getMaxBytesPerGatheringWrite() {
200         return maxBytesPerGatheringWrite;
201     }
202 }