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