Resolved issue: NETTY-84 Replace ChannelFactory.getExternalResource() with ChannelFactory.releaseExternalResources()
This commit is contained in:
parent
3e09a4ee60
commit
0830444fc8
@ -103,7 +103,7 @@ import org.jboss.netty.channel.SimpleChannelHandler;
|
|||||||
* {@link ClientBootstrap} instances as you want to apply different settings
|
* {@link ClientBootstrap} instances as you want to apply different settings
|
||||||
* for different {@link Channel}s.
|
* for different {@link Channel}s.
|
||||||
*
|
*
|
||||||
* TODO: Show how to shut down a service using ChannelFactoryResource.release().
|
* TODO: Show how to shut down a service.
|
||||||
*
|
*
|
||||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||||
* @author Trustin Lee (tlee@redhat.com)
|
* @author Trustin Lee (tlee@redhat.com)
|
||||||
|
@ -137,7 +137,7 @@ import org.jboss.netty.channel.SimpleChannelHandler;
|
|||||||
* {@link ServerBootstrap} instances as you want to apply different settings
|
* {@link ServerBootstrap} instances as you want to apply different settings
|
||||||
* for different {@link Channel}s.
|
* for different {@link Channel}s.
|
||||||
*
|
*
|
||||||
* TODO: Show how to shut down a service using ChannelFactoryResource.release().
|
* TODO: Show how to shut down a service.
|
||||||
*
|
*
|
||||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||||
* @author Trustin Lee (tlee@redhat.com)
|
* @author Trustin Lee (tlee@redhat.com)
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.jboss.netty.channel;
|
package org.jboss.netty.channel;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +38,17 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
|||||||
* is attached to the new {@link Channel}, and starts to handle all associated
|
* is attached to the new {@link Channel}, and starts to handle all associated
|
||||||
* {@link ChannelEvent}s.
|
* {@link ChannelEvent}s.
|
||||||
*
|
*
|
||||||
* TODO: Document how to shut down a service using ChannelFactoryResource.
|
* <h3>Graceful shutdown</h3>
|
||||||
|
* <p>
|
||||||
|
* To shut down a network application service which is managed by a factory.
|
||||||
|
* you should follow the following steps:
|
||||||
|
* <ol>
|
||||||
|
* <li>close all channels created by the factory and their child channels, and</li>
|
||||||
|
* <li>call {@link #releaseExternalResources()}.</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>
|
||||||
|
* For detailed transport-specific information on shutting down a factory,
|
||||||
|
* please refer to the Javadoc of {@link ChannelFactory}'s subtypes.
|
||||||
*
|
*
|
||||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||||
* @author Trustin Lee (tlee@redhat.com)
|
* @author Trustin Lee (tlee@redhat.com)
|
||||||
@ -62,12 +74,14 @@ public interface ChannelFactory {
|
|||||||
Channel newChannel(ChannelPipeline pipeline);
|
Channel newChannel(ChannelPipeline pipeline);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the external resources that this factory depends on to function.
|
* Releases the external resources that this factory depends on to function.
|
||||||
* Please note that {@link ChannelFactoryResource#release()} can be called
|
* An external resource is a resource that this factory didn't create by
|
||||||
* to release all external resources conveniently when the resources are not
|
* itself. For example, {@link Executor}s that you specified in the factory
|
||||||
* used by this factory or any other part of your application.
|
* constructor are external resources. You can call this method to release
|
||||||
* An unexpected behavior will be resulted in if the returned resources are
|
* all external resources conveniently when the resources are not used by
|
||||||
* released when there's an open channel which is managed by this factory.
|
* this factory or any other part of your application. An unexpected
|
||||||
|
* behavior will be resulted in if the resources are released when there's
|
||||||
|
* an open channel which is managed by this factory.
|
||||||
*/
|
*/
|
||||||
ChannelFactoryResource getExternalResource();
|
void releaseExternalResources();
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
*
|
|
||||||
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
|
||||||
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* This is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this software; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
|
||||||
*/
|
|
||||||
package org.jboss.netty.channel;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The abstract representation of external resources that a
|
|
||||||
* {@link ChannelFactory} depends on. A user can release the external
|
|
||||||
* resources such as {@link ExecutorService}s conveniently.
|
|
||||||
*
|
|
||||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
|
||||||
* @author Trustin Lee (tlee@redhat.com)
|
|
||||||
*
|
|
||||||
* @version $Rev$, $Date$
|
|
||||||
*
|
|
||||||
* @apiviz.exclude
|
|
||||||
*/
|
|
||||||
public interface ChannelFactoryResource {
|
|
||||||
/**
|
|
||||||
* Releases this resource.
|
|
||||||
*/
|
|
||||||
void release();
|
|
||||||
}
|
|
@ -44,8 +44,8 @@ class DefaultNioSocketChannelConfig extends DefaultSocketChannelConfig
|
|||||||
private static final InternalLogger logger =
|
private static final InternalLogger logger =
|
||||||
InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class);
|
InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class);
|
||||||
|
|
||||||
private volatile int writeBufferHighWaterMark = 256 * 1024;
|
private volatile int writeBufferHighWaterMark = 64 * 1024;
|
||||||
private volatile int writeBufferLowWaterMark = 128 * 1024;
|
private volatile int writeBufferLowWaterMark = 32 * 1024;
|
||||||
private volatile ReceiveBufferSizePredictor predictor =
|
private volatile ReceiveBufferSizePredictor predictor =
|
||||||
new DefaultReceiveBufferSizePredictor();
|
new DefaultReceiveBufferSizePredictor();
|
||||||
private volatile int writeSpinCount = 16;
|
private volatile int writeSpinCount = 16;
|
||||||
|
@ -24,18 +24,15 @@ package org.jboss.netty.channel.socket.nio;
|
|||||||
|
|
||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
|
|
||||||
import org.jboss.netty.channel.ChannelFactoryResource;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
import org.jboss.netty.channel.ChannelSink;
|
import org.jboss.netty.channel.ChannelSink;
|
||||||
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
||||||
import org.jboss.netty.channel.socket.SocketChannel;
|
import org.jboss.netty.channel.socket.SocketChannel;
|
||||||
|
import org.jboss.netty.util.ExecutorShutdownUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ClientSocketChannelFactory} which creates a client-side NIO-based
|
* A {@link ClientSocketChannelFactory} which creates a client-side NIO-based
|
||||||
@ -62,7 +59,6 @@ import org.jboss.netty.channel.socket.SocketChannel;
|
|||||||
* more {@link Channel}s in a non-blocking mode.
|
* more {@link Channel}s in a non-blocking mode.
|
||||||
*
|
*
|
||||||
* <h3>Life cycle of threads and graceful shutdown</h3>
|
* <h3>Life cycle of threads and graceful shutdown</h3>
|
||||||
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
|
|
||||||
* <p>
|
* <p>
|
||||||
* All threads are acquired from the {@link Executor}s which were specified
|
* All threads are acquired from the {@link Executor}s which were specified
|
||||||
* when a {@link NioClientSocketChannelFactory} was created. A boss thread is
|
* when a {@link NioClientSocketChannelFactory} was created. A boss thread is
|
||||||
@ -78,11 +74,8 @@ import org.jboss.netty.channel.socket.SocketChannel;
|
|||||||
* following:
|
* following:
|
||||||
*
|
*
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>close all channels created by the factory,</li>
|
* <li>close all channels created by the factory, and</li>
|
||||||
* <li>call {@link ExecutorService#shutdownNow()} or {@link ExecutorService#shutdown()}
|
* <li>call {@link #releaseExternalResources()}.</li>
|
||||||
* for all executors which were specified to create the factory, and</li>
|
|
||||||
* <li>call {@link ExecutorService#awaitTermination(long, TimeUnit)}
|
|
||||||
* until it returns {@code true}.</li>
|
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* Please make sure not to shut down the executor until all channels are
|
* Please make sure not to shut down the executor until all channels are
|
||||||
@ -98,7 +91,8 @@ import org.jboss.netty.channel.socket.SocketChannel;
|
|||||||
*/
|
*/
|
||||||
public class NioClientSocketChannelFactory implements ClientSocketChannelFactory {
|
public class NioClientSocketChannelFactory implements ClientSocketChannelFactory {
|
||||||
|
|
||||||
private final ChannelFactoryResource externalResource;
|
private final Executor bossExecutor;
|
||||||
|
private final Executor workerExecutor;
|
||||||
private final ChannelSink sink;
|
private final ChannelSink sink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,7 +136,8 @@ public class NioClientSocketChannelFactory implements ClientSocketChannelFactory
|
|||||||
"must be a positive integer.");
|
"must be a positive integer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
externalResource = new ChannelFactoryExecutorResource(bossExecutor, workerExecutor);
|
this.bossExecutor = bossExecutor;
|
||||||
|
this.workerExecutor = workerExecutor;
|
||||||
sink = new NioClientSocketPipelineSink(bossExecutor, workerExecutor, workerCount);
|
sink = new NioClientSocketPipelineSink(bossExecutor, workerExecutor, workerCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +145,7 @@ public class NioClientSocketChannelFactory implements ClientSocketChannelFactory
|
|||||||
return new NioClientSocketChannel(this, pipeline, sink);
|
return new NioClientSocketChannel(this, pipeline, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFactoryResource getExternalResource() {
|
public void releaseExternalResources() {
|
||||||
return externalResource;
|
ExecutorShutdownUtil.shutdown(bossExecutor, workerExecutor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,15 @@ package org.jboss.netty.channel.socket.nio;
|
|||||||
|
|
||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
|
|
||||||
import org.jboss.netty.channel.ChannelFactoryResource;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
import org.jboss.netty.channel.ChannelSink;
|
import org.jboss.netty.channel.ChannelSink;
|
||||||
import org.jboss.netty.channel.socket.ServerSocketChannel;
|
import org.jboss.netty.channel.socket.ServerSocketChannel;
|
||||||
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
||||||
|
import org.jboss.netty.util.ExecutorShutdownUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ServerSocketChannelFactory} which creates a server-side NIO-based
|
* A {@link ServerSocketChannelFactory} which creates a server-side NIO-based
|
||||||
@ -64,7 +61,6 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
|||||||
* more {@link Channel}s in a non-blocking mode.
|
* more {@link Channel}s in a non-blocking mode.
|
||||||
*
|
*
|
||||||
* <h3>Life cycle of threads and graceful shutdown</h3>
|
* <h3>Life cycle of threads and graceful shutdown</h3>
|
||||||
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
|
|
||||||
* <p>
|
* <p>
|
||||||
* All threads are acquired from the {@link Executor}s which were specified
|
* All threads are acquired from the {@link Executor}s which were specified
|
||||||
* when a {@link NioServerSocketChannelFactory} was created. Boss threads are
|
* when a {@link NioServerSocketChannelFactory} was created. Boss threads are
|
||||||
@ -81,11 +77,8 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
|||||||
*
|
*
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>unbind all channels created by the factory,
|
* <li>unbind all channels created by the factory,
|
||||||
* <li>close all child channels accepted by the unbound channels,</li>
|
* <li>close all child channels accepted by the unbound channels, and</li>
|
||||||
* <li>call {@link ExecutorService#shutdownNow()} or {@link ExecutorService#shutdown()}
|
* <li>call {@link #releaseExternalResources()}.</li>
|
||||||
* for all executors which were specified to create the factory, and</li>
|
|
||||||
* <li>call {@link ExecutorService#awaitTermination(long, TimeUnit)}
|
|
||||||
* until it returns {@code true}.</li>
|
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* Please make sure not to shut down the executor until all channels are
|
* Please make sure not to shut down the executor until all channels are
|
||||||
@ -102,7 +95,7 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
|||||||
public class NioServerSocketChannelFactory implements ServerSocketChannelFactory {
|
public class NioServerSocketChannelFactory implements ServerSocketChannelFactory {
|
||||||
|
|
||||||
final Executor bossExecutor;
|
final Executor bossExecutor;
|
||||||
private final ChannelFactoryResource externalResource;
|
private final Executor workerExecutor;
|
||||||
private final ChannelSink sink;
|
private final ChannelSink sink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +139,7 @@ public class NioServerSocketChannelFactory implements ServerSocketChannelFactory
|
|||||||
"must be a positive integer.");
|
"must be a positive integer.");
|
||||||
}
|
}
|
||||||
this.bossExecutor = bossExecutor;
|
this.bossExecutor = bossExecutor;
|
||||||
externalResource = new ChannelFactoryExecutorResource(bossExecutor, workerExecutor);
|
this.workerExecutor = workerExecutor;
|
||||||
sink = new NioServerSocketPipelineSink(workerExecutor, workerCount);
|
sink = new NioServerSocketPipelineSink(workerExecutor, workerCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +147,7 @@ public class NioServerSocketChannelFactory implements ServerSocketChannelFactory
|
|||||||
return new NioServerSocketChannel(this, pipeline, sink);
|
return new NioServerSocketChannel(this, pipeline, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFactoryResource getExternalResource() {
|
public void releaseExternalResources() {
|
||||||
return externalResource;
|
ExecutorShutdownUtil.shutdown(bossExecutor, workerExecutor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,13 @@
|
|||||||
package org.jboss.netty.channel.socket.oio;
|
package org.jboss.netty.channel.socket.oio;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
|
|
||||||
import org.jboss.netty.channel.ChannelFactoryResource;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
|
||||||
import org.jboss.netty.channel.socket.SocketChannel;
|
import org.jboss.netty.channel.socket.SocketChannel;
|
||||||
|
import org.jboss.netty.util.ExecutorShutdownUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ClientSocketChannelFactory} which creates a client-side blocking
|
* A {@link ClientSocketChannelFactory} which creates a client-side blocking
|
||||||
@ -51,7 +48,6 @@ import org.jboss.netty.channel.socket.SocketChannel;
|
|||||||
* traditional blocking I/O thread model.
|
* traditional blocking I/O thread model.
|
||||||
*
|
*
|
||||||
* <h3>Life cycle of threads and graceful shutdown</h3>
|
* <h3>Life cycle of threads and graceful shutdown</h3>
|
||||||
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
|
|
||||||
* <p>
|
* <p>
|
||||||
* Worker threads are acquired from the {@link Executor} which was specified
|
* Worker threads are acquired from the {@link Executor} which was specified
|
||||||
* when a {@link OioClientSocketChannelFactory} was created (i.e. {@code workerExecutor}.)
|
* when a {@link OioClientSocketChannelFactory} was created (i.e. {@code workerExecutor}.)
|
||||||
@ -64,11 +60,8 @@ import org.jboss.netty.channel.socket.SocketChannel;
|
|||||||
* you should do the following:
|
* you should do the following:
|
||||||
*
|
*
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>close all channels created by the factory,</li>
|
* <li>close all channels created by the factory, and</li>
|
||||||
* <li>call {@link ExecutorService#shutdownNow()} for the executor which was
|
* <li>call {@link #releaseExternalResources()}.</li>
|
||||||
* specified to create the factory, and</li>
|
|
||||||
* <li>call {@link ExecutorService#awaitTermination(long, TimeUnit)}
|
|
||||||
* until it returns {@code true}.</li>
|
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* Please make sure not to shut down the executor until all channels are
|
* Please make sure not to shut down the executor until all channels are
|
||||||
@ -90,7 +83,7 @@ import org.jboss.netty.channel.socket.SocketChannel;
|
|||||||
*/
|
*/
|
||||||
public class OioClientSocketChannelFactory implements ClientSocketChannelFactory {
|
public class OioClientSocketChannelFactory implements ClientSocketChannelFactory {
|
||||||
|
|
||||||
private final ChannelFactoryResource externalResource;
|
private final Executor workerExecutor;
|
||||||
final OioClientSocketPipelineSink sink;
|
final OioClientSocketPipelineSink sink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,7 +96,7 @@ public class OioClientSocketChannelFactory implements ClientSocketChannelFactory
|
|||||||
if (workerExecutor == null) {
|
if (workerExecutor == null) {
|
||||||
throw new NullPointerException("workerExecutor");
|
throw new NullPointerException("workerExecutor");
|
||||||
}
|
}
|
||||||
externalResource = new ChannelFactoryExecutorResource(workerExecutor);
|
this.workerExecutor = workerExecutor;
|
||||||
sink = new OioClientSocketPipelineSink(workerExecutor);
|
sink = new OioClientSocketPipelineSink(workerExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +104,7 @@ public class OioClientSocketChannelFactory implements ClientSocketChannelFactory
|
|||||||
return new OioClientSocketChannel(this, pipeline, sink);
|
return new OioClientSocketChannel(this, pipeline, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFactoryResource getExternalResource() {
|
public void releaseExternalResources() {
|
||||||
return externalResource;
|
ExecutorShutdownUtil.shutdown(workerExecutor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,11 @@ import java.util.concurrent.RejectedExecutionException;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelFactoryExecutorResource;
|
|
||||||
import org.jboss.netty.channel.ChannelFactoryResource;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
import org.jboss.netty.channel.ChannelSink;
|
import org.jboss.netty.channel.ChannelSink;
|
||||||
import org.jboss.netty.channel.socket.ServerSocketChannel;
|
import org.jboss.netty.channel.socket.ServerSocketChannel;
|
||||||
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
||||||
|
import org.jboss.netty.util.ExecutorShutdownUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ServerSocketChannelFactory} which creates a server-side blocking
|
* A {@link ServerSocketChannelFactory} which creates a server-side blocking
|
||||||
@ -61,7 +60,6 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
|||||||
* traditional blocking I/O thread model.
|
* traditional blocking I/O thread model.
|
||||||
*
|
*
|
||||||
* <h3>Life cycle of threads and graceful shutdown</h3>
|
* <h3>Life cycle of threads and graceful shutdown</h3>
|
||||||
* TODO: Rewrite this section to recommend a user to call ChannelFactoryResource.release().
|
|
||||||
* <p>
|
* <p>
|
||||||
* All threads are acquired from the {@link Executor}s which were specified
|
* All threads are acquired from the {@link Executor}s which were specified
|
||||||
* when a {@link OioServerSocketChannelFactory} was created. Boss threads are
|
* when a {@link OioServerSocketChannelFactory} was created. Boss threads are
|
||||||
@ -103,7 +101,7 @@ import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
|
|||||||
public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
|
public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
|
||||||
|
|
||||||
final Executor bossExecutor;
|
final Executor bossExecutor;
|
||||||
private final ChannelFactoryResource externalResource;
|
private final Executor workerExecutor;
|
||||||
private final ChannelSink sink;
|
private final ChannelSink sink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,7 +121,7 @@ public class OioServerSocketChannelFactory implements ServerSocketChannelFactory
|
|||||||
throw new NullPointerException("workerExecutor");
|
throw new NullPointerException("workerExecutor");
|
||||||
}
|
}
|
||||||
this.bossExecutor = bossExecutor;
|
this.bossExecutor = bossExecutor;
|
||||||
externalResource = new ChannelFactoryExecutorResource(bossExecutor, workerExecutor);
|
this.workerExecutor = workerExecutor;
|
||||||
sink = new OioServerSocketPipelineSink(workerExecutor);
|
sink = new OioServerSocketPipelineSink(workerExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +129,7 @@ public class OioServerSocketChannelFactory implements ServerSocketChannelFactory
|
|||||||
return new OioServerSocketChannel(this, pipeline, sink);
|
return new OioServerSocketChannel(this, pipeline, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFactoryResource getExternalResource() {
|
public void releaseExternalResources() {
|
||||||
return externalResource;
|
ExecutorShutdownUtil.shutdown(bossExecutor, workerExecutor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ public class DiscardClient {
|
|||||||
ClientBootstrap bootstrap = new ClientBootstrap(factory);
|
ClientBootstrap bootstrap = new ClientBootstrap(factory);
|
||||||
DiscardClientHandler handler = new DiscardClientHandler(firstMessageSize);
|
DiscardClientHandler handler = new DiscardClientHandler(firstMessageSize);
|
||||||
|
|
||||||
|
//bootstrap.getPipeline().addLast("executor", new ExecutionHandler(new MemoryAwareThreadPoolExecutor(16, 0, 0)));
|
||||||
bootstrap.getPipeline().addLast("handler", handler);
|
bootstrap.getPipeline().addLast("handler", handler);
|
||||||
bootstrap.setOption("tcpNoDelay", true);
|
bootstrap.setOption("tcpNoDelay", true);
|
||||||
bootstrap.setOption("keepAlive", true);
|
bootstrap.setOption("keepAlive", true);
|
||||||
@ -80,6 +81,6 @@ public class DiscardClient {
|
|||||||
future.getChannel().getCloseFuture().awaitUninterruptibly();
|
future.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||||
|
|
||||||
// Shut down thread pools to exit.
|
// Shut down thread pools to exit.
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,6 @@ public class FactorialClient {
|
|||||||
"Factorial of %,d is: %,d", count, handler.getFactorial());
|
"Factorial of %,d is: %,d", count, handler.getFactorial());
|
||||||
|
|
||||||
// Shut down all thread pools to exit.
|
// Shut down all thread pools to exit.
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ public class HttpClient {
|
|||||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||||
if (!future.isSuccess()) {
|
if (!future.isSuccess()) {
|
||||||
future.getCause().printStackTrace();
|
future.getCause().printStackTrace();
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +95,6 @@ public class HttpClient {
|
|||||||
channel.getCloseFuture().awaitUninterruptibly();
|
channel.getCloseFuture().awaitUninterruptibly();
|
||||||
|
|
||||||
// Shut down executor threads to exit.
|
// Shut down executor threads to exit.
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -78,7 +78,7 @@ public class SecureChatClient {
|
|||||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||||
if (!future.isSuccess()) {
|
if (!future.isSuccess()) {
|
||||||
future.getCause().printStackTrace();
|
future.getCause().printStackTrace();
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +103,6 @@ public class SecureChatClient {
|
|||||||
channel.close().awaitUninterruptibly();
|
channel.close().awaitUninterruptibly();
|
||||||
|
|
||||||
// Shut down all thread pools to exit.
|
// Shut down all thread pools to exit.
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ public class TelnetClient {
|
|||||||
Channel channel = future.awaitUninterruptibly().getChannel();
|
Channel channel = future.awaitUninterruptibly().getChannel();
|
||||||
if (!future.isSuccess()) {
|
if (!future.isSuccess()) {
|
||||||
future.getCause().printStackTrace();
|
future.getCause().printStackTrace();
|
||||||
factory.getExternalResource();
|
factory.releaseExternalResources();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +103,6 @@ public class TelnetClient {
|
|||||||
channel.close().awaitUninterruptibly();
|
channel.close().awaitUninterruptibly();
|
||||||
|
|
||||||
// Shut down all thread pools to exit.
|
// Shut down all thread pools to exit.
|
||||||
factory.getExternalResource().release();
|
factory.releaseExternalResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,49 +20,37 @@
|
|||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||||
*/
|
*/
|
||||||
package org.jboss.netty.channel;
|
package org.jboss.netty.util;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ChannelFactoryResource} whose underlying resource is a list of
|
* Shuts down a list of {@link Executor}s. {@link #shutdown(Executor...)} will
|
||||||
* {@link Executor}s. {@link #release()} will shut down all specified
|
* shut down all specified {@link ExecutorService}s immediately and wait for
|
||||||
* {@link ExecutorService}s immediately and wait for their termination.
|
* their termination. An {@link Executor} which is not an {@link ExecutorService}
|
||||||
* An {@link Executor} which is not an {@link ExecutorService} will be ignored.
|
* will be ignored silently.
|
||||||
*
|
*
|
||||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||||
* @author Trustin Lee (tlee@redhat.com)
|
* @author Trustin Lee (tlee@redhat.com)
|
||||||
* @version $Rev$, $Date$
|
* @version $Rev$, $Date$
|
||||||
*
|
|
||||||
* @apiviz.exclude
|
|
||||||
*/
|
*/
|
||||||
public class ChannelFactoryExecutorResource implements
|
public class ExecutorShutdownUtil {
|
||||||
ChannelFactoryResource {
|
|
||||||
|
|
||||||
private final Executor[] executors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance with the specified executors.
|
* Shuts down the specified executors.
|
||||||
*
|
|
||||||
* @param executors a list of {@link Executor}s
|
|
||||||
*/
|
*/
|
||||||
public ChannelFactoryExecutorResource(Executor... executors) {
|
public static void shutdown(Executor... executors) {
|
||||||
if (executors == null) {
|
Executor[] executorsCopy = new Executor[executors.length];
|
||||||
throw new NullPointerException("executors");
|
|
||||||
}
|
|
||||||
this.executors = new Executor[executors.length];
|
|
||||||
for (int i = 0; i < executors.length; i ++) {
|
for (int i = 0; i < executors.length; i ++) {
|
||||||
if (executors[i] == null) {
|
if (executors[i] == null) {
|
||||||
throw new NullPointerException("executors[" + i + "]");
|
throw new NullPointerException("executors[" + i + "]");
|
||||||
}
|
}
|
||||||
this.executors[i] = executors[i];
|
executorsCopy[i] = executors[i];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void release() {
|
for (Executor e: executorsCopy) {
|
||||||
for (Executor e: executors) {
|
|
||||||
if (!(e instanceof ExecutorService)) {
|
if (!(e instanceof ExecutorService)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -80,4 +68,8 @@ public class ChannelFactoryExecutorResource implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExecutorShutdownUtil() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
}
|
}
|
@ -85,7 +85,7 @@ public class NioClientSocketShutdownTimeTest {
|
|||||||
|
|
||||||
f.getChannel().close().awaitUninterruptibly();
|
f.getChannel().close().awaitUninterruptibly();
|
||||||
} finally {
|
} finally {
|
||||||
b.getFactory().getExternalResource().release();
|
b.getFactory().releaseExternalResources();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serverSocket.close();
|
serverSocket.close();
|
||||||
|
@ -106,7 +106,7 @@ public class NioServerSocketShutdownTimeTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
channel.close().awaitUninterruptibly();
|
channel.close().awaitUninterruptibly();
|
||||||
bootstrap.getFactory().getExternalResource().release();
|
bootstrap.getFactory().releaseExternalResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
long shutdownTime = System.currentTimeMillis() - startTime;
|
long shutdownTime = System.currentTimeMillis() - startTime;
|
||||||
|
Loading…
Reference in New Issue
Block a user