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.net.SocketAddress;
31  import java.util.concurrent.TimeUnit;
32  
33  import org.apache.hc.core5.annotation.Contract;
34  import org.apache.hc.core5.annotation.ThreadingBehavior;
35  import org.apache.hc.core5.util.Args;
36  import org.apache.hc.core5.util.TimeValue;
37  import org.apache.hc.core5.util.Timeout;
38  
39  /**
40   * I/O reactor configuration parameters.
41   *
42   * @since 4.2
43   */
44  @Contract(threading = ThreadingBehavior.IMMUTABLE)
45  public final class IOReactorConfig {
46  
47      public static final IOReactorConfig DEFAULT = new Builder().build();
48  
49      private final TimeValue selectInterval;
50      private final int ioThreadCount;
51      private final Timeout  soTimeout;
52      private final boolean soReuseAddress;
53      private final TimeValue soLinger;
54      private final boolean soKeepAlive;
55      private final boolean tcpNoDelay;
56      private final int sndBufSize;
57      private final int rcvBufSize;
58      private final int backlogSize;
59      private final SocketAddress socksProxyAddress;
60      private final String socksProxyUsername;
61      private final String socksProxyPassword;
62  
63      IOReactorConfig(
64              final TimeValue selectInterval,
65              final int ioThreadCount,
66              final Timeout soTimeout,
67              final boolean soReuseAddress,
68              final TimeValue soLinger,
69              final boolean soKeepAlive,
70              final boolean tcpNoDelay,
71              final int sndBufSize,
72              final int rcvBufSize,
73              final int backlogSize,
74              final SocketAddress socksProxyAddress,
75              final String socksProxyUsername,
76              final String socksProxyPassword) {
77          super();
78          this.selectInterval = selectInterval;
79          this.ioThreadCount = ioThreadCount;
80          this.soTimeout = soTimeout;
81          this.soReuseAddress = soReuseAddress;
82          this.soLinger = soLinger;
83          this.soKeepAlive = soKeepAlive;
84          this.tcpNoDelay = tcpNoDelay;
85          this.sndBufSize = sndBufSize;
86          this.rcvBufSize = rcvBufSize;
87          this.backlogSize = backlogSize;
88          this.socksProxyAddress = socksProxyAddress;
89          this.socksProxyUsername = socksProxyUsername;
90          this.socksProxyPassword = socksProxyPassword;
91      }
92  
93      /**
94       * @see Builder#setSelectInterval(TimeValue)
95       */
96      public TimeValue getSelectInterval() {
97          return this.selectInterval;
98      }
99  
100     /**
101      * @see Builder#setIoThreadCount(int)
102      */
103     public int getIoThreadCount() {
104         return this.ioThreadCount;
105     }
106 
107     /**
108      * @see Builder#setSoTimeout(Timeout)
109      */
110     public Timeout getSoTimeout() {
111         return soTimeout;
112     }
113 
114     /**
115      * @see Builder#setSoReuseAddress(boolean)
116      */
117     public boolean isSoReuseAddress() {
118         return soReuseAddress;
119     }
120 
121     /**
122      * @see Builder#setSoLinger(TimeValue)
123      */
124     public TimeValue getSoLinger() {
125         return soLinger;
126     }
127 
128     /**
129      * @see Builder#setSoKeepAlive(boolean)
130      */
131     public boolean isSoKeepalive() {
132         return this.soKeepAlive;
133     }
134 
135     /**
136      * @see Builder#setTcpNoDelay(boolean)
137      */
138     public boolean isTcpNoDelay() {
139         return tcpNoDelay;
140     }
141 
142     /**
143      * @see Builder#setSndBufSize(int)
144      */
145     public int getSndBufSize() {
146         return sndBufSize;
147     }
148 
149     /**
150      * @see Builder#setRcvBufSize(int)
151      */
152     public int getRcvBufSize() {
153         return rcvBufSize;
154     }
155 
156     /**
157      * @see Builder#setBacklogSize(int)
158      */
159     public int getBacklogSize() {
160         return backlogSize;
161     }
162 
163     /**
164      * @see Builder#setSocksProxyAddress(SocketAddress)
165      */
166     public SocketAddress getSocksProxyAddress() {
167         return this.socksProxyAddress;
168     }
169 
170     /**
171      * @see Builder#setSocksProxyUsername(String)
172      */
173     public String getSocksProxyUsername() {
174         return this.socksProxyUsername;
175     }
176 
177     /**
178      * @see Builder#setSocksProxyAddress(SocketAddress)
179      */
180     public String getSocksProxyPassword() {
181         return this.socksProxyPassword;
182     }
183 
184     public static Builder custom() {
185         return new Builder();
186     }
187 
188     public static Builder copy(final IOReactorConfig config) {
189         Args.notNull(config, "I/O reactor config");
190         return new Builder()
191             .setSelectInterval(config.getSelectInterval())
192             .setIoThreadCount(config.getIoThreadCount())
193             .setSoTimeout(config.getSoTimeout())
194             .setSoReuseAddress(config.isSoReuseAddress())
195             .setSoLinger(config.getSoLinger())
196             .setSoKeepAlive(config.isSoKeepalive())
197             .setTcpNoDelay(config.isTcpNoDelay())
198             .setSndBufSize(config.getSndBufSize())
199             .setRcvBufSize(config.getRcvBufSize())
200             .setBacklogSize(config.getBacklogSize())
201             .setSocksProxyAddress(config.getSocksProxyAddress())
202             .setSocksProxyUsername(config.getSocksProxyUsername())
203             .setSocksProxyPassword(config.getSocksProxyPassword());
204     }
205 
206     public static class Builder {
207 
208         private static int defaultMaxIOThreadCount = -1;
209 
210         /**
211          * Gets the default value for {@code ioThreadCount}. Returns
212          * {@link Runtime#availableProcessors()} if
213          * {@link #setDefaultMaxIOThreadCount(int)} was called with a value less &lt;= 0.
214          *
215          * @return the default value for ioThreadCount.
216          * @since 4.4.10
217          */
218         public static int getDefaultMaxIOThreadCount() {
219             return defaultMaxIOThreadCount > 0 ? defaultMaxIOThreadCount : Runtime.getRuntime().availableProcessors();
220         }
221 
222         /**
223          * Sets the default value for {@code ioThreadCount}. Use a value &lt;= 0 to
224          * cause {@link #getDefaultMaxIOThreadCount()} to return
225          * {@link Runtime#availableProcessors()}.
226          *
227          * @param defaultMaxIOThreadCount
228          *            the default value for ioThreadCount.
229          * @since 4.4.10
230          */
231         public static void setDefaultMaxIOThreadCount(final int defaultMaxIOThreadCount) {
232             Builder.defaultMaxIOThreadCount = defaultMaxIOThreadCount;
233         }
234 
235         private TimeValue selectInterval;
236         private int ioThreadCount;
237         private Timeout  soTimeout;
238         private boolean soReuseAddress;
239         private TimeValue soLinger;
240         private boolean soKeepAlive;
241         private boolean tcpNoDelay;
242         private int sndBufSize;
243         private int rcvBufSize;
244         private int backlogSize;
245         private SocketAddress socksProxyAddress;
246         private String socksProxyUsername;
247         private String socksProxyPassword;
248 
249         Builder() {
250             this.selectInterval = TimeValue.ofSeconds(1);
251             this.ioThreadCount = Builder.getDefaultMaxIOThreadCount();
252             this.soTimeout = Timeout.ZERO_MILLISECONDS;
253             this.soReuseAddress = false;
254             this.soLinger = TimeValue.NEG_ONE_SECOND;
255             this.soKeepAlive = false;
256             this.tcpNoDelay = true;
257             this.sndBufSize = 0;
258             this.rcvBufSize = 0;
259             this.backlogSize = 0;
260             this.socksProxyAddress = null;
261             this.socksProxyUsername = null;
262             this.socksProxyPassword = null;
263         }
264 
265         /**
266          * Determines time interval at which the I/O reactor wakes up to check for timed out sessions
267          * and session requests.
268          * <p>
269          * Default: {@code 1000} milliseconds.
270          * </p>
271          */
272         public Builder setSelectInterval(final TimeValue selectInterval) {
273             this.selectInterval = selectInterval;
274             return this;
275         }
276 
277         /**
278          * Determines the number of I/O dispatch threads to be used by the I/O reactor.
279          * <p>
280          * Default: {@code 2}
281          * </p>
282          */
283         public Builder setIoThreadCount(final int ioThreadCount) {
284             this.ioThreadCount = ioThreadCount;
285             return this;
286         }
287 
288         /**
289          * Determines the default socket timeout value for non-blocking I/O operations.
290          * <p>
291          * Default: {@code 0} (no timeout)
292          * </p>
293          *
294          * @see java.net.SocketOptions#SO_TIMEOUT
295          */
296         public Builder setSoTimeout(final int soTimeout, final TimeUnit timeUnit) {
297             this.soTimeout = Timeout.of(soTimeout, timeUnit);
298             return this;
299         }
300 
301         /**
302          * Determines the default socket timeout value for non-blocking I/O operations.
303          * <p>
304          * Default: {@code 0} (no timeout)
305          * </p>
306          *
307          * @see java.net.SocketOptions#SO_TIMEOUT
308          */
309         public Builder setSoTimeout(final Timeout soTimeout) {
310             this.soTimeout = soTimeout;
311             return this;
312         }
313 
314         /**
315          * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
316          * for newly created sockets.
317          * <p>
318          * Default: {@code false}
319          * </p>
320          *
321          * @see java.net.SocketOptions#SO_REUSEADDR
322          */
323         public Builder setSoReuseAddress(final boolean soReuseAddress) {
324             this.soReuseAddress = soReuseAddress;
325             return this;
326         }
327 
328         /**
329          * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
330          * for newly created sockets.
331          * <p>
332          * Default: {@code -1}
333          * </p>
334          *
335          * @see java.net.SocketOptions#SO_LINGER
336          */
337         public Builder setSoLinger(final int soLinger, final TimeUnit timeUnit) {
338             this.soLinger = TimeValue.of(soLinger, timeUnit);
339             return this;
340         }
341 
342         /**
343          * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
344          * for newly created sockets.
345          * <p>
346          * Default: {@code -1}
347          * </p>
348          *
349          * @see java.net.SocketOptions#SO_LINGER
350          */
351         public Builder setSoLinger(final TimeValue soLinger) {
352             this.soLinger = soLinger;
353             return this;
354         }
355 
356         /**
357          * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
358          * for newly created sockets.
359          * <p>
360          * Default: {@code -1}
361          * </p>
362          *
363          * @see java.net.SocketOptions#SO_KEEPALIVE
364          */
365         public Builder setSoKeepAlive(final boolean soKeepAlive) {
366             this.soKeepAlive = soKeepAlive;
367             return this;
368         }
369 
370         /**
371          * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
372          * for newly created sockets.
373          * <p>
374          * Default: {@code false}
375          * </p>
376          *
377          * @see java.net.SocketOptions#TCP_NODELAY
378          */
379         public Builder setTcpNoDelay(final boolean tcpNoDelay) {
380             this.tcpNoDelay = tcpNoDelay;
381             return this;
382         }
383 
384         /**
385          * Determines the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter
386          * for newly created sockets.
387          * <p>
388          * Default: {@code 0} (system default)
389          * </p>
390          *
391          * @see java.net.SocketOptions#SO_SNDBUF
392          */
393         public Builder setSndBufSize(final int sndBufSize) {
394             this.sndBufSize = sndBufSize;
395             return this;
396         }
397 
398         /**
399          * Determines the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter
400          * for newly created sockets.
401          * <p>
402          * Default: {@code 0} (system default)
403          * </p>
404          *
405          * @see java.net.SocketOptions#SO_RCVBUF
406          */
407         public Builder setRcvBufSize(final int rcvBufSize) {
408             this.rcvBufSize = rcvBufSize;
409             return this;
410         }
411 
412         /**
413          * Determines the default backlog size value for server sockets binds.
414          * <p>
415          * Default: {@code 0} (system default)
416          * </p>
417          *
418          * @since 4.4
419          */
420         public Builder setBacklogSize(final int backlogSize) {
421             this.backlogSize = backlogSize;
422             return this;
423         }
424 
425         /**
426          * The address of the SOCKS proxy to use.
427          */
428         public Builder setSocksProxyAddress(final SocketAddress socksProxyAddress) {
429             this.socksProxyAddress = socksProxyAddress;
430             return this;
431         }
432 
433         /**
434          * The username to provide to the SOCKS proxy for username/password authentication.
435          */
436         public Builder setSocksProxyUsername(final String socksProxyUsername) {
437             this.socksProxyUsername = socksProxyUsername;
438             return this;
439         }
440 
441         /**
442          * The password to provide to the SOCKS proxy for username/password authentication.
443          */
444         public Builder setSocksProxyPassword(final String socksProxyPassword) {
445             this.socksProxyPassword = socksProxyPassword;
446             return this;
447         }
448 
449         public IOReactorConfig build() {
450             return new IOReactorConfig(
451                     selectInterval != null ? selectInterval : TimeValue.ofSeconds(1),
452                     ioThreadCount,
453                     Timeout.defaultsToDisabled(soTimeout),
454                     soReuseAddress,
455                     TimeValue.defaultsToNegativeOneMillisecond(soLinger),
456                     soKeepAlive,
457                     tcpNoDelay,
458                     sndBufSize, rcvBufSize, backlogSize,
459                     socksProxyAddress, socksProxyUsername, socksProxyPassword);
460         }
461 
462     }
463 
464     @Override
465     public String toString() {
466         final StringBuilder builder = new StringBuilder();
467         builder.append("[selectInterval=").append(this.selectInterval)
468                 .append(", ioThreadCount=").append(this.ioThreadCount)
469                 .append(", soTimeout=").append(this.soTimeout)
470                 .append(", soReuseAddress=").append(this.soReuseAddress)
471                 .append(", soLinger=").append(this.soLinger)
472                 .append(", soKeepAlive=").append(this.soKeepAlive)
473                 .append(", tcpNoDelay=").append(this.tcpNoDelay)
474                 .append(", sndBufSize=").append(this.sndBufSize)
475                 .append(", rcvBufSize=").append(this.rcvBufSize)
476                 .append(", backlogSize=").append(this.backlogSize)
477                 .append(", socksProxyAddress=").append(this.socksProxyAddress)
478                 .append("]");
479         return builder.toString();
480     }
481 
482 }