Updated JavaDoc of the org.jboss.netty.channel.group package
This commit is contained in:
parent
4ee657cd0b
commit
20aecc928f
@ -25,9 +25,54 @@ package org.jboss.netty.channel.group;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ServerChannel;
|
||||
|
||||
/**
|
||||
* A thread-safe {@link Set} that contains open {@link Channel}s and provides
|
||||
* various bulk operations on them. Using {@link ChannelGroup}, you can
|
||||
* categorize {@link Channel}s into a meaningful group (e.g. on a per-service
|
||||
* or per-state basis.) A closed {@link Channel} is automatically removed from
|
||||
* the collection, so that you don't need to worry about the life cycle of the
|
||||
* added {@link Channel}. A {@link Channel} can belong to more than one
|
||||
* {@link ChannelGroup}.
|
||||
*
|
||||
* <h3>Simplify shutdown process with {@link ChannelGroup}</h3>
|
||||
* <p>
|
||||
* If both {@link ServerChannel}s and non-{@link ServerChannel}s exists in the
|
||||
* same {@link ChannelGroup}, any requested I/O operations on the group are
|
||||
* performed for the {@link ServerChannel}s first and then for the others.
|
||||
* <p>
|
||||
* This rule is very useful when you shut down a server in one shot:
|
||||
*
|
||||
* <pre>
|
||||
* ChannelGroup allChannels = new DefaultChannelGroup();
|
||||
*
|
||||
* public static void main(String[] args) throws Exception {
|
||||
* ServerBootstrap b = new ServerBootstrap(..);
|
||||
* ...
|
||||
*
|
||||
* // Start the server
|
||||
* b.getPipeline().addLast("handler", new MyHandler());
|
||||
* Channel serverChannel = b.bind(..);
|
||||
*
|
||||
* ... Wait until the shutdown signal reception ...
|
||||
*
|
||||
* // Close the serverChannel and then all accepted connections.
|
||||
* allChannels.close().awaitUninterruptibly();
|
||||
* b.releaseExternalResources();
|
||||
* }
|
||||
*
|
||||
* public class MyHandler extends SimpleChannelUpstreamHandler {
|
||||
* public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
* // Add all open channels to the global group so that they are
|
||||
* // closed on shutdown.
|
||||
* allChannels.add(e.getChannel());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||
* @author Trustin Lee (tlee@redhat.com)
|
||||
* @version $Rev$, $Date$
|
||||
@ -36,13 +81,89 @@ import org.jboss.netty.channel.Channel;
|
||||
* @apiviz.has org.jboss.netty.channel.group.ChannelGroupFuture oneway - - returns
|
||||
*/
|
||||
public interface ChannelGroup extends Set<Channel>, Comparable<ChannelGroup> {
|
||||
|
||||
/**
|
||||
* Returns the name of this group. A group name is purely for helping
|
||||
* you to distinguish one group from others.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns the {@link Channel} whose ID matches the specified integer.
|
||||
*
|
||||
* @return the matching {@link Channel} if found. {@code null} otherwise.
|
||||
*/
|
||||
Channel find(Integer id);
|
||||
|
||||
/**
|
||||
* Calls {@link Channel#setInterestOps(int)} for all {@link Channel}s in
|
||||
* this group with the specified {@code interestOps}. Please note that
|
||||
* this operation is asynchronous as {@link Channel#setInterestOps(int)} is.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture setInterestOps(int interestOps);
|
||||
|
||||
/**
|
||||
* Calls {@link Channel#setReadable(boolean)} for all {@link Channel}s in
|
||||
* this group with the specified boolean flag. Please note that this
|
||||
* operation is asynchronous as {@link Channel#setReadable(boolean)} is.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture setReadable(boolean readable);
|
||||
|
||||
/**
|
||||
* Writes the specified {@code message} to all {@link Channel}s in this
|
||||
* group. If the specified {@code message} is an instance of
|
||||
* {@link ChannelBuffer}, it is automatically
|
||||
* {@linkplain ChannelBuffer#duplicate() duplicated} to avoid a race
|
||||
* condition. Please note that this operation is asynchronous as
|
||||
* {@link Channel#write(Object)} is.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture write(Object message);
|
||||
|
||||
/**
|
||||
* Writes the specified {@code message} with the specified
|
||||
* {@code remoteAddress} to all {@link Channel}s in this group. If the
|
||||
* specified {@code message} is an instance of {@link ChannelBuffer}, it is
|
||||
* automatically {@linkplain ChannelBuffer#duplicate() duplicated} to avoid
|
||||
* a race condition. Please note that this operation is asynchronous as
|
||||
* {@link Channel#write(Object, SocketAddress)} is.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture write(Object message, SocketAddress remoteAddress);
|
||||
|
||||
/**
|
||||
* Disconnects all {@link Channel}s in this group from their remote peers.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture disconnect();
|
||||
|
||||
/**
|
||||
* Unbinds all {@link Channel}s in this group from their local address.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture unbind();
|
||||
|
||||
/**
|
||||
* Closes all {@link Channel}s in this group. If the {@link Channel} is
|
||||
* connected to a remote peer or bound to a local address, it is
|
||||
* automatically disconnected and unbound.
|
||||
*
|
||||
* @return the {@link ChannelGroupFuture} instance that notifies when
|
||||
* the operation is done for all channels
|
||||
*/
|
||||
ChannelGroupFuture close();
|
||||
}
|
||||
|
@ -22,12 +22,87 @@
|
||||
*/
|
||||
package org.jboss.netty.channel.group;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelHandler;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.handler.execution.ExecutionHandler;
|
||||
|
||||
/**
|
||||
* The result of an asynchronous {@link ChannelGroup} operation.
|
||||
*
|
||||
* <p>
|
||||
* All I/O operations in {@link ChannelGroup} are asynchronous. It means any
|
||||
* I/O calls will return immediately with no guarantee that the requested I/O
|
||||
* operations have been completed at the end of the call. Instead, you will be
|
||||
* returned with a {@link ChannelGroupFuture} instance which tells you when the
|
||||
* requested I/O operations have succeeded, failed, or cancelled.
|
||||
* <p>
|
||||
* Various methods are provided to let you check if the I/O operations has been
|
||||
* completed, wait for the completion, and retrieve the result of the I/O
|
||||
* operation. It also allows you to add more than one
|
||||
* {@link ChannelGroupFutureListener} so you can get notified when the I/O
|
||||
* operation have been completed.
|
||||
*
|
||||
* <h3>Prefer {@link #addListener(ChannelGroupFutureListener)} to {@link #await()}</h3>
|
||||
*
|
||||
* It is recommended to prefer {@link #addListener(ChannelGroupFutureListener)} to
|
||||
* {@link #await()} wherever possible to get notified when I/O operations are
|
||||
* done and to do any follow-up tasks.
|
||||
* <p>
|
||||
* {@link #addListener(ChannelGroupFutureListener)} is non-blocking. It simply
|
||||
* adds the specified {@link ChannelGroupFutureListener} to the
|
||||
* {@link ChannelGroupFuture}, and I/O thread will notify the listeners when
|
||||
* the I/O operations associated with the future is done.
|
||||
* {@link ChannelGroupFutureListener} yields the best performance and resource
|
||||
* utilization because it does not block at all, but it could be tricky to
|
||||
* implement a sequential logic if you are not used to event-driven programming.
|
||||
* <p>
|
||||
* By contrast, {@link #await()} is a blocking operation. Once called, the
|
||||
* caller thread blocks until all I/O operations are done. It is easier to
|
||||
* implement a sequential logic with {@link #await()}, but the caller thread
|
||||
* blocks unnecessarily until all I/O operations are done and there's relatively
|
||||
* expensive cost of inter-thread notification. Moreover, there's a chance of
|
||||
* dead lock in a particular circumstance, which is described below.
|
||||
*
|
||||
* <h3>Do not call {@link #await()} inside {@link ChannelHandler}</h3>
|
||||
* <p>
|
||||
* The event handler methods in {@link ChannelHandler} is often called by
|
||||
* an I/O thread unless an {@link ExecutionHandler} is in the
|
||||
* {@link ChannelPipeline}. If {@link #await()} is called by an event handler
|
||||
* method, which is called by the I/O thread, the I/O operation it is waiting
|
||||
* for might never be complete because {@link #await()} can block the I/O
|
||||
* operation it is waiting for, which is a dead lock.
|
||||
* <pre>
|
||||
* // BAD - NEVER DO THIS
|
||||
* public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
* if (e.getMessage() instanceof ShutdownMessage) {
|
||||
* ChannelGroup allChannels = MyServer.getAllChannels();
|
||||
* ChannelGroupFuture future = allChannels.close();
|
||||
* future.awaitUninterruptibly();
|
||||
* // Perform post-shutdown operation
|
||||
* // ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // GOOD
|
||||
* public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
|
||||
* if (e.getMessage() instanceof ShutdownMessage) {
|
||||
* ChannelGroup allChannels = MyServer.getAllChannels();
|
||||
* ChannelGroupFuture future = allChannels.close();
|
||||
* future.addListener(new ChannelGroupFutureListener() {
|
||||
* public void operationComplete(ChannelGroupFuture future) {
|
||||
* // Perform post-closure operation
|
||||
* // ...
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||
* @author Trustin Lee (tlee@redhat.com)
|
||||
* @version $Rev$, $Date$
|
||||
@ -36,9 +111,28 @@ import org.jboss.netty.channel.ChannelFuture;
|
||||
*/
|
||||
public interface ChannelGroupFuture extends Iterable<ChannelFuture>{
|
||||
|
||||
/**
|
||||
* Returns the {@link ChannelGroup} which is associated with this future.
|
||||
*/
|
||||
ChannelGroup getGroup();
|
||||
|
||||
/**
|
||||
* Returns the {@link ChannelFuture} of the I/O operation which is
|
||||
* associated with the {@link Channel} whose ID matches the specified
|
||||
* integer.
|
||||
*
|
||||
* @return the matching {@link ChannelFuture} if found.
|
||||
* {@code null} otherwise.
|
||||
*/
|
||||
ChannelFuture find(Integer channelId);
|
||||
|
||||
/**
|
||||
* Returns the {@link ChannelFuture} of the I/O operation which is
|
||||
* associated with the specified {@link Channel}.
|
||||
*
|
||||
* @return the matching {@link ChannelFuture} if found.
|
||||
* {@code null} otherwise.
|
||||
*/
|
||||
ChannelFuture find(Channel channel);
|
||||
|
||||
/**
|
||||
@ -48,12 +142,28 @@ public interface ChannelGroupFuture extends Iterable<ChannelFuture>{
|
||||
*/
|
||||
boolean isDone();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if all I/O operations associated with
|
||||
* this future were successful without any failure.
|
||||
*/
|
||||
boolean isCompleteSuccess();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the I/O operations associated with
|
||||
* this future were partially successful with some failure.
|
||||
*/
|
||||
boolean isPartialSuccess();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if all I/O operations associated with
|
||||
* this future have failed without any success.
|
||||
*/
|
||||
boolean isCompleteFailure();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the I/O operations associated with
|
||||
* this future have failed partially with some success.
|
||||
*/
|
||||
boolean isPartialFailure();
|
||||
|
||||
/**
|
||||
@ -131,4 +241,12 @@ public interface ChannelGroupFuture extends Iterable<ChannelFuture>{
|
||||
* the specified time limit
|
||||
*/
|
||||
boolean awaitUninterruptibly(long timeoutMillis);
|
||||
|
||||
/**
|
||||
* Returns the {@link Iterator} that enumerates all {@link ChannelFuture}s
|
||||
* which are associated with this future. Please note that the returned
|
||||
* {@link Iterator} is is unmodifiable, which means a {@link ChannelFuture}
|
||||
* cannot be removed from this future.
|
||||
*/
|
||||
Iterator<ChannelFuture> iterator();
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* Listens to the result of a {@link ChannelGroupFuture}. The result of the
|
||||
* asynchronous {@link ChannelGroup} I/O operation is notified once this
|
||||
* listener is added by calling {@link ChannelGroupFuture#addListener(ChannelGroupFutureListener)}.
|
||||
* asynchronous {@link ChannelGroup} I/O operations is notified once this
|
||||
* listener is added by calling {@link ChannelGroupFuture#addListener(ChannelGroupFutureListener)}
|
||||
* and all I/O operations are complete.
|
||||
*
|
||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||
* @author Trustin Lee (tlee@redhat.com)
|
||||
@ -37,8 +38,8 @@ import java.util.EventListener;
|
||||
public interface ChannelGroupFutureListener extends EventListener {
|
||||
|
||||
/**
|
||||
* Invoked when the I/O operation associated with the
|
||||
* {@link ChannelGroupFuture} has been completed.
|
||||
* Invoked when all I/O operations associated with the
|
||||
* {@link ChannelGroupFuture} have been completed.
|
||||
*
|
||||
* @param future The source {@link ChannelGroupFuture} which called this
|
||||
* callback.
|
||||
|
@ -41,6 +41,8 @@ import org.jboss.netty.util.internal.CombinedIterator;
|
||||
import org.jboss.netty.util.internal.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* The default {@link ChannelGroup} implementation.
|
||||
*
|
||||
* @author The Netty Project (netty-dev@lists.jboss.org)
|
||||
* @author Trustin Lee (tlee@redhat.com)
|
||||
* @version $Rev$, $Date$
|
||||
@ -58,10 +60,18 @@ public class DefaultChannelGroup extends AbstractSet<Channel> implements Channel
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new group with a generated name.
|
||||
*/
|
||||
public DefaultChannelGroup() {
|
||||
this("group-0x" + Integer.toHexString(nextId.incrementAndGet()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new group with the specified {@code name}. Please note that
|
||||
* different groups can have the same name, which means no duplicate check
|
||||
* is done against group names.
|
||||
*/
|
||||
public DefaultChannelGroup(String name) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
|
@ -22,8 +22,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* A global channel registry which helps a user maintain the list of open
|
||||
* channels and perform bulk operations on them.
|
||||
* A channel registry which helps a user maintain the list of open
|
||||
* {@link org.jboss.netty.channel.Channel}s and perform bulk operations on them.
|
||||
*
|
||||
* @apiviz.exclude ^java
|
||||
* @apiviz.exclude \.(Abstract|Default).*$
|
||||
|
Loading…
Reference in New Issue
Block a user