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      private static final int AVAIL_PROCS = Runtime.getRuntime().availableProcessors();
47  
48      public static final IOReactorConfig DEFAULT = new Builder().build();
49  
50      private final long selectInterval;
51      private final int ioThreadCount;
52      private final Timeout  soTimeout;
53      private final boolean soReuseAddress;
54      private final TimeValue soLinger;
55      private final boolean soKeepAlive;
56      private final boolean tcpNoDelay;
57      private final int sndBufSize;
58      private final int rcvBufSize;
59      private final int backlogSize;
60  
61      IOReactorConfig(
62              final long selectInterval,
63              final int ioThreadCount,
64              final Timeout soTimeout,
65              final boolean soReuseAddress,
66              final TimeValue soLinger,
67              final boolean soKeepAlive,
68              final boolean tcpNoDelay,
69              final int sndBufSize,
70              final int rcvBufSize,
71              final int backlogSize) {
72          super();
73          this.selectInterval = selectInterval;
74          this.ioThreadCount = ioThreadCount;
75          this.soTimeout = soTimeout;
76          this.soReuseAddress = soReuseAddress;
77          this.soLinger = soLinger;
78          this.soKeepAlive = soKeepAlive;
79          this.tcpNoDelay = tcpNoDelay;
80          this.sndBufSize = sndBufSize;
81          this.rcvBufSize = rcvBufSize;
82          this.backlogSize = backlogSize;
83      }
84  
85      /**
86       * Determines time interval in milliseconds at which the I/O reactor wakes up to check for
87       * timed out sessions and session requests.
88       * <p>
89       * Default: {@code 1000} milliseconds.
90       */
91      public long getSelectInterval() {
92          return this.selectInterval;
93      }
94  
95      /**
96       * Determines the number of I/O dispatch threads to be used by the I/O reactor.
97       * <p>
98       * Default: {@code 2}
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      *
109      * @see java.net.SocketOptions#SO_TIMEOUT
110      */
111     public Timeout getSoTimeout() {
112         return soTimeout;
113     }
114 
115     /**
116      * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
117      * for newly created sockets.
118      * <p>
119      * Default: {@code false}
120      *
121      * @see java.net.SocketOptions#SO_REUSEADDR
122      */
123     public boolean isSoReuseAddress() {
124         return soReuseAddress;
125     }
126 
127     /**
128      * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
129      * for newly created sockets.
130      * <p>
131      * Default: {@code -1}
132      *
133      * @see java.net.SocketOptions#SO_LINGER
134      */
135     public TimeValue getSoLinger() {
136         return soLinger;
137     }
138 
139     /**
140      * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
141      * for newly created sockets.
142      * <p>
143      * Default: {@code -1}
144      *
145      * @see java.net.SocketOptions#SO_KEEPALIVE
146      */
147     public boolean isSoKeepalive() {
148         return this.soKeepAlive;
149     }
150 
151     /**
152      * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
153      * for newly created sockets.
154      * <p>
155      * Default: {@code false}
156      *
157      * @see java.net.SocketOptions#TCP_NODELAY
158      */
159     public boolean isTcpNoDelay() {
160         return tcpNoDelay;
161     }
162 
163     /**
164      * Determines the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter
165      * for newly created sockets.
166      * <p>
167      * Default: {@code 0} (system default)
168      *
169      * @see java.net.SocketOptions#SO_SNDBUF
170      */
171     public int getSndBufSize() {
172         return sndBufSize;
173     }
174 
175     /**
176      * Determines the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter
177      * for newly created sockets.
178      * <p>
179      * Default: {@code 0} (system default)
180      *
181      * @see java.net.SocketOptions#SO_RCVBUF
182      */
183     public int getRcvBufSize() {
184         return rcvBufSize;
185     }
186 
187     /**
188      * Determines the default backlog size value for server sockets binds.
189      * <p>
190      * Default: {@code 0} (system default)
191      *
192      * @since 4.4
193      */
194     public int getBacklogSize() {
195         return backlogSize;
196     }
197 
198     public static Builder custom() {
199         return new Builder();
200     }
201 
202     public static Builder copy(final IOReactorConfig config) {
203         Args.notNull(config, "I/O reactor config");
204         return new Builder()
205             .setSelectInterval(config.getSelectInterval())
206             .setIoThreadCount(config.getIoThreadCount())
207             .setSoTimeout(config.getSoTimeout())
208             .setSoReuseAddress(config.isSoReuseAddress())
209             .setSoLinger(config.getSoLinger())
210             .setSoKeepAlive(config.isSoKeepalive())
211             .setTcpNoDelay(config.isTcpNoDelay())
212             .setSndBufSize(config.getSndBufSize())
213             .setRcvBufSize(config.getRcvBufSize())
214             .setBacklogSize(config.getBacklogSize());
215     }
216 
217     public static class Builder {
218 
219         private long selectInterval;
220         private int ioThreadCount;
221         private Timeout  soTimeout;
222         private boolean soReuseAddress;
223         private TimeValue soLinger;
224         private boolean soKeepAlive;
225         private boolean tcpNoDelay;
226         private int sndBufSize;
227         private int rcvBufSize;
228         private int backlogSize;
229 
230         Builder() {
231             this.selectInterval = 1000;
232             this.ioThreadCount = AVAIL_PROCS;
233             this.soTimeout = Timeout.ZERO_MILLISECONDS;
234             this.soReuseAddress = false;
235             this.soLinger = TimeValue.NEG_ONE_SECONDS;
236             this.soKeepAlive = false;
237             this.tcpNoDelay = true;
238             this.sndBufSize = 0;
239             this.rcvBufSize = 0;
240             this.backlogSize = 0;
241         }
242 
243         public Builder setSelectInterval(final long selectInterval) {
244             this.selectInterval = selectInterval;
245             return this;
246         }
247 
248         public Builder setIoThreadCount(final int ioThreadCount) {
249             this.ioThreadCount = ioThreadCount;
250             return this;
251         }
252 
253         public Builder setSoTimeout(final int soTimeout, final TimeUnit timeUnit) {
254             this.soTimeout = Timeout.of(soTimeout, timeUnit);
255             return this;
256         }
257 
258         public Builder setSoTimeout(final Timeout soTimeout) {
259             this.soTimeout = soTimeout;
260             return this;
261         }
262 
263         public Builder setSoReuseAddress(final boolean soReuseAddress) {
264             this.soReuseAddress = soReuseAddress;
265             return this;
266         }
267 
268         public Builder setSoLinger(final int soLinger, final TimeUnit timeUnit) {
269             this.soLinger = TimeValue.of(soLinger, timeUnit);
270             return this;
271         }
272 
273         public Builder setSoLinger(final TimeValue soLinger) {
274             this.soLinger = soLinger;
275             return this;
276         }
277 
278         public Builder setSoKeepAlive(final boolean soKeepAlive) {
279             this.soKeepAlive = soKeepAlive;
280             return this;
281         }
282 
283         public Builder setTcpNoDelay(final boolean tcpNoDelay) {
284             this.tcpNoDelay = tcpNoDelay;
285             return this;
286         }
287 
288         public Builder setSndBufSize(final int sndBufSize) {
289             this.sndBufSize = sndBufSize;
290             return this;
291         }
292 
293         public Builder setRcvBufSize(final int rcvBufSize) {
294             this.rcvBufSize = rcvBufSize;
295             return this;
296         }
297 
298         public Builder setBacklogSize(final int backlogSize) {
299             this.backlogSize = backlogSize;
300             return this;
301         }
302 
303         public IOReactorConfig build() {
304             return new IOReactorConfig(
305                     selectInterval, ioThreadCount,
306                     Timeout.defaultsToDisabled(soTimeout),
307                     soReuseAddress,
308                     TimeValue.defaultsToNegativeOneMillisecond(soLinger),
309                     soKeepAlive,
310                     tcpNoDelay,
311                     sndBufSize, rcvBufSize, backlogSize);
312         }
313 
314     }
315 
316     @Override
317     public String toString() {
318         final StringBuilder builder = new StringBuilder();
319         builder.append("[selectInterval=").append(this.selectInterval)
320                 .append(", ioThreadCount=").append(this.ioThreadCount)
321                 .append(", soTimeout=").append(this.soTimeout)
322                 .append(", soReuseAddress=").append(this.soReuseAddress)
323                 .append(", soLinger=").append(this.soLinger)
324                 .append(", soKeepAlive=").append(this.soKeepAlive)
325                 .append(", tcpNoDelay=").append(this.tcpNoDelay)
326                 .append(", sndBufSize=").append(this.sndBufSize)
327                 .append(", rcvBufSize=").append(this.rcvBufSize)
328                 .append(", backlogSize=").append(this.backlogSize)
329                 .append("]");
330         return builder.toString();
331     }
332 
333 }