View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.reactor;
29  
30  import java.util.concurrent.TimeUnit;
31  
32  import org.apache.hc.core5.annotation.Contract;
33  import org.apache.hc.core5.annotation.ThreadingBehavior;
34  import org.apache.hc.core5.util.Args;
35  import org.apache.hc.core5.util.TimeValue;
36  import org.apache.hc.core5.util.Timeout;
37  
38  /**
39   * I/O reactor configuration parameters.
40   *
41   * @since 4.2
42   */
43  @Contract(threading = ThreadingBehavior.IMMUTABLE)
44  public final class IOReactorConfig {
45  
46      public static final IOReactorConfig DEFAULT = new Builder().build();
47  
48      private final TimeValue selectInterval;
49      private final int ioThreadCount;
50      private final Timeout  soTimeout;
51      private final boolean soReuseAddress;
52      private final TimeValue soLinger;
53      private final boolean soKeepAlive;
54      private final boolean tcpNoDelay;
55      private final int sndBufSize;
56      private final int rcvBufSize;
57      private final int backlogSize;
58  
59      IOReactorConfig(
60              final TimeValue selectInterval,
61              final int ioThreadCount,
62              final Timeout soTimeout,
63              final boolean soReuseAddress,
64              final TimeValue soLinger,
65              final boolean soKeepAlive,
66              final boolean tcpNoDelay,
67              final int sndBufSize,
68              final int rcvBufSize,
69              final int backlogSize) {
70          super();
71          this.selectInterval = selectInterval;
72          this.ioThreadCount = ioThreadCount;
73          this.soTimeout = soTimeout;
74          this.soReuseAddress = soReuseAddress;
75          this.soLinger = soLinger;
76          this.soKeepAlive = soKeepAlive;
77          this.tcpNoDelay = tcpNoDelay;
78          this.sndBufSize = sndBufSize;
79          this.rcvBufSize = rcvBufSize;
80          this.backlogSize = backlogSize;
81      }
82  
83      /**
84       * Determines time interval at which the I/O reactor wakes up to check for timed out sessions
85       * and session requests.
86       * <p>
87       * Default: {@code 1000} milliseconds.
88       * </p>
89       */
90      public TimeValue getSelectInterval() {
91          return this.selectInterval;
92      }
93  
94      /**
95       * Determines the number of I/O dispatch threads to be used by the I/O reactor.
96       * <p>
97       * Default: {@code 2}
98       * </p>
99       */
100     public int getIoThreadCount() {
101         return this.ioThreadCount;
102     }
103 
104     /**
105      * Determines the default socket timeout value for non-blocking I/O operations.
106      * <p>
107      * Default: {@code 0} (no timeout)
108      * </p>
109      *
110      * @see java.net.SocketOptions#SO_TIMEOUT
111      */
112     public Timeout getSoTimeout() {
113         return soTimeout;
114     }
115 
116     /**
117      * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
118      * for newly created sockets.
119      * <p>
120      * Default: {@code false}
121      * </p>
122      *
123      * @see java.net.SocketOptions#SO_REUSEADDR
124      */
125     public boolean isSoReuseAddress() {
126         return soReuseAddress;
127     }
128 
129     /**
130      * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
131      * for newly created sockets.
132      * <p>
133      * Default: {@code -1}
134      * </p>
135      *
136      * @see java.net.SocketOptions#SO_LINGER
137      */
138     public TimeValue getSoLinger() {
139         return soLinger;
140     }
141 
142     /**
143      * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
144      * for newly created sockets.
145      * <p>
146      * Default: {@code -1}
147      * </p>
148      *
149      * @see java.net.SocketOptions#SO_KEEPALIVE
150      */
151     public boolean isSoKeepalive() {
152         return this.soKeepAlive;
153     }
154 
155     /**
156      * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
157      * for newly created sockets.
158      * <p>
159      * Default: {@code false}
160      * </p>
161      *
162      * @see java.net.SocketOptions#TCP_NODELAY
163      */
164     public boolean isTcpNoDelay() {
165         return tcpNoDelay;
166     }
167 
168     /**
169      * Determines the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter
170      * for newly created sockets.
171      * <p>
172      * Default: {@code 0} (system default)
173      * </p>
174      *
175      * @see java.net.SocketOptions#SO_SNDBUF
176      */
177     public int getSndBufSize() {
178         return sndBufSize;
179     }
180 
181     /**
182      * Determines the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter
183      * for newly created sockets.
184      * <p>
185      * Default: {@code 0} (system default)
186      * </p>
187      *
188      * @see java.net.SocketOptions#SO_RCVBUF
189      */
190     public int getRcvBufSize() {
191         return rcvBufSize;
192     }
193 
194     /**
195      * Determines the default backlog size value for server sockets binds.
196      * <p>
197      * Default: {@code 0} (system default)
198      * </p>
199      *
200      * @since 4.4
201      */
202     public int getBacklogSize() {
203         return backlogSize;
204     }
205 
206     public static Builder custom() {
207         return new Builder();
208     }
209 
210     public static Builder copy(final IOReactorConfig config) {
211         Args.notNull(config, "I/O reactor config");
212         return new Builder()
213             .setSelectInterval(config.getSelectInterval())
214             .setIoThreadCount(config.getIoThreadCount())
215             .setSoTimeout(config.getSoTimeout())
216             .setSoReuseAddress(config.isSoReuseAddress())
217             .setSoLinger(config.getSoLinger())
218             .setSoKeepAlive(config.isSoKeepalive())
219             .setTcpNoDelay(config.isTcpNoDelay())
220             .setSndBufSize(config.getSndBufSize())
221             .setRcvBufSize(config.getRcvBufSize())
222             .setBacklogSize(config.getBacklogSize());
223     }
224 
225     public static class Builder {
226 
227         private static int DefaultMaxIoThreadCount = -1;
228 
229         /**
230          * Gets the default value for {@code ioThreadCount}. Returns
231          * {@link Runtime#availableProcessors()} if
232          * {@link #setDefaultMaxIoThreadCount(int)} was called with a value less &lt;= 0.
233          *
234          * @return the default value for ioThreadCount.
235          * @since 4.4.10
236          */
237         public static int getDefaultMaxIoThreadCount() {
238             return DefaultMaxIoThreadCount > 0 ? DefaultMaxIoThreadCount : Runtime.getRuntime().availableProcessors();
239         }
240 
241         /**
242          * Sets the default value for {@code ioThreadCount}. Use a value &lt;= 0 to
243          * cause {@link #getDefaultMaxIoThreadCount()} to return
244          * {@link Runtime#availableProcessors()}.
245          *
246          * @param defaultMaxIoThreadCount
247          *            the default value for ioThreadCount.
248          * @since 4.4.10
249          */
250         public static void setDefaultMaxIoThreadCount(final int defaultMaxIoThreadCount) {
251             DefaultMaxIoThreadCount = defaultMaxIoThreadCount;
252         }
253 
254         private TimeValue selectInterval;
255         private int ioThreadCount;
256         private Timeout  soTimeout;
257         private boolean soReuseAddress;
258         private TimeValue soLinger;
259         private boolean soKeepAlive;
260         private boolean tcpNoDelay;
261         private int sndBufSize;
262         private int rcvBufSize;
263         private int backlogSize;
264 
265         Builder() {
266             this.selectInterval = TimeValue.ofSeconds(1);
267             this.ioThreadCount = Builder.getDefaultMaxIoThreadCount();
268             this.soTimeout = Timeout.ZERO_MILLISECONDS;
269             this.soReuseAddress = false;
270             this.soLinger = TimeValue.NEG_ONE_SECONDS;
271             this.soKeepAlive = false;
272             this.tcpNoDelay = true;
273             this.sndBufSize = 0;
274             this.rcvBufSize = 0;
275             this.backlogSize = 0;
276         }
277 
278         public Builder setSelectInterval(final TimeValue selectInterval) {
279             this.selectInterval = selectInterval;
280             return this;
281         }
282 
283         public Builder setIoThreadCount(final int ioThreadCount) {
284             this.ioThreadCount = ioThreadCount;
285             return this;
286         }
287 
288         public Builder setSoTimeout(final int soTimeout, final TimeUnit timeUnit) {
289             this.soTimeout = Timeout.of(soTimeout, timeUnit);
290             return this;
291         }
292 
293         public Builder setSoTimeout(final Timeout soTimeout) {
294             this.soTimeout = soTimeout;
295             return this;
296         }
297 
298         public Builder setSoReuseAddress(final boolean soReuseAddress) {
299             this.soReuseAddress = soReuseAddress;
300             return this;
301         }
302 
303         public Builder setSoLinger(final int soLinger, final TimeUnit timeUnit) {
304             this.soLinger = TimeValue.of(soLinger, timeUnit);
305             return this;
306         }
307 
308         public Builder setSoLinger(final TimeValue soLinger) {
309             this.soLinger = soLinger;
310             return this;
311         }
312 
313         public Builder setSoKeepAlive(final boolean soKeepAlive) {
314             this.soKeepAlive = soKeepAlive;
315             return this;
316         }
317 
318         public Builder setTcpNoDelay(final boolean tcpNoDelay) {
319             this.tcpNoDelay = tcpNoDelay;
320             return this;
321         }
322 
323         public Builder setSndBufSize(final int sndBufSize) {
324             this.sndBufSize = sndBufSize;
325             return this;
326         }
327 
328         public Builder setRcvBufSize(final int rcvBufSize) {
329             this.rcvBufSize = rcvBufSize;
330             return this;
331         }
332 
333         public Builder setBacklogSize(final int backlogSize) {
334             this.backlogSize = backlogSize;
335             return this;
336         }
337 
338         public IOReactorConfig build() {
339             return new IOReactorConfig(
340                     selectInterval != null ? selectInterval : TimeValue.ofSeconds(1),
341                     ioThreadCount,
342                     Timeout.defaultsToDisabled(soTimeout),
343                     soReuseAddress,
344                     TimeValue.defaultsToNegativeOneMillisecond(soLinger),
345                     soKeepAlive,
346                     tcpNoDelay,
347                     sndBufSize, rcvBufSize, backlogSize);
348         }
349 
350     }
351 
352     @Override
353     public String toString() {
354         final StringBuilder builder = new StringBuilder();
355         builder.append("[selectIntervalMillis=").append(this.selectInterval)
356                 .append(", ioThreadCount=").append(this.ioThreadCount)
357                 .append(", soTimeout=").append(this.soTimeout)
358                 .append(", soReuseAddress=").append(this.soReuseAddress)
359                 .append(", soLinger=").append(this.soLinger)
360                 .append(", soKeepAlive=").append(this.soKeepAlive)
361                 .append(", tcpNoDelay=").append(this.tcpNoDelay)
362                 .append(", sndBufSize=").append(this.sndBufSize)
363                 .append(", rcvBufSize=").append(this.rcvBufSize)
364                 .append(", backlogSize=").append(this.backlogSize)
365                 .append("]");
366         return builder.toString();
367     }
368 
369 }