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       * Determines time interval at which the I/O reactor wakes up to check for timed out sessions
95       * and session requests.
96       * <p>
97       * Default: {@code 1000} milliseconds.
98       * </p>
99       */
100     public TimeValue getSelectInterval() {
101         return this.selectInterval;
102     }
103 
104     /**
105      * Determines the number of I/O dispatch threads to be used by the I/O reactor.
106      * <p>
107      * Default: {@code 2}
108      * </p>
109      */
110     public int getIoThreadCount() {
111         return this.ioThreadCount;
112     }
113 
114     /**
115      * Determines the default socket timeout value for non-blocking I/O operations.
116      * <p>
117      * Default: {@code 0} (no timeout)
118      * </p>
119      *
120      * @see java.net.SocketOptions#SO_TIMEOUT
121      */
122     public Timeout getSoTimeout() {
123         return soTimeout;
124     }
125 
126     /**
127      * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
128      * for newly created sockets.
129      * <p>
130      * Default: {@code false}
131      * </p>
132      *
133      * @see java.net.SocketOptions#SO_REUSEADDR
134      */
135     public boolean isSoReuseAddress() {
136         return soReuseAddress;
137     }
138 
139     /**
140      * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
141      * for newly created sockets.
142      * <p>
143      * Default: {@code -1}
144      * </p>
145      *
146      * @see java.net.SocketOptions#SO_LINGER
147      */
148     public TimeValue getSoLinger() {
149         return soLinger;
150     }
151 
152     /**
153      * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
154      * for newly created sockets.
155      * <p>
156      * Default: {@code -1}
157      * </p>
158      *
159      * @see java.net.SocketOptions#SO_KEEPALIVE
160      */
161     public boolean isSoKeepalive() {
162         return this.soKeepAlive;
163     }
164 
165     /**
166      * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
167      * for newly created sockets.
168      * <p>
169      * Default: {@code false}
170      * </p>
171      *
172      * @see java.net.SocketOptions#TCP_NODELAY
173      */
174     public boolean isTcpNoDelay() {
175         return tcpNoDelay;
176     }
177 
178     /**
179      * Determines the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter
180      * for newly created sockets.
181      * <p>
182      * Default: {@code 0} (system default)
183      * </p>
184      *
185      * @see java.net.SocketOptions#SO_SNDBUF
186      */
187     public int getSndBufSize() {
188         return sndBufSize;
189     }
190 
191     /**
192      * Determines the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter
193      * for newly created sockets.
194      * <p>
195      * Default: {@code 0} (system default)
196      * </p>
197      *
198      * @see java.net.SocketOptions#SO_RCVBUF
199      */
200     public int getRcvBufSize() {
201         return rcvBufSize;
202     }
203 
204     /**
205      * Determines the default backlog size value for server sockets binds.
206      * <p>
207      * Default: {@code 0} (system default)
208      * </p>
209      *
210      * @since 4.4
211      */
212     public int getBacklogSize() {
213         return backlogSize;
214     }
215 
216     /**
217      * The address of the SOCKS proxy to use.
218      */
219     public SocketAddress getSocksProxyAddress() {
220         return this.socksProxyAddress;
221     }
222 
223     /**
224      * The username to provide to the SOCKS proxy for username/password authentication.
225      */
226     public String getSocksProxyUsername() {
227         return this.socksProxyUsername;
228     }
229 
230     /**
231      * The password to provide to the SOCKS proxy for username/password authentication.
232      */
233     public String getSocksProxyPassword() {
234         return this.socksProxyPassword;
235     }
236 
237     public static Builder custom() {
238         return new Builder();
239     }
240 
241     public static Builder copy(final IOReactorConfig config) {
242         Args.notNull(config, "I/O reactor config");
243         return new Builder()
244             .setSelectInterval(config.getSelectInterval())
245             .setIoThreadCount(config.getIoThreadCount())
246             .setSoTimeout(config.getSoTimeout())
247             .setSoReuseAddress(config.isSoReuseAddress())
248             .setSoLinger(config.getSoLinger())
249             .setSoKeepAlive(config.isSoKeepalive())
250             .setTcpNoDelay(config.isTcpNoDelay())
251             .setSndBufSize(config.getSndBufSize())
252             .setRcvBufSize(config.getRcvBufSize())
253             .setBacklogSize(config.getBacklogSize())
254             .setSocksProxyAddress(config.getSocksProxyAddress())
255             .setSocksProxyUsername(config.getSocksProxyUsername())
256             .setSocksProxyPassword(config.getSocksProxyPassword());
257     }
258 
259     public static class Builder {
260 
261         private static int DefaultMaxIoThreadCount = -1;
262 
263         /**
264          * Gets the default value for {@code ioThreadCount}. Returns
265          * {@link Runtime#availableProcessors()} if
266          * {@link #setDefaultMaxIoThreadCount(int)} was called with a value less &lt;= 0.
267          *
268          * @return the default value for ioThreadCount.
269          * @since 4.4.10
270          */
271         public static int getDefaultMaxIoThreadCount() {
272             return DefaultMaxIoThreadCount > 0 ? DefaultMaxIoThreadCount : Runtime.getRuntime().availableProcessors();
273         }
274 
275         /**
276          * Sets the default value for {@code ioThreadCount}. Use a value &lt;= 0 to
277          * cause {@link #getDefaultMaxIoThreadCount()} to return
278          * {@link Runtime#availableProcessors()}.
279          *
280          * @param defaultMaxIoThreadCount
281          *            the default value for ioThreadCount.
282          * @since 4.4.10
283          */
284         public static void setDefaultMaxIoThreadCount(final int defaultMaxIoThreadCount) {
285             DefaultMaxIoThreadCount = defaultMaxIoThreadCount;
286         }
287 
288         private TimeValue selectInterval;
289         private int ioThreadCount;
290         private Timeout  soTimeout;
291         private boolean soReuseAddress;
292         private TimeValue soLinger;
293         private boolean soKeepAlive;
294         private boolean tcpNoDelay;
295         private int sndBufSize;
296         private int rcvBufSize;
297         private int backlogSize;
298         private SocketAddress socksProxyAddress;
299         private String socksProxyUsername;
300         private String socksProxyPassword;
301 
302         Builder() {
303             this.selectInterval = TimeValue.ofSeconds(1);
304             this.ioThreadCount = Builder.getDefaultMaxIoThreadCount();
305             this.soTimeout = Timeout.ZERO_MILLISECONDS;
306             this.soReuseAddress = false;
307             this.soLinger = TimeValue.NEG_ONE_SECONDS;
308             this.soKeepAlive = false;
309             this.tcpNoDelay = true;
310             this.sndBufSize = 0;
311             this.rcvBufSize = 0;
312             this.backlogSize = 0;
313             this.socksProxyAddress = null;
314             this.socksProxyUsername = null;
315             this.socksProxyPassword = null;
316         }
317 
318         public Builder setSelectInterval(final TimeValue selectInterval) {
319             this.selectInterval = selectInterval;
320             return this;
321         }
322 
323         public Builder setIoThreadCount(final int ioThreadCount) {
324             this.ioThreadCount = ioThreadCount;
325             return this;
326         }
327 
328         public Builder setSoTimeout(final int soTimeout, final TimeUnit timeUnit) {
329             this.soTimeout = Timeout.of(soTimeout, timeUnit);
330             return this;
331         }
332 
333         public Builder setSoTimeout(final Timeout soTimeout) {
334             this.soTimeout = soTimeout;
335             return this;
336         }
337 
338         public Builder setSoReuseAddress(final boolean soReuseAddress) {
339             this.soReuseAddress = soReuseAddress;
340             return this;
341         }
342 
343         public Builder setSoLinger(final int soLinger, final TimeUnit timeUnit) {
344             this.soLinger = TimeValue.of(soLinger, timeUnit);
345             return this;
346         }
347 
348         public Builder setSoLinger(final TimeValue soLinger) {
349             this.soLinger = soLinger;
350             return this;
351         }
352 
353         public Builder setSoKeepAlive(final boolean soKeepAlive) {
354             this.soKeepAlive = soKeepAlive;
355             return this;
356         }
357 
358         public Builder setTcpNoDelay(final boolean tcpNoDelay) {
359             this.tcpNoDelay = tcpNoDelay;
360             return this;
361         }
362 
363         public Builder setSndBufSize(final int sndBufSize) {
364             this.sndBufSize = sndBufSize;
365             return this;
366         }
367 
368         public Builder setRcvBufSize(final int rcvBufSize) {
369             this.rcvBufSize = rcvBufSize;
370             return this;
371         }
372 
373         public Builder setBacklogSize(final int backlogSize) {
374             this.backlogSize = backlogSize;
375             return this;
376         }
377 
378         public Builder setSocksProxyAddress(final SocketAddress socksProxyAddress) {
379             this.socksProxyAddress = socksProxyAddress;
380             return this;
381         }
382 
383         public Builder setSocksProxyUsername(final String socksProxyUsername) {
384             this.socksProxyUsername = socksProxyUsername;
385             return this;
386         }
387 
388         public Builder setSocksProxyPassword(final String socksProxyPassword) {
389             this.socksProxyPassword = socksProxyPassword;
390             return this;
391         }
392 
393         public IOReactorConfig build() {
394             return new IOReactorConfig(
395                     selectInterval != null ? selectInterval : TimeValue.ofSeconds(1),
396                     ioThreadCount,
397                     Timeout.defaultsToDisabled(soTimeout),
398                     soReuseAddress,
399                     TimeValue.defaultsToNegativeOneMillisecond(soLinger),
400                     soKeepAlive,
401                     tcpNoDelay,
402                     sndBufSize, rcvBufSize, backlogSize,
403                     socksProxyAddress, socksProxyUsername, socksProxyPassword);
404         }
405 
406     }
407 
408     @Override
409     public String toString() {
410         final StringBuilder builder = new StringBuilder();
411         builder.append("[selectIntervalMillis=").append(this.selectInterval)
412                 .append(", ioThreadCount=").append(this.ioThreadCount)
413                 .append(", soTimeout=").append(this.soTimeout)
414                 .append(", soReuseAddress=").append(this.soReuseAddress)
415                 .append(", soLinger=").append(this.soLinger)
416                 .append(", soKeepAlive=").append(this.soKeepAlive)
417                 .append(", tcpNoDelay=").append(this.tcpNoDelay)
418                 .append(", sndBufSize=").append(this.sndBufSize)
419                 .append(", rcvBufSize=").append(this.rcvBufSize)
420                 .append(", backlogSize=").append(this.backlogSize)
421                 .append(", socksProxyAddress=").append(this.socksProxyAddress)
422                 .append("]");
423         return builder.toString();
424     }
425 
426 }