1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.core.service;
21
22 import java.util.AbstractSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.concurrent.Executor;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicInteger;
32
33 import org.apache.mina.core.IoUtil;
34 import org.apache.mina.core.filterchain.DefaultIoFilterChain;
35 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
36 import org.apache.mina.core.filterchain.IoFilterChainBuilder;
37 import org.apache.mina.core.future.ConnectFuture;
38 import org.apache.mina.core.future.DefaultIoFuture;
39 import org.apache.mina.core.future.IoFuture;
40 import org.apache.mina.core.future.WriteFuture;
41 import org.apache.mina.core.session.AbstractIoSession;
42 import org.apache.mina.core.session.DefaultIoSessionDataStructureFactory;
43 import org.apache.mina.core.session.IdleStatus;
44 import org.apache.mina.core.session.IoSession;
45 import org.apache.mina.core.session.IoSessionConfig;
46 import org.apache.mina.core.session.IoSessionDataStructureFactory;
47 import org.apache.mina.core.session.IoSessionInitializationException;
48 import org.apache.mina.core.session.IoSessionInitializer;
49 import org.apache.mina.util.ExceptionMonitor;
50 import org.apache.mina.util.NamePreservingRunnable;
51
52
53
54
55
56
57
58
59
60
61 public abstract class AbstractIoService implements IoService {
62
63
64
65
66 private static final AtomicInteger id = new AtomicInteger();
67
68
69
70
71
72 private final String threadName;
73
74
75
76
77 private final Executor executor;
78
79
80
81
82
83
84
85
86 private final boolean createdExecutor;
87
88
89
90
91 private IoHandler handler;
92
93
94
95
96 private final IoSessionConfig sessionConfig;
97
98 private final IoServiceListener serviceActivationListener = new IoServiceListener() {
99 public void serviceActivated(IoService service) {
100
101 AbstractIoService s = (AbstractIoService) service;
102 IoServiceStatistics _stats = (IoServiceStatistics) s.getStatistics();
103 _stats.setLastReadTime(s.getActivationTime());
104 _stats.setLastWriteTime(s.getActivationTime());
105 _stats.setLastThroughputCalculationTime(s.getActivationTime());
106
107 }
108
109 public void serviceDeactivated(IoService service) {
110 }
111
112 public void serviceIdle(IoService service, IdleStatus idleStatus) {
113 }
114
115 public void sessionCreated(IoSession session) {
116 }
117
118 public void sessionDestroyed(IoSession session) {
119 }
120 };
121
122
123
124
125 private IoFilterChainBuilder filterChainBuilder = new DefaultIoFilterChainBuilder();
126
127 private IoSessionDataStructureFactory sessionDataStructureFactory = new DefaultIoSessionDataStructureFactory();
128
129
130
131
132 private final IoServiceListenerSupport listeners;
133
134
135
136
137
138 protected final Object disposalLock = new Object();
139
140 private volatile boolean disposing;
141
142 private volatile boolean disposed;
143
144 private IoFuture disposalFuture;
145
146
147
148
149 private IoServiceStatistics stats = new IoServiceStatistics(this);
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {
165 if (sessionConfig == null) {
166 throw new NullPointerException("sessionConfig");
167 }
168
169 if (getTransportMetadata() == null) {
170 throw new NullPointerException("TransportMetadata");
171 }
172
173 if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(
174 sessionConfig.getClass())) {
175 throw new IllegalArgumentException("sessionConfig type: "
176 + sessionConfig.getClass() + " (expected: "
177 + getTransportMetadata().getSessionConfigType() + ")");
178 }
179
180
181
182 listeners = new IoServiceListenerSupport(this);
183 listeners.add(serviceActivationListener);
184
185
186 this.sessionConfig = sessionConfig;
187
188
189
190 ExceptionMonitor.getInstance();
191
192 if (executor == null) {
193 this.executor = Executors.newCachedThreadPool();
194 createdExecutor = true;
195 } else {
196 this.executor = executor;
197 createdExecutor = false;
198 }
199
200 threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();
201 }
202
203
204
205
206 public final IoFilterChainBuilder getFilterChainBuilder() {
207 return filterChainBuilder;
208 }
209
210
211
212
213 public final void setFilterChainBuilder(IoFilterChainBuilder builder) {
214 if (builder == null) {
215 builder = new DefaultIoFilterChainBuilder();
216 }
217 filterChainBuilder = builder;
218 }
219
220
221
222
223 public final DefaultIoFilterChainBuilder getFilterChain() {
224 if (filterChainBuilder instanceof DefaultIoFilterChainBuilder) {
225 return (DefaultIoFilterChainBuilder) filterChainBuilder;
226 } else {
227 throw new IllegalStateException(
228 "Current filter chain builder is not a DefaultIoFilterChainBuilder.");
229 }
230 }
231
232
233
234
235 public final void addListener(IoServiceListener listener) {
236 listeners.add(listener);
237 }
238
239
240
241
242 public final void removeListener(IoServiceListener listener) {
243 listeners.remove(listener);
244 }
245
246
247
248
249 public final boolean isActive() {
250 return listeners.isActive();
251 }
252
253
254
255
256 public final boolean isDisposing() {
257 return disposing;
258 }
259
260
261
262
263 public final boolean isDisposed() {
264 return disposed;
265 }
266
267
268
269
270 public final void dispose() {
271 if (disposed) {
272 return;
273 }
274
275 IoFuture disposalFuture;
276 synchronized (disposalLock) {
277 disposalFuture = this.disposalFuture;
278 if (!disposing) {
279 disposing = true;
280 try {
281 this.disposalFuture = disposalFuture = dispose0();
282 } catch (Exception e) {
283 ExceptionMonitor.getInstance().exceptionCaught(e);
284 } finally {
285 if (disposalFuture == null) {
286 disposed = true;
287 }
288 }
289 }
290 }
291
292 if (disposalFuture != null) {
293 disposalFuture.awaitUninterruptibly();
294 }
295
296 if (createdExecutor) {
297 ExecutorService e = (ExecutorService) executor;
298 e.shutdown();
299 while (!e.isTerminated()) {
300 try {
301 e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
302 } catch (InterruptedException e1) {
303
304 }
305 }
306 }
307
308 disposed = true;
309 }
310
311
312
313
314
315 protected abstract IoFuture dispose0() throws Exception;
316
317
318
319
320 public final Map<Long, IoSession> getManagedSessions() {
321 return listeners.getManagedSessions();
322 }
323
324
325
326
327 public final int getManagedSessionCount() {
328 return listeners.getManagedSessionCount();
329 }
330
331
332
333
334 public final IoHandler getHandler() {
335 return handler;
336 }
337
338
339
340
341 public final void setHandler(IoHandler handler) {
342 if (handler == null) {
343 throw new NullPointerException("handler cannot be null");
344 }
345
346 if (isActive()) {
347 throw new IllegalStateException(
348 "handler cannot be set while the service is active.");
349 }
350
351 this.handler = handler;
352 }
353
354
355
356
357 public IoSessionConfig getSessionConfig() {
358 return sessionConfig;
359 }
360
361
362
363
364 public final IoSessionDataStructureFactory getSessionDataStructureFactory() {
365 return sessionDataStructureFactory;
366 }
367
368
369
370
371 public final void setSessionDataStructureFactory(
372 IoSessionDataStructureFactory sessionDataStructureFactory) {
373 if (sessionDataStructureFactory == null) {
374 throw new NullPointerException("sessionDataStructureFactory");
375 }
376
377 if (isActive()) {
378 throw new IllegalStateException(
379 "sessionDataStructureFactory cannot be set while the service is active.");
380 }
381
382 this.sessionDataStructureFactory = sessionDataStructureFactory;
383 }
384
385
386
387
388 public IoServiceStatistics getStatistics() {
389 return stats;
390 }
391
392
393
394
395 public final long getActivationTime() {
396 return listeners.getActivationTime();
397 }
398
399
400
401
402 public final Set<WriteFuture> broadcast(Object message) {
403
404
405
406 final List<WriteFuture> futures = IoUtil.broadcast(message,
407 getManagedSessions().values());
408 return new AbstractSet<WriteFuture>() {
409 @Override
410 public Iterator<WriteFuture> iterator() {
411 return futures.iterator();
412 }
413
414 @Override
415 public int size() {
416 return futures.size();
417 }
418 };
419 }
420
421 public final IoServiceListenerSupport getListeners() {
422 return listeners;
423 }
424
425
426 protected final void executeWorker(Runnable worker) {
427 executeWorker(worker, null);
428 }
429
430 protected final void executeWorker(Runnable worker, String suffix) {
431 String actualThreadName = threadName;
432 if (suffix != null) {
433 actualThreadName = actualThreadName + '-' + suffix;
434 }
435 executor.execute(new NamePreservingRunnable(worker, actualThreadName));
436 }
437
438
439 @SuppressWarnings("unchecked")
440 protected final void finishSessionInitialization(IoSession session,
441 IoFuture future, IoSessionInitializer sessionInitializer) {
442
443 if (stats.getLastReadTime() == 0) {
444 ((IoServiceStatistics)stats).setLastReadTime(getActivationTime());
445 }
446 if (stats.getLastWriteTime() == 0) {
447 ((IoServiceStatistics)stats).setLastWriteTime(getActivationTime());
448 }
449
450
451
452
453
454 try {
455 ((AbstractIoSession) session).setAttributeMap(session.getService()
456 .getSessionDataStructureFactory().getAttributeMap(session));
457 } catch (IoSessionInitializationException e) {
458 throw e;
459 } catch (Exception e) {
460 throw new IoSessionInitializationException(
461 "Failed to initialize an attributeMap.", e);
462 }
463
464 try {
465 ((AbstractIoSession) session).setWriteRequestQueue(session
466 .getService().getSessionDataStructureFactory()
467 .getWriteRequestQueue(session));
468 } catch (IoSessionInitializationException e) {
469 throw e;
470 } catch (Exception e) {
471 throw new IoSessionInitializationException(
472 "Failed to initialize a writeRequestQueue.", e);
473 }
474
475 if (future != null && future instanceof ConnectFuture) {
476
477 session.setAttribute(DefaultIoFilterChain.SESSION_CREATED_FUTURE,
478 future);
479 }
480
481 if (sessionInitializer != null) {
482 sessionInitializer.initializeSession(session, future);
483 }
484
485 finishSessionInitialization0(session, future);
486 }
487
488
489
490
491
492
493
494 protected void finishSessionInitialization0(IoSession session,
495 IoFuture future) {
496 }
497
498 protected static class ServiceOperationFuture extends DefaultIoFuture {
499 public ServiceOperationFuture() {
500 super(null);
501 }
502
503 public final boolean isDone() {
504 return getValue() == Boolean.TRUE;
505 }
506
507 public final void setDone() {
508 setValue(Boolean.TRUE);
509 }
510
511 public final Exception getException() {
512 if (getValue() instanceof Exception) {
513 return (Exception) getValue();
514 } else {
515 return null;
516 }
517 }
518
519 public final void setException(Exception exception) {
520 if (exception == null) {
521 throw new NullPointerException("exception");
522 }
523 setValue(exception);
524 }
525 }
526
527
528
529
530 public int getScheduledWriteBytes() {
531 return stats.getScheduledWriteBytes();
532 }
533
534
535
536
537 public int getScheduledWriteMessages() {
538 return stats.getScheduledWriteMessages();
539 }
540
541 }