View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.channel.socket.oio;
17  
18  import java.util.concurrent.Executor;
19  import java.util.concurrent.RejectedExecutionException;
20  
21  import org.jboss.netty.channel.Channel;
22  import org.jboss.netty.channel.ChannelPipeline;
23  import org.jboss.netty.channel.ChannelSink;
24  import org.jboss.netty.channel.group.ChannelGroup;
25  import org.jboss.netty.channel.socket.ServerSocketChannel;
26  import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
27  import org.jboss.netty.util.internal.ExecutorUtil;
28  
29  /**
30   * A {@link ServerSocketChannelFactory} which creates a server-side blocking
31   * I/O based {@link ServerSocketChannel}.  It utilizes the good old blocking
32   * I/O API which is known to yield better throughput and latency when there
33   * are relatively small number of connections to serve.
34   *
35   * <h3>How threads work</h3>
36   * <p>
37   * There are two types of threads in a {@link OioServerSocketChannelFactory};
38   * one is boss thread and the other is worker thread.
39   *
40   * <h4>Boss threads</h4>
41   * <p>
42   * Each bound {@link ServerSocketChannel} has its own boss thread.
43   * For example, if you opened two server ports such as 80 and 443, you will
44   * have two boss threads.  A boss thread accepts incoming connections until
45   * the port is unbound.  Once a connection is accepted successfully, the boss
46   * thread passes the accepted {@link Channel} to one of the worker
47   * threads that the {@link OioServerSocketChannelFactory} manages.
48   *
49   * <h4>Worker threads</h4>
50   * <p>
51   * Each connected {@link Channel} has a dedicated worker thread, just like a
52   * traditional blocking I/O thread model.
53   *
54   * <h3>Life cycle of threads and graceful shutdown</h3>
55   * <p>
56   * All threads are acquired from the {@link Executor}s which were specified
57   * when a {@link OioServerSocketChannelFactory} was created.  Boss threads are
58   * acquired from the {@code bossExecutor}, and worker threads are acquired from
59   * the {@code workerExecutor}.  Therefore, you should make sure the specified
60   * {@link Executor}s are able to lend the sufficient number of threads.
61   * <p>
62   * Both boss and worker threads are acquired lazily, and then released when
63   * there's nothing left to process.  All the related resources are also
64   * released when the boss and worker threads are released.  Therefore, to shut
65   * down a service gracefully, you should do the following:
66   *
67   * <ol>
68   * <li>unbind all channels created by the factory,
69   * <li>close all child channels accepted by the unbound channels,
70   *     (these two steps so far is usually done using {@link ChannelGroup#close()})</li>
71   * <li>call {@link #releaseExternalResources()}.</li>
72   * </ol>
73   *
74   * Please make sure not to shut down the executor until all channels are
75   * closed.  Otherwise, you will end up with a {@link RejectedExecutionException}
76   * and the related resources might not be released properly.
77   *
78   * <h3>Limitation</h3>
79   * <p>
80   * A {@link ServerSocketChannel} created by this factory and its child channels
81   * do not support asynchronous operations.  Any I/O requests such as
82   * {@code "write"} will be performed in a blocking manner.
83   *
84   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
85   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
86   *
87   * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
88   *
89   * @apiviz.landmark
90   */
91  public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
92  
93      final Executor bossExecutor;
94      private final Executor workerExecutor;
95      private final ChannelSink sink;
96  
97      /**
98       * Creates a new instance.
99       *
100      * @param bossExecutor
101      *        the {@link Executor} which will execute the boss threads
102      * @param workerExecutor
103      *        the {@link Executor} which will execute the I/O worker threads
104      */
105     public OioServerSocketChannelFactory(
106             Executor bossExecutor, Executor workerExecutor) {
107         if (bossExecutor == null) {
108             throw new NullPointerException("bossExecutor");
109         }
110         if (workerExecutor == null) {
111             throw new NullPointerException("workerExecutor");
112         }
113         this.bossExecutor = bossExecutor;
114         this.workerExecutor = workerExecutor;
115         sink = new OioServerSocketPipelineSink(workerExecutor);
116     }
117 
118     public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
119         return new OioServerSocketChannel(this, pipeline, sink);
120     }
121 
122     public void releaseExternalResources() {
123         ExecutorUtil.terminate(bossExecutor, workerExecutor);
124     }
125 }