1 /*
2 * Copyright 2013 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://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 io.netty5.channel.group;
17
18 import io.netty5.bootstrap.ServerBootstrap;
19 import io.netty5.buffer.api.Buffer;
20 import io.netty5.buffer.api.DefaultBufferAllocators;
21 import io.netty5.channel.Channel;
22 import io.netty5.channel.ChannelHandler;
23 import io.netty5.channel.ChannelHandlerContext;
24 import io.netty5.channel.ChannelId;
25 import io.netty5.channel.EventLoop;
26 import io.netty5.channel.ServerChannel;
27 import io.netty5.util.concurrent.GlobalEventExecutor;
28
29 import java.nio.charset.StandardCharsets;
30 import java.util.Set;
31
32 /**
33 * A thread-safe {@link Set} that contains open {@link Channel}s and provides
34 * various bulk operations on them. Using {@link ChannelGroup}, you can
35 * categorize {@link Channel}s into a meaningful group (e.g. on a per-service
36 * or per-state basis.) A closed {@link Channel} is automatically removed from
37 * the collection, so that you don't need to worry about the life cycle of the
38 * added {@link Channel}. A {@link Channel} can belong to more than one
39 * {@link ChannelGroup}.
40 *
41 * <h3>Broadcast a message to multiple {@link Channel}s</h3>
42 * <p>
43 * If you need to broadcast a message to more than one {@link Channel}, you can
44 * add the {@link Channel}s associated with the recipients and call {@link ChannelGroup#write(Object)}:
45 * <pre>
46 * <strong>{@link ChannelGroup} recipients =
47 * new {@link DefaultChannelGroup}({@link GlobalEventExecutor}.INSTANCE);</strong>
48 * recipients.add(channelA);
49 * recipients.add(channelB);
50 * ..
51 * <strong>recipients.write({@link DefaultBufferAllocators#preferredAllocator()}.copyOf(
52 * "Service will shut down for maintenance in 5 minutes.",
53 * {@link StandardCharsets#UTF_8}));</strong>
54 * </pre>
55 *
56 * <h3>Simplify shutdown process with {@link ChannelGroup}</h3>
57 * <p>
58 * If both {@link ServerChannel}s and non-{@link ServerChannel}s exist in the
59 * same {@link ChannelGroup}, any requested I/O operations on the group are
60 * performed for the {@link ServerChannel}s first and then for the others.
61 * <p>
62 * This rule is very useful when you shut down a server in one shot:
63 *
64 * <pre>
65 * <strong>{@link ChannelGroup} allChannels =
66 * new {@link DefaultChannelGroup}({@link GlobalEventExecutor}.INSTANCE);</strong>
67 *
68 * public static void main(String[] args) throws Exception {
69 * {@link ServerBootstrap} b = new {@link ServerBootstrap}(..);
70 * ...
71 * b.childHandler(new MyHandler());
72 *
73 * // Start the server
74 * b.getPipeline().addLast("handler", new MyHandler());
75 * {@link Channel} serverChannel = b.bind(..).sync();
76 * <strong>allChannels.add(serverChannel);</strong>
77 *
78 * ... Wait until the shutdown signal reception ...
79 *
80 * // Close the serverChannel and then all accepted connections.
81 * <strong>allChannels.close().await();</strong>
82 * }
83 *
84 * public class MyHandler implements {@link ChannelHandler} {
85 * {@code @Override}
86 * public void channelActive({@link ChannelHandlerContext} ctx) {
87 * // closed on shutdown.
88 * <strong>allChannels.add(ctx.channel());</strong>
89 * ctx.fireChannelActive();
90 * }
91 * }
92 * </pre>
93 */
94 public interface ChannelGroup extends Set<Channel>, Comparable<ChannelGroup> {
95
96 /**
97 * Returns the name of this group. A group name is purely for helping
98 * you to distinguish one group from others.
99 */
100 String name();
101
102 /**
103 * Returns the {@link Channel} which has the specified {@link ChannelId}.
104 *
105 * @return the matching {@link Channel} if found. {@code null} otherwise.
106 */
107 Channel find(ChannelId id);
108
109 /**
110 * Writes the specified {@code message} to all {@link Channel}s in this
111 * group.
112 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically
113 * {@linkplain Buffer#copy() copied} to avoid a race condition.
114 * Please note that this operation is asynchronous as {@link Channel#write(Object)} is.
115 *
116 * @return itself
117 */
118 ChannelGroupFuture write(Object message);
119
120 /**
121 * Writes the specified {@code message} to all {@link Channel}s in this
122 * group that are matched by the given {@link ChannelMatcher}.
123 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically
124 * {@linkplain Buffer#copy() copied} to avoid a race condition.
125 * Please note that this operation is asynchronous as {@link Channel#write(Object)} is.
126 *
127 * @return the {@link ChannelGroupFuture} instance that notifies when
128 * the operation is done for all channels
129 */
130 ChannelGroupFuture write(Object message, ChannelMatcher matcher);
131
132 /**
133 * Flush all {@link Channel}s in this
134 * group.
135 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically
136 * {@linkplain Buffer#copy() copied} to avoid a race condition.
137 * Please note that this operation is asynchronous as {@link Channel#flush()} is.
138 *
139 * @return the {@link ChannelGroupFuture} instance that notifies when
140 * the operation is done for all channels
141 */
142 ChannelGroup flush();
143
144 /**
145 * Flush all {@link Channel}s in this group that are matched by the given {@link ChannelMatcher}.
146 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically
147 * {@linkplain Buffer#copy() copied} to avoid a race condition.
148 * Please note that this operation is asynchronous as {@link Channel#flush()} is.
149 *
150 * @return the {@link ChannelGroupFuture} instance that notifies when
151 * the operation is done for all channels
152 */
153 ChannelGroup flush(ChannelMatcher matcher);
154
155 /**
156 * Shortcut for calling {@link #write(Object)} and {@link #flush()}.
157 */
158 ChannelGroupFuture writeAndFlush(Object message);
159
160 /**
161 * @deprecated Use {@link #writeAndFlush(Object)} instead.
162 */
163 @Deprecated
164 ChannelGroupFuture flushAndWrite(Object message);
165
166 /**
167 * Shortcut for calling {@link #write(Object)} and {@link #flush()} and only act on
168 * {@link Channel}s that are matched by the {@link ChannelMatcher}.
169 */
170 ChannelGroupFuture writeAndFlush(Object message, ChannelMatcher matcher);
171
172 /**
173 * @deprecated Use {@link #writeAndFlush(Object, ChannelMatcher)} instead.
174 */
175 @Deprecated
176 ChannelGroupFuture flushAndWrite(Object message, ChannelMatcher matcher);
177
178 /**
179 * Disconnects all {@link Channel}s in this group from their remote peers.
180 *
181 * @return the {@link ChannelGroupFuture} instance that notifies when
182 * the operation is done for all channels
183 */
184 ChannelGroupFuture disconnect();
185
186 /**
187 * Disconnects all {@link Channel}s in this group from their remote peers,
188 * that are matched by the given {@link ChannelMatcher}.
189 *
190 * @return the {@link ChannelGroupFuture} instance that notifies when
191 * the operation is done for all channels
192 */
193 ChannelGroupFuture disconnect(ChannelMatcher matcher);
194
195 /**
196 * Closes all {@link Channel}s in this group. If the {@link Channel} is
197 * connected to a remote peer or bound to a local address, it is
198 * automatically disconnected and unbound.
199 *
200 * @return the {@link ChannelGroupFuture} instance that notifies when
201 * the operation is done for all channels
202 */
203 ChannelGroupFuture close();
204
205 /**
206 * Closes all {@link Channel}s in this group that are matched by the given {@link ChannelMatcher}.
207 * If the {@link Channel} is connected to a remote peer or bound to a local address, it is
208 * automatically disconnected and unbound.
209 *
210 * @return the {@link ChannelGroupFuture} instance that notifies when
211 * the operation is done for all channels
212 */
213 ChannelGroupFuture close(ChannelMatcher matcher);
214
215 /**
216 * @deprecated This method will be removed in the next major feature release.
217 *
218 * Deregister all {@link Channel}s in this group from their {@link EventLoop}.
219 * Please note that this operation is asynchronous as {@link Channel#deregister()} is.
220 *
221 * @return the {@link ChannelGroupFuture} instance that notifies when
222 * the operation is done for all channels
223 */
224 @Deprecated
225 ChannelGroupFuture deregister();
226
227 /**
228 * @deprecated This method will be removed in the next major feature release.
229 *
230 * Deregister all {@link Channel}s in this group from their {@link EventLoop} that are matched by the given
231 * {@link ChannelMatcher}. Please note that this operation is asynchronous as {@link Channel#deregister()} is.
232 *
233 * @return the {@link ChannelGroupFuture} instance that notifies when
234 * the operation is done for all channels
235 */
236 @Deprecated
237 ChannelGroupFuture deregister(ChannelMatcher matcher);
238
239 /**
240 * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that are part of this
241 * {@link ChannelGroup}, at the time of calling, are closed.
242 */
243 ChannelGroupFuture newCloseFuture();
244
245 /**
246 * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that are part of this
247 * {@link ChannelGroup}, at the time of calling, are closed.
248 */
249 ChannelGroupFuture newCloseFuture(ChannelMatcher matcher);
250 }