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