001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.common;
021:
022: import java.util.AbstractSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Set;
026: import java.util.concurrent.atomic.AtomicLong;
027:
028: /**
029: * Base implementation of {@link IoService}s.
030: *
031: * @author The Apache MINA Project (dev@mina.apache.org)
032: * @version $Rev: 607163 $, $Date: 2007-12-27 20:20:07 -0700 (Thu, 27 Dec 2007) $
033: */
034: public abstract class AbstractIoService implements IoService {
035: private static final IoServiceListener SERVICE_ACTIVATION_LISTENER = new IoServiceListener() {
036: public void serviceActivated(IoService service) {
037: // Update lastIoTime.
038: AbstractIoService s = (AbstractIoService) service;
039: s.setLastReadTime(s.getActivationTime());
040: s.setLastWriteTime(s.getActivationTime());
041: s.lastThroughputCalculationTime = s.getActivationTime();
042:
043: // Start idleness notification.
044: IdleStatusChecker.getInstance().addService(s);
045: }
046:
047: public void serviceDeactivated(IoService service) {
048: IdleStatusChecker.getInstance().removeService(
049: (AbstractIoService) service);
050: }
051:
052: public void serviceIdle(IoService service, IdleStatus idleStatus) {
053: }
054:
055: public void sessionCreated(IoSession session) {
056: }
057:
058: public void sessionDestroyed(IoSession session) {
059: }
060: };
061:
062: /**
063: * Current filter chain builder.
064: */
065: private IoFilterChainBuilder filterChainBuilder = new DefaultIoFilterChainBuilder();
066:
067: /**
068: * Current handler.
069: */
070: private IoHandler handler;
071:
072: private IoSessionDataStructureFactory sessionDataStructureFactory = new DefaultIoSessionDataStructureFactory();
073:
074: /**
075: * Maintains the {@link IoServiceListener}s of this service.
076: */
077: private final IoServiceListenerSupport listeners;
078:
079: private final Object disposalLock = new Object();
080: private volatile boolean disposing;
081: private volatile boolean disposed;
082: private IoFuture disposalFuture;
083:
084: private final AtomicLong readBytes = new AtomicLong();
085: private final AtomicLong writtenBytes = new AtomicLong();
086: private final AtomicLong readMessages = new AtomicLong();
087: private final AtomicLong writtenMessages = new AtomicLong();
088: private long lastReadTime;
089: private long lastWriteTime;
090:
091: private final AtomicLong scheduledWriteBytes = new AtomicLong();
092: private final AtomicLong scheduledWriteMessages = new AtomicLong();
093:
094: private final Object throughputCalculationLock = new Object();
095: private int throughputCalculationInterval = 3;
096:
097: private long lastThroughputCalculationTime;
098: private long lastReadBytes;
099: private long lastWrittenBytes;
100: private long lastReadMessages;
101: private long lastWrittenMessages;
102: private double readBytesThroughput;
103: private double writtenBytesThroughput;
104: private double readMessagesThroughput;
105: private double writtenMessagesThroughput;
106: private double largestReadBytesThroughput;
107: private double largestWrittenBytesThroughput;
108: private double largestReadMessagesThroughput;
109: private double largestWrittenMessagesThroughput;
110:
111: private final Object idlenessCheckLock = new Object();
112: private int idleTimeForRead;
113: private int idleTimeForWrite;
114: private int idleTimeForBoth;
115:
116: private int idleCountForBoth;
117: private int idleCountForRead;
118: private int idleCountForWrite;
119:
120: private long lastIdleTimeForBoth;
121: private long lastIdleTimeForRead;
122: private long lastIdleTimeForWrite;
123:
124: /**
125: * The default {@link IoSessionConfig} which will be used to configure new sessions.
126: */
127: private IoSessionConfig sessionConfig;
128:
129: protected AbstractIoService(IoSessionConfig sessionConfig) {
130: if (sessionConfig == null) {
131: throw new NullPointerException("sessionConfig");
132: }
133:
134: if (!getTransportMetadata().getSessionConfigType()
135: .isAssignableFrom(sessionConfig.getClass())) {
136: throw new IllegalArgumentException("sessionConfig type: "
137: + sessionConfig.getClass() + " (expected: "
138: + getTransportMetadata().getSessionConfigType()
139: + ")");
140: }
141:
142: this .listeners = new IoServiceListenerSupport(this );
143: this .listeners.add(SERVICE_ACTIVATION_LISTENER);
144: this .sessionConfig = sessionConfig;
145:
146: // Make JVM load the exception monitor before some transports
147: // change the thread context class loader.
148: ExceptionMonitor.getInstance();
149: }
150:
151: public final IoFilterChainBuilder getFilterChainBuilder() {
152: return filterChainBuilder;
153: }
154:
155: public final void setFilterChainBuilder(IoFilterChainBuilder builder) {
156: if (builder == null) {
157: builder = new DefaultIoFilterChainBuilder();
158: }
159: filterChainBuilder = builder;
160: }
161:
162: public final DefaultIoFilterChainBuilder getFilterChain() {
163: if (filterChainBuilder instanceof DefaultIoFilterChainBuilder) {
164: return (DefaultIoFilterChainBuilder) filterChainBuilder;
165: } else {
166: throw new IllegalStateException(
167: "Current filter chain builder is not a DefaultIoFilterChainBuilder.");
168: }
169: }
170:
171: public final void addListener(IoServiceListener listener) {
172: listeners.add(listener);
173: }
174:
175: public final void removeListener(IoServiceListener listener) {
176: listeners.remove(listener);
177: }
178:
179: public final boolean isActive() {
180: return listeners.isActive();
181: }
182:
183: public final boolean isDisposing() {
184: return disposing;
185: }
186:
187: public final boolean isDisposed() {
188: return disposed;
189: }
190:
191: public final void dispose() {
192: if (disposed) {
193: return;
194: }
195:
196: IoFuture disposalFuture;
197: synchronized (disposalLock) {
198: disposalFuture = this .disposalFuture;
199: if (!disposing) {
200: disposing = true;
201: try {
202: this .disposalFuture = disposalFuture = dispose0();
203: } catch (Exception e) {
204: ExceptionMonitor.getInstance().exceptionCaught(e);
205: } finally {
206: if (disposalFuture == null) {
207: disposed = true;
208: }
209: }
210: }
211: }
212:
213: if (disposalFuture != null) {
214: disposalFuture.awaitUninterruptibly();
215: }
216:
217: disposed = true;
218: }
219:
220: /**
221: * Implement this method to release any acquired resources. This method
222: * is invoked only once by {@link #dispose()}.
223: */
224: protected abstract IoFuture dispose0() throws Exception;
225:
226: public final Set<IoSession> getManagedSessions() {
227: return listeners.getManagedSessions();
228: }
229:
230: public final long getCumulativeManagedSessionCount() {
231: return listeners.getCumulativeManagedSessionCount();
232: }
233:
234: public final int getLargestManagedSessionCount() {
235: return listeners.getLargestManagedSessionCount();
236: }
237:
238: public final int getManagedSessionCount() {
239: return listeners.getManagedSessionCount();
240: }
241:
242: public final IoHandler getHandler() {
243: return handler;
244: }
245:
246: public final void setHandler(IoHandler handler) {
247: if (handler == null) {
248: throw new NullPointerException("handler");
249: }
250:
251: if (isActive()) {
252: throw new IllegalStateException(
253: "handler cannot be set while the service is active.");
254: }
255:
256: this .handler = handler;
257: }
258:
259: public IoSessionConfig getSessionConfig() {
260: return sessionConfig;
261: }
262:
263: public final IoSessionDataStructureFactory getSessionDataStructureFactory() {
264: return sessionDataStructureFactory;
265: }
266:
267: public final void setSessionDataStructureFactory(
268: IoSessionDataStructureFactory sessionDataStructureFactory) {
269: if (sessionDataStructureFactory == null) {
270: throw new NullPointerException(
271: "sessionDataStructureFactory");
272: }
273:
274: if (isActive()) {
275: throw new IllegalStateException(
276: "sessionDataStructureFactory cannot be set while the service is active.");
277: }
278:
279: this .sessionDataStructureFactory = sessionDataStructureFactory;
280: }
281:
282: public final long getReadBytes() {
283: return readBytes.get();
284: }
285:
286: protected final void increaseReadBytes(long increment,
287: long currentTime) {
288: readBytes.addAndGet(increment);
289: lastReadTime = currentTime;
290: idleCountForBoth = 0;
291: idleCountForRead = 0;
292: }
293:
294: public final long getReadMessages() {
295: return readMessages.get();
296: }
297:
298: protected final void increaseReadMessages(long currentTime) {
299: readMessages.incrementAndGet();
300: lastReadTime = currentTime;
301: idleCountForBoth = 0;
302: idleCountForRead = 0;
303: }
304:
305: public final int getThroughputCalculationInterval() {
306: return throughputCalculationInterval;
307: }
308:
309: public final void setThroughputCalculationInterval(
310: int throughputCalculationInterval) {
311: if (throughputCalculationInterval < 0) {
312: throw new IllegalArgumentException(
313: "throughputCalculationInterval: "
314: + throughputCalculationInterval);
315: }
316:
317: this .throughputCalculationInterval = throughputCalculationInterval;
318: }
319:
320: public final long getThroughputCalculationIntervalInMillis() {
321: return throughputCalculationInterval * 1000L;
322: }
323:
324: public final double getReadBytesThroughput() {
325: resetThroughput();
326: return readBytesThroughput;
327: }
328:
329: public final double getWrittenBytesThroughput() {
330: resetThroughput();
331: return writtenBytesThroughput;
332: }
333:
334: public final double getReadMessagesThroughput() {
335: resetThroughput();
336: return readMessagesThroughput;
337: }
338:
339: public final double getWrittenMessagesThroughput() {
340: resetThroughput();
341: return writtenMessagesThroughput;
342: }
343:
344: public final double getLargestReadBytesThroughput() {
345: return largestReadBytesThroughput;
346: }
347:
348: public final double getLargestWrittenBytesThroughput() {
349: return largestWrittenBytesThroughput;
350: }
351:
352: public final double getLargestReadMessagesThroughput() {
353: return largestReadMessagesThroughput;
354: }
355:
356: public final double getLargestWrittenMessagesThroughput() {
357: return largestWrittenMessagesThroughput;
358: }
359:
360: private void resetThroughput() {
361: if (getManagedSessionCount() == 0) {
362: readBytesThroughput = 0;
363: writtenBytesThroughput = 0;
364: readMessagesThroughput = 0;
365: writtenMessagesThroughput = 0;
366: }
367: }
368:
369: private void updateThroughput(long currentTime) {
370: synchronized (throughputCalculationLock) {
371: int interval = (int) (currentTime - lastThroughputCalculationTime);
372: long minInterval = getThroughputCalculationIntervalInMillis();
373: if (minInterval == 0 || interval < minInterval) {
374: return;
375: }
376:
377: long readBytes = this .readBytes.get();
378: long writtenBytes = this .writtenBytes.get();
379: long readMessages = this .readMessages.get();
380: long writtenMessages = this .writtenMessages.get();
381:
382: readBytesThroughput = (readBytes - lastReadBytes) * 1000.0
383: / interval;
384: writtenBytesThroughput = (writtenBytes - lastWrittenBytes)
385: * 1000.0 / interval;
386: readMessagesThroughput = (readMessages - lastReadMessages)
387: * 1000.0 / interval;
388: writtenMessagesThroughput = (writtenMessages - lastWrittenMessages)
389: * 1000.0 / interval;
390:
391: if (readBytesThroughput > largestReadBytesThroughput) {
392: largestReadBytesThroughput = readBytesThroughput;
393: }
394: if (writtenBytesThroughput > largestWrittenBytesThroughput) {
395: largestWrittenBytesThroughput = writtenBytesThroughput;
396: }
397: if (readMessagesThroughput > largestReadMessagesThroughput) {
398: largestReadMessagesThroughput = readMessagesThroughput;
399: }
400: if (writtenMessagesThroughput > largestWrittenMessagesThroughput) {
401: largestWrittenMessagesThroughput = writtenMessagesThroughput;
402: }
403:
404: lastReadBytes = readBytes;
405: lastWrittenBytes = writtenBytes;
406: lastReadMessages = readMessages;
407: lastWrittenMessages = writtenMessages;
408:
409: lastThroughputCalculationTime = currentTime;
410: }
411: }
412:
413: public final long getScheduledWriteBytes() {
414: return scheduledWriteBytes.get();
415: }
416:
417: protected final void increaseScheduledWriteBytes(long increment) {
418: scheduledWriteBytes.addAndGet(increment);
419: }
420:
421: public final long getScheduledWriteMessages() {
422: return scheduledWriteMessages.get();
423: }
424:
425: protected final void increaseScheduledWriteMessages() {
426: scheduledWriteMessages.incrementAndGet();
427: }
428:
429: protected final void decreaseScheduledWriteMessages() {
430: scheduledWriteMessages.decrementAndGet();
431: }
432:
433: public final long getActivationTime() {
434: return listeners.getActivationTime();
435: }
436:
437: public final long getLastIoTime() {
438: return Math.max(lastReadTime, lastWriteTime);
439: }
440:
441: public final long getLastReadTime() {
442: return lastReadTime;
443: }
444:
445: protected final void setLastReadTime(long lastReadTime) {
446: this .lastReadTime = lastReadTime;
447: }
448:
449: public final long getLastWriteTime() {
450: return lastWriteTime;
451: }
452:
453: protected final void setLastWriteTime(long lastWriteTime) {
454: this .lastWriteTime = lastWriteTime;
455: }
456:
457: public final long getWrittenBytes() {
458: return writtenBytes.get();
459: }
460:
461: protected final void increaseWrittenBytes(long increment,
462: long currentTime) {
463: writtenBytes.addAndGet(increment);
464: lastWriteTime = currentTime;
465: idleCountForBoth = 0;
466: idleCountForWrite = 0;
467: }
468:
469: public final long getWrittenMessages() {
470: return writtenMessages.get();
471: }
472:
473: protected final void increaseWrittenMessages(long currentTime) {
474: writtenMessages.incrementAndGet();
475: lastWriteTime = currentTime;
476: idleCountForBoth = 0;
477: idleCountForWrite = 0;
478: }
479:
480: public final int getIdleTime(IdleStatus status) {
481: if (status == IdleStatus.BOTH_IDLE) {
482: return idleTimeForBoth;
483: }
484:
485: if (status == IdleStatus.READER_IDLE) {
486: return idleTimeForRead;
487: }
488:
489: if (status == IdleStatus.WRITER_IDLE) {
490: return idleTimeForWrite;
491: }
492:
493: throw new IllegalArgumentException("Unknown idle status: "
494: + status);
495: }
496:
497: public final long getIdleTimeInMillis(IdleStatus status) {
498: return getIdleTime(status) * 1000L;
499: }
500:
501: public final void setIdleTime(IdleStatus status, int idleTime) {
502: if (idleTime < 0) {
503: throw new IllegalArgumentException("Illegal idle time: "
504: + idleTime);
505: }
506:
507: if (status == IdleStatus.BOTH_IDLE) {
508: idleTimeForBoth = idleTime;
509: } else if (status == IdleStatus.READER_IDLE) {
510: idleTimeForRead = idleTime;
511: } else if (status == IdleStatus.WRITER_IDLE) {
512: idleTimeForWrite = idleTime;
513: } else {
514: throw new IllegalArgumentException("Unknown idle status: "
515: + status);
516: }
517:
518: if (idleTime == 0) {
519: if (status == IdleStatus.BOTH_IDLE) {
520: idleCountForBoth = 0;
521: } else if (status == IdleStatus.READER_IDLE) {
522: idleCountForRead = 0;
523: } else if (status == IdleStatus.WRITER_IDLE) {
524: idleCountForWrite = 0;
525: }
526: }
527: }
528:
529: public final boolean isIdle(IdleStatus status) {
530: if (status == IdleStatus.BOTH_IDLE) {
531: return idleCountForBoth > 0;
532: }
533:
534: if (status == IdleStatus.READER_IDLE) {
535: return idleCountForRead > 0;
536: }
537:
538: if (status == IdleStatus.WRITER_IDLE) {
539: return idleCountForWrite > 0;
540: }
541:
542: throw new IllegalArgumentException("Unknown idle status: "
543: + status);
544: }
545:
546: public final int getIdleCount(IdleStatus status) {
547: if (status == IdleStatus.BOTH_IDLE) {
548: return idleCountForBoth;
549: }
550:
551: if (status == IdleStatus.READER_IDLE) {
552: return idleCountForRead;
553: }
554:
555: if (status == IdleStatus.WRITER_IDLE) {
556: return idleCountForWrite;
557: }
558:
559: throw new IllegalArgumentException("Unknown idle status: "
560: + status);
561: }
562:
563: public final long getLastIdleTime(IdleStatus status) {
564: if (status == IdleStatus.BOTH_IDLE) {
565: return lastIdleTimeForBoth;
566: }
567:
568: if (status == IdleStatus.READER_IDLE) {
569: return lastIdleTimeForRead;
570: }
571:
572: if (status == IdleStatus.WRITER_IDLE) {
573: return lastIdleTimeForWrite;
574: }
575:
576: throw new IllegalArgumentException("Unknown idle status: "
577: + status);
578: }
579:
580: private void increaseIdleCount(IdleStatus status, long currentTime) {
581: if (status == IdleStatus.BOTH_IDLE) {
582: idleCountForBoth++;
583: lastIdleTimeForBoth = currentTime;
584: } else if (status == IdleStatus.READER_IDLE) {
585: idleCountForRead++;
586: lastIdleTimeForRead = currentTime;
587: } else if (status == IdleStatus.WRITER_IDLE) {
588: idleCountForWrite++;
589: lastIdleTimeForWrite = currentTime;
590: } else {
591: throw new IllegalArgumentException("Unknown idle status: "
592: + status);
593: }
594: }
595:
596: protected final void notifyIdleness(long currentTime) {
597: updateThroughput(currentTime);
598:
599: synchronized (idlenessCheckLock) {
600: notifyIdleness(currentTime,
601: getIdleTimeInMillis(IdleStatus.BOTH_IDLE),
602: IdleStatus.BOTH_IDLE, Math.max(getLastIoTime(),
603: getLastIdleTime(IdleStatus.BOTH_IDLE)));
604:
605: notifyIdleness(currentTime,
606: getIdleTimeInMillis(IdleStatus.READER_IDLE),
607: IdleStatus.READER_IDLE, Math.max(getLastReadTime(),
608: getLastIdleTime(IdleStatus.READER_IDLE)));
609:
610: notifyIdleness(currentTime,
611: getIdleTimeInMillis(IdleStatus.WRITER_IDLE),
612: IdleStatus.WRITER_IDLE, Math.max(
613: getLastWriteTime(),
614: getLastIdleTime(IdleStatus.WRITER_IDLE)));
615: }
616: }
617:
618: private void notifyIdleness(long currentTime, long idleTime,
619: IdleStatus status, long lastIoTime) {
620: if (idleTime > 0 && lastIoTime != 0
621: && currentTime - lastIoTime >= idleTime) {
622: increaseIdleCount(status, currentTime);
623: listeners.fireServiceIdle(status);
624: }
625: }
626:
627: public final int getBothIdleCount() {
628: return getIdleCount(IdleStatus.BOTH_IDLE);
629: }
630:
631: public final long getLastBothIdleTime() {
632: return getLastIdleTime(IdleStatus.BOTH_IDLE);
633: }
634:
635: public final long getLastReaderIdleTime() {
636: return getLastIdleTime(IdleStatus.READER_IDLE);
637: }
638:
639: public final long getLastWriterIdleTime() {
640: return getLastIdleTime(IdleStatus.WRITER_IDLE);
641: }
642:
643: public final int getReaderIdleCount() {
644: return getIdleCount(IdleStatus.READER_IDLE);
645: }
646:
647: public final int getWriterIdleCount() {
648: return getIdleCount(IdleStatus.WRITER_IDLE);
649: }
650:
651: public final int getBothIdleTime() {
652: return getIdleTime(IdleStatus.BOTH_IDLE);
653: }
654:
655: public final long getBothIdleTimeInMillis() {
656: return getIdleTimeInMillis(IdleStatus.BOTH_IDLE);
657: }
658:
659: public final int getReaderIdleTime() {
660: return getIdleTime(IdleStatus.READER_IDLE);
661: }
662:
663: public final long getReaderIdleTimeInMillis() {
664: return getIdleTimeInMillis(IdleStatus.READER_IDLE);
665: }
666:
667: public final int getWriterIdleTime() {
668: return getIdleTime(IdleStatus.WRITER_IDLE);
669: }
670:
671: public final long getWriterIdleTimeInMillis() {
672: return getIdleTimeInMillis(IdleStatus.WRITER_IDLE);
673: }
674:
675: public final boolean isBothIdle() {
676: return isIdle(IdleStatus.BOTH_IDLE);
677: }
678:
679: public final boolean isReaderIdle() {
680: return isIdle(IdleStatus.READER_IDLE);
681: }
682:
683: public final boolean isWriterIdle() {
684: return isIdle(IdleStatus.WRITER_IDLE);
685: }
686:
687: public final void setBothIdleTime(int idleTime) {
688: setIdleTime(IdleStatus.BOTH_IDLE, idleTime);
689: }
690:
691: public final void setReaderIdleTime(int idleTime) {
692: setIdleTime(IdleStatus.READER_IDLE, idleTime);
693: }
694:
695: public final void setWriterIdleTime(int idleTime) {
696: setIdleTime(IdleStatus.WRITER_IDLE, idleTime);
697: }
698:
699: public final Set<WriteFuture> broadcast(Object message) {
700: // Convert to Set. We do not return a List here because only the
701: // direct caller of MessageBroadcaster knows the order of write
702: // operations.
703: final List<WriteFuture> futures = IoUtil.broadcast(message,
704: getManagedSessions());
705: return new AbstractSet<WriteFuture>() {
706: @Override
707: public Iterator<WriteFuture> iterator() {
708: return futures.iterator();
709: }
710:
711: @Override
712: public int size() {
713: return futures.size();
714: }
715: };
716: }
717:
718: protected final IoServiceListenerSupport getListeners() {
719: return listeners;
720: }
721:
722: // TODO Figure out make it work without causing a compiler error / warning.
723: @SuppressWarnings("unchecked")
724: protected final void finishSessionInitialization(IoSession session,
725: IoFuture future, IoSessionInitializer sessionInitializer) {
726: // Update lastIoTime if needed.
727: if (getLastReadTime() == 0) {
728: setLastReadTime(getActivationTime());
729: }
730: if (getLastWriteTime() == 0) {
731: setLastWriteTime(getActivationTime());
732: }
733:
734: // Every property but attributeMap should be set now.
735: // Now initialize the attributeMap. The reason why we initialize
736: // the attributeMap at last is to make sure all session properties
737: // such as remoteAddress are provided to IoSessionDataStructureFactory.
738: try {
739: ((AbstractIoSession) session).setAttributeMap(session
740: .getService().getSessionDataStructureFactory()
741: .getAttributeMap(session));
742: } catch (IoSessionInitializationException e) {
743: throw e;
744: } catch (Exception e) {
745: throw new IoSessionInitializationException(
746: "Failed to initialize an attributeMap.", e);
747: }
748:
749: try {
750: ((AbstractIoSession) session).setWriteRequestQueue(session
751: .getService().getSessionDataStructureFactory()
752: .getWriteRequestQueue(session));
753: } catch (IoSessionInitializationException e) {
754: throw e;
755: } catch (Exception e) {
756: throw new IoSessionInitializationException(
757: "Failed to initialize a writeRequestQueue.", e);
758: }
759:
760: if (future != null && future instanceof ConnectFuture) {
761: // DefaultIoFilterChain will notify the future. (We support ConnectFuture only for now).
762: session.setAttribute(
763: DefaultIoFilterChain.SESSION_OPENED_FUTURE, future);
764: }
765:
766: if (sessionInitializer != null) {
767: sessionInitializer.initializeSession(session, future);
768: }
769:
770: finishSessionInitialization0(session, future);
771: }
772:
773: /**
774: * Implement this method to perform additional tasks required for session
775: * initialization. Do not call this method directly;
776: * {@link #finishSessionInitialization(IoSession, IoFuture, IoSessionInitializer)} will call
777: * this method instead.
778: */
779: @SuppressWarnings("unused")
780: protected void finishSessionInitialization0(IoSession session,
781: IoFuture future) {
782: }
783:
784: protected static class ServiceOperationFuture extends
785: DefaultIoFuture {
786: public ServiceOperationFuture() {
787: super (null);
788: }
789:
790: public final boolean isDone() {
791: return getValue() == Boolean.TRUE;
792: }
793:
794: public final void setDone() {
795: setValue(Boolean.TRUE);
796: }
797:
798: public final Exception getException() {
799: if (getValue() instanceof Exception) {
800: return (Exception) getValue();
801: } else {
802: return null;
803: }
804: }
805:
806: public final void setException(Exception exception) {
807: if (exception == null) {
808: throw new NullPointerException("exception");
809: }
810: setValue(exception);
811: }
812: }
813: }
|