001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027
028package org.apache.http.impl.nio.reactor;
029
030import org.apache.http.util.Args;
031
032/**
033 * I/O reactor configuration parameters.
034 *
035 * @since 4.2
036 */
037public final class IOReactorConfig implements Cloneable {
038
039    private static final int AVAIL_PROCS = Runtime.getRuntime().availableProcessors();
040
041    public static final IOReactorConfig DEFAULT = new Builder().build();
042
043    // TODO: make final
044    private long selectInterval;
045    private long shutdownGracePeriod;
046    private boolean interestOpQueued;
047    private int ioThreadCount;
048    private int soTimeout;
049    private boolean soReuseAddress;
050    private int soLinger;
051    private boolean soKeepAlive;
052    private boolean tcpNoDelay;
053    private int connectTimeout;
054    private int sndBufSize;
055    private int rcvBufSize;
056    private final int backlogSize;
057
058    @Deprecated
059    public IOReactorConfig() {
060        super();
061        this.selectInterval = 1000;
062        this.shutdownGracePeriod = 500;
063        this.interestOpQueued = false;
064        this.ioThreadCount = AVAIL_PROCS;
065        this.soTimeout = 0;
066        this.soReuseAddress = false;
067        this.soLinger = -1;
068        this.soKeepAlive = false;
069        this.tcpNoDelay = true;
070        this.connectTimeout = 0;
071        this.sndBufSize = 0;
072        this.rcvBufSize = 0;
073        this.backlogSize = 0;
074    }
075
076    IOReactorConfig(
077            final long selectInterval,
078            final long shutdownGracePeriod,
079            final boolean interestOpQueued,
080            final int ioThreadCount,
081            final int soTimeout,
082            final boolean soReuseAddress,
083            final int soLinger,
084            final boolean soKeepAlive,
085            final boolean tcpNoDelay,
086            final int connectTimeout,
087            final int sndBufSize,
088            final int rcvBufSize,
089            final int backlogSize) {
090        super();
091        this.selectInterval = selectInterval;
092        this.shutdownGracePeriod = shutdownGracePeriod;
093        this.interestOpQueued = interestOpQueued;
094        this.ioThreadCount = ioThreadCount;
095        this.soTimeout = soTimeout;
096        this.soReuseAddress = soReuseAddress;
097        this.soLinger = soLinger;
098        this.soKeepAlive = soKeepAlive;
099        this.tcpNoDelay = tcpNoDelay;
100        this.connectTimeout = connectTimeout;
101        this.sndBufSize = sndBufSize;
102        this.rcvBufSize = rcvBufSize;
103        this.backlogSize = backlogSize;
104    }
105
106    /**
107     * Determines time interval in milliseconds at which the I/O reactor wakes up to check for
108     * timed out sessions and session requests.
109     * <p>
110     * Default: {@code 1000} milliseconds.
111     */
112    public long getSelectInterval() {
113        return this.selectInterval;
114    }
115
116    /**
117     * @deprecated (4.3) use {@link Builder#setSelectInterval(long)}
118     */
119    @Deprecated
120    public void setSelectInterval(final long selectInterval) {
121        Args.positive(selectInterval, "Select internal");
122        this.selectInterval = selectInterval;
123    }
124
125    /**
126     * Determines grace period in milliseconds the I/O reactors are expected to block waiting
127     * for individual worker threads to terminate cleanly.
128     * <p>
129     * Default: {@code 500} milliseconds.
130     */
131    public long getShutdownGracePeriod() {
132        return this.shutdownGracePeriod;
133    }
134
135    /**
136     * @deprecated (4.3) use {@link Builder#setShutdownGracePeriod(long)}
137     */
138    @Deprecated
139    public void setShutdownGracePeriod(final long gracePeriod) {
140        Args.positive(gracePeriod, "Shutdown grace period");
141        this.shutdownGracePeriod = gracePeriod;
142    }
143
144    /**
145     * Determines whether or not I/O interest operations are to be queued and executed
146     * asynchronously by the I/O reactor thread or to be applied to the underlying
147     * {@link java.nio.channels.SelectionKey} immediately.
148     * <p>
149     * Default: {@code false}
150     *
151     * @see java.nio.channels.SelectionKey
152     * @see java.nio.channels.SelectionKey#interestOps()
153     * @see java.nio.channels.SelectionKey#interestOps(int)
154     */
155    public boolean isInterestOpQueued() {
156        return this.interestOpQueued;
157    }
158
159    /**
160     * @deprecated (4.3) use {@link Builder#setInterestOpQueued(boolean)}
161     */
162    @Deprecated
163    public void setInterestOpQueued(final boolean interestOpQueued) {
164        this.interestOpQueued = interestOpQueued;
165    }
166
167    /**
168     * Determines the number of I/O dispatch threads to be used by the I/O reactor.
169     * <p>
170     * Default: {@code 2}
171     */
172    public int getIoThreadCount() {
173        return this.ioThreadCount;
174    }
175
176    /**
177     * @deprecated (4.3) use {@link Builder#setIoThreadCount(int)}
178     */
179    @Deprecated
180    public void setIoThreadCount(final int ioThreadCount) {
181        Args.positive(ioThreadCount, "I/O thread count");
182        this.ioThreadCount = ioThreadCount;
183    }
184
185    /**
186     * Determines the default socket timeout value for non-blocking I/O operations.
187     * <p>
188     * Default: {@code 0} (no timeout)
189     *
190     * @see java.net.SocketOptions#SO_TIMEOUT
191     */
192    public int getSoTimeout() {
193        return soTimeout;
194    }
195
196    /**
197     * @deprecated (4.3) use {@link Builder#setSoTimeout(int)}
198     */
199    @Deprecated
200    public void setSoTimeout(final int soTimeout) {
201        this.soTimeout = soTimeout;
202    }
203
204    /**
205     * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
206     * for newly created sockets.
207     * <p>
208     * Default: {@code false}
209     *
210     * @see java.net.SocketOptions#SO_REUSEADDR
211     */
212    public boolean isSoReuseAddress() {
213        return soReuseAddress;
214    }
215
216    /**
217     * @deprecated (4.3) use {@link Builder#setSoReuseAddress(boolean)}
218     */
219    @Deprecated
220    public void setSoReuseAddress(final boolean soReuseAddress) {
221        this.soReuseAddress = soReuseAddress;
222    }
223
224    /**
225     * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
226     * for newly created sockets.
227     * <p>
228     * Default: {@code -1}
229     *
230     * @see java.net.SocketOptions#SO_LINGER
231     */
232    public int getSoLinger() {
233        return soLinger;
234    }
235
236    /**
237     * @deprecated (4.3) use {@link Builder#setSoLinger(int)}
238     */
239    @Deprecated
240    public void setSoLinger(final int soLinger) {
241        this.soLinger = soLinger;
242    }
243
244    /**
245     * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
246     * for newly created sockets.
247     * <p>
248     * Default: {@code -1}
249     *
250     * @see java.net.SocketOptions#SO_KEEPALIVE
251     */
252    public boolean isSoKeepalive() {
253        return this.soKeepAlive;
254    }
255
256    /**
257     * @deprecated (4.3) use {@link Builder#setSoKeepAlive(boolean)}
258     */
259    @Deprecated
260    public void setSoKeepalive(final boolean soKeepAlive) {
261        this.soKeepAlive = soKeepAlive;
262    }
263
264    /**
265     * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
266     * for newly created sockets.
267     * <p>
268     * Default: {@code false}
269     *
270     * @see java.net.SocketOptions#TCP_NODELAY
271     */
272    public boolean isTcpNoDelay() {
273        return tcpNoDelay;
274    }
275
276    /**
277     * @deprecated (4.3) use {@link Builder#setTcpNoDelay(boolean)}
278     */
279    @Deprecated
280    public void setTcpNoDelay(final boolean tcpNoDelay) {
281        this.tcpNoDelay = tcpNoDelay;
282    }
283
284    /**
285     * Determines the default connect timeout value for non-blocking connection requests.
286     * <p>
287     * Default: {@code 0} (no timeout)
288     */
289    public int getConnectTimeout() {
290        return connectTimeout;
291    }
292
293    /**
294     * @deprecated (4.3) use {@link Builder#setConnectTimeout(int)}
295     */
296    @Deprecated
297    public void setConnectTimeout(final int connectTimeout) {
298        this.connectTimeout = connectTimeout;
299    }
300
301    /**
302     * Determines the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter
303     * for newly created sockets.
304     * <p>
305     * Default: {@code 0} (system default)
306     *
307     * @see java.net.SocketOptions#SO_SNDBUF
308     */
309    public int getSndBufSize() {
310        return sndBufSize;
311    }
312
313    /**
314     * @deprecated (4.3) use {@link Builder#setSndBufSize(int)}
315     */
316    @Deprecated
317    public void setSndBufSize(final int sndBufSize) {
318        this.sndBufSize = sndBufSize;
319    }
320
321    /**
322     * Determines the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter
323     * for newly created sockets.
324     * <p>
325     * Default: {@code 0} (system default)
326     *
327     * @see java.net.SocketOptions#SO_RCVBUF
328     */
329    public int getRcvBufSize() {
330        return rcvBufSize;
331    }
332
333    /**
334     * @deprecated (4.3) use {@link Builder#setRcvBufSize(int)}
335     */
336    @Deprecated
337    public void setRcvBufSize(final int rcvBufSize) {
338        this.rcvBufSize = rcvBufSize;
339    }
340
341    /**
342     * Determines the default backlog size value for server sockets binds.
343     * <p>
344     * Default: {@code 0} (system default)
345     *
346     * @since 4.4
347     */
348    public int getBacklogSize() {
349        return backlogSize;
350    }
351
352    @Override
353    protected IOReactorConfig clone() throws CloneNotSupportedException {
354        return (IOReactorConfig) super.clone();
355    }
356
357    public static Builder custom() {
358        return new Builder();
359    }
360
361    public static Builder copy(final IOReactorConfig config) {
362        Args.notNull(config, "I/O reactor config");
363        return new Builder()
364            .setSelectInterval(config.getSelectInterval())
365            .setShutdownGracePeriod(config.getShutdownGracePeriod())
366            .setInterestOpQueued(config.isInterestOpQueued())
367            .setIoThreadCount(config.getIoThreadCount())
368            .setSoTimeout(config.getSoTimeout())
369            .setSoReuseAddress(config.isSoReuseAddress())
370            .setSoLinger(config.getSoLinger())
371            .setSoKeepAlive(config.isSoKeepalive())
372            .setTcpNoDelay(config.isTcpNoDelay())
373            .setConnectTimeout(config.getConnectTimeout())
374            .setSndBufSize(config.getSndBufSize())
375            .setRcvBufSize(config.getRcvBufSize())
376            .setBacklogSize(config.getBacklogSize());
377    }
378
379    public static class Builder {
380
381        private long selectInterval;
382        private long shutdownGracePeriod;
383        private boolean interestOpQueued;
384        private int ioThreadCount;
385        private int soTimeout;
386        private boolean soReuseAddress;
387        private int soLinger;
388        private boolean soKeepAlive;
389        private boolean tcpNoDelay;
390        private int connectTimeout;
391        private int sndBufSize;
392        private int rcvBufSize;
393        private int backlogSize;
394
395        Builder() {
396            this.selectInterval = 1000;
397            this.shutdownGracePeriod = 500;
398            this.interestOpQueued = false;
399            this.ioThreadCount = AVAIL_PROCS;
400            this.soTimeout = 0;
401            this.soReuseAddress = false;
402            this.soLinger = -1;
403            this.soKeepAlive = false;
404            this.tcpNoDelay = true;
405            this.connectTimeout = 0;
406            this.sndBufSize = 0;
407            this.rcvBufSize = 0;
408            this.backlogSize = 0;
409        }
410
411        public Builder setSelectInterval(final long selectInterval) {
412            this.selectInterval = selectInterval;
413            return this;
414        }
415
416        public Builder setShutdownGracePeriod(final long shutdownGracePeriod) {
417            this.shutdownGracePeriod = shutdownGracePeriod;
418            return this;
419        }
420
421        public Builder setInterestOpQueued(final boolean interestOpQueued) {
422            this.interestOpQueued = interestOpQueued;
423            return this;
424        }
425
426        public Builder setIoThreadCount(final int ioThreadCount) {
427            this.ioThreadCount = ioThreadCount;
428            return this;
429        }
430
431        public Builder setSoTimeout(final int soTimeout) {
432            this.soTimeout = soTimeout;
433            return this;
434        }
435
436        public Builder setSoReuseAddress(final boolean soReuseAddress) {
437            this.soReuseAddress = soReuseAddress;
438            return this;
439        }
440
441        public Builder setSoLinger(final int soLinger) {
442            this.soLinger = soLinger;
443            return this;
444        }
445
446        public Builder setSoKeepAlive(final boolean soKeepAlive) {
447            this.soKeepAlive = soKeepAlive;
448            return this;
449        }
450
451        public Builder setTcpNoDelay(final boolean tcpNoDelay) {
452            this.tcpNoDelay = tcpNoDelay;
453            return this;
454        }
455
456        public Builder setConnectTimeout(final int connectTimeout) {
457            this.connectTimeout = connectTimeout;
458            return this;
459        }
460
461        public Builder setSndBufSize(final int sndBufSize) {
462            this.sndBufSize = sndBufSize;
463            return this;
464        }
465
466        public Builder setRcvBufSize(final int rcvBufSize) {
467            this.rcvBufSize = rcvBufSize;
468            return this;
469        }
470
471        public Builder setBacklogSize(final int backlogSize) {
472            this.backlogSize = backlogSize;
473            return this;
474        }
475
476        public IOReactorConfig build() {
477            return new IOReactorConfig(
478                    selectInterval, shutdownGracePeriod, interestOpQueued, ioThreadCount,
479                    soTimeout, soReuseAddress, soLinger, soKeepAlive, tcpNoDelay,
480                    connectTimeout, sndBufSize, rcvBufSize, backlogSize);
481        }
482
483    }
484
485    @Override
486    public String toString() {
487        final StringBuilder builder = new StringBuilder();
488        builder.append("[selectInterval=").append(this.selectInterval)
489                .append(", shutdownGracePeriod=").append(this.shutdownGracePeriod)
490                .append(", interestOpQueued=").append(this.interestOpQueued)
491                .append(", ioThreadCount=").append(this.ioThreadCount)
492                .append(", soTimeout=").append(this.soTimeout)
493                .append(", soReuseAddress=").append(this.soReuseAddress)
494                .append(", soLinger=").append(this.soLinger)
495                .append(", soKeepAlive=").append(this.soKeepAlive)
496                .append(", tcpNoDelay=").append(this.tcpNoDelay)
497                .append(", connectTimeout=").append(this.connectTimeout)
498                .append(", sndBufSize=").append(this.sndBufSize)
499                .append(", rcvBufSize=").append(this.rcvBufSize)
500                .append(", backlogSize=").append(this.backlogSize)
501                .append("]");
502        return builder.toString();
503    }
504
505}