You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ed...@apache.org on 2008/08/10 23:20:07 UTC

svn commit: r684597 - in /mina/trunk/core/src/main/java/org/apache/mina/core: service/AbstractIoService.java service/IoServiceIdleState.java service/IoServiceStatistics.java session/AbstractIoSession.java

Author: edeoliveira
Date: Sun Aug 10 14:20:07 2008
New Revision: 684597

URL: http://svn.apache.org/viewvc?rev=684597&view=rev
Log:
DIRMINA-608 extracted stats and idle state methods to make AbstractIoService lighter

Added:
    mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceIdleState.java   (with props)
    mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java   (with props)
Modified:
    mina/trunk/core/src/main/java/org/apache/mina/core/service/AbstractIoService.java
    mina/trunk/core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java

Modified: mina/trunk/core/src/main/java/org/apache/mina/core/service/AbstractIoService.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/core/service/AbstractIoService.java?rev=684597&r1=684596&r2=684597&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/core/service/AbstractIoService.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/core/service/AbstractIoService.java Sun Aug 10 14:20:07 2008
@@ -29,7 +29,6 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.mina.core.IoUtil;
 import org.apache.mina.core.filterchain.DefaultIoFilterChain;
@@ -51,7 +50,6 @@
 import org.apache.mina.util.ExceptionMonitor;
 import org.apache.mina.util.NamePreservingRunnable;
 
-
 /**
  * Base implementation of {@link IoService}s.
  * 
@@ -61,18 +59,19 @@
  * @author The Apache MINA Project (dev@mina.apache.org)
  * @version $Rev$, $Date$
  */
-public abstract class AbstractIoService implements IoService, IoServiceStatistics, IoServiceIdleState {
+public abstract class AbstractIoService implements IoService {
     /** 
      * The unique number identifying the Service. It's incremented
      * for each new IoService created.
      */
     private static final AtomicInteger id = new AtomicInteger();
 
-    /** The thread name built from the IoService unherited 
+    /** 
+     * The thread name built from the IoService inherited 
      * instance class name and the IoService Id 
      **/
     private final String threadName;
-    
+
     /**
      * The associated executor, responsible for handling execution of I/O events.
      */
@@ -97,26 +96,31 @@
      */
     private final IoSessionConfig sessionConfig;
 
-    private final IoServiceListener serviceActivationListener =
-        new IoServiceListener() {
-            public void serviceActivated(IoService service) {
-                // Update lastIoTime.
-                AbstractIoService s = (AbstractIoService) service;
-                s.setLastReadTime(s.getActivationTime());
-                s.setLastWriteTime(s.getActivationTime());
-                s.lastThroughputCalculationTime = s.getActivationTime();
+    private final IoServiceListener serviceActivationListener = new IoServiceListener() {
+        public void serviceActivated(IoService service) {
+            // Update lastIoTime.
+            AbstractIoService s = (AbstractIoService) service;
+            IoServiceStatistics _stats = (IoServiceStatistics) s.getStatistics();
+            _stats.setLastReadTime(s.getActivationTime());
+            _stats.setLastWriteTime(s.getActivationTime());
+            _stats.setLastThroughputCalculationTime(s.getActivationTime());
 
-                // Start idleness notification.
-                idleStatusChecker.addService(s);
-            }
+            // Start idleness notification.
+            idleStatusChecker.addService(s);
+        }
 
-            public void serviceDeactivated(IoService service) {
-                idleStatusChecker.removeService((AbstractIoService) service);
-            }
+        public void serviceDeactivated(IoService service) {
+            idleStatusChecker.removeService((AbstractIoService) service);
+        }
+
+        public void serviceIdle(IoService service, IdleStatus idleStatus) {
+        }
+
+        public void sessionCreated(IoSession session) {
+        }
 
-            public void serviceIdle(IoService service, IdleStatus idleStatus) {}
-            public void sessionCreated(IoSession session) {}
-            public void sessionDestroyed(IoSession session) {}
+        public void sessionDestroyed(IoSession session) {
+        }
     };
 
     /**
@@ -124,8 +128,7 @@
      */
     private IoFilterChainBuilder filterChainBuilder = new DefaultIoFilterChainBuilder();
 
-    private IoSessionDataStructureFactory sessionDataStructureFactory =
-        new DefaultIoSessionDataStructureFactory();
+    private IoSessionDataStructureFactory sessionDataStructureFactory = new DefaultIoSessionDataStructureFactory();
 
     /**
      * Maintains the {@link IoServiceListener}s of this service.
@@ -137,68 +140,42 @@
      * destroyed.
      */
     protected final Object disposalLock = new Object();
+
     private volatile boolean disposing;
+
     private volatile boolean disposed;
-    private IoFuture disposalFuture;
 
-    private final AtomicLong readBytes = new AtomicLong();
-    private final AtomicLong writtenBytes = new AtomicLong();
-    private final AtomicLong readMessages = new AtomicLong();
-    private final AtomicLong writtenMessages = new AtomicLong();
-    private long lastReadTime;
-    private long lastWriteTime;
-
-    private final AtomicInteger scheduledWriteBytes = new AtomicInteger();
-    private final AtomicInteger scheduledWriteMessages = new AtomicInteger();
-
-    private final Object throughputCalculationLock = new Object();
-    private int throughputCalculationInterval = 3;
-
-    private long lastThroughputCalculationTime;
-    private long lastReadBytes;
-    private long lastWrittenBytes;
-    private long lastReadMessages;
-    private long lastWrittenMessages;
-    private double readBytesThroughput;
-    private double writtenBytesThroughput;
-    private double readMessagesThroughput;
-    private double writtenMessagesThroughput;
-    private double largestReadBytesThroughput;
-    private double largestWrittenBytesThroughput;
-    private double largestReadMessagesThroughput;
-    private double largestWrittenMessagesThroughput;
+    private IoFuture disposalFuture;
 
     private final IdleStatusChecker idleStatusChecker = new IdleStatusChecker();
-    private final Object idlenessCheckLock = new Object();
-    private int idleTimeForRead;
-    private int idleTimeForWrite;
-    private int idleTimeForBoth;
-
-    private int idleCountForBoth;
-    private int idleCountForRead;
-    private int idleCountForWrite;
-
-    private long lastIdleTimeForBoth;
-    private long lastIdleTimeForRead;
-    private long lastIdleTimeForWrite;
-
-    /**
-	 * Constructor for {@link AbstractIoService}. You need to provide a default
-	 * session configuration and an {@link Executor} for handling I/O events. If
-	 * a null {@link Executor} is provided, a default one will be created using
-	 * {@link Executors#newCachedThreadPool()}.
-	 * 
-	 * @param sessionConfig
-	 *            the default configuration for the managed {@link IoSession}
-	 * @param executor
-	 *            the {@link Executor} used for handling execution of I/O
-	 *            events. Can be <code>null</code>.
-	 */
+
+    /**
+     * {@inheritDoc}
+     */
+    private IoServiceStatistics stats = new IoServiceStatistics(this);
+    
+    /**
+     * Reference to the object holding all the idle state vars.
+     */    
+    private IoServiceIdleState idleState = new IoServiceIdleState(this);
+
+    /**
+     * Constructor for {@link AbstractIoService}. You need to provide a default
+     * session configuration and an {@link Executor} for handling I/O events. If
+     * a null {@link Executor} is provided, a default one will be created using
+     * {@link Executors#newCachedThreadPool()}.
+     * 
+     * @param sessionConfig
+     *            the default configuration for the managed {@link IoSession}
+     * @param executor
+     *            the {@link Executor} used for handling execution of I/O
+     *            events. Can be <code>null</code>.
+     */
     protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {
         if (sessionConfig == null) {
             throw new NullPointerException("sessionConfig");
         }
-        
+
         if (getTransportMetadata() == null) {
             throw new NullPointerException("TransportMetadata");
         }
@@ -214,7 +191,7 @@
         // for this service, which will give information on the service state.
         listeners = new IoServiceListenerSupport(this);
         listeners.add(serviceActivationListener);
-        
+
         // Stores the given session configuration
         this.sessionConfig = sessionConfig;
 
@@ -328,7 +305,7 @@
         if (disposalFuture != null) {
             disposalFuture.awaitUninterruptibly();
         }
-        
+
         if (createdExecutor) {
             ExecutorService e = (ExecutorService) executor;
             e.shutdown();
@@ -360,20 +337,6 @@
     /**
      * {@inheritDoc}
      */
-    public final long getCumulativeManagedSessionCount() {
-        return listeners.getCumulativeManagedSessionCount();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getLargestManagedSessionCount() {
-        return listeners.getLargestManagedSessionCount();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public final int getManagedSessionCount() {
         return listeners.getManagedSessionCount();
     }
@@ -394,7 +357,8 @@
         }
 
         if (isActive()) {
-            throw new IllegalStateException("handler cannot be set while the service is active.");
+            throw new IllegalStateException(
+                    "handler cannot be set while the service is active.");
         }
 
         this.handler = handler;
@@ -417,7 +381,8 @@
     /**
      * {@inheritDoc}
      */
-    public final void setSessionDataStructureFactory(IoSessionDataStructureFactory sessionDataStructureFactory) {
+    public final void setSessionDataStructureFactory(
+            IoSessionDataStructureFactory sessionDataStructureFactory) {
         if (sessionDataStructureFactory == null) {
             throw new NullPointerException("sessionDataStructureFactory");
         }
@@ -434,203 +399,14 @@
      * {@inheritDoc}
      */
     public IoServiceIdleState getIdleState() {
-        return this;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public IoServiceStatistics getStatistics() {
-        return this;
-    }
-       
-    /**
-     * {@inheritDoc}
-     */
-    public final long getReadBytes() {
-        return readBytes.get();
-    }
-
-    public final void increaseReadBytes(long increment, long currentTime) {
-        readBytes.addAndGet(increment);
-        lastReadTime = currentTime;
-        idleCountForBoth = 0;
-        idleCountForRead = 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getReadMessages() {
-        return readMessages.get();
-    }
-
-    public final void increaseReadMessages(long currentTime) {
-        readMessages.incrementAndGet();
-        lastReadTime = currentTime;
-        idleCountForBoth = 0;
-        idleCountForRead = 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getThroughputCalculationInterval() {
-        return throughputCalculationInterval;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final void setThroughputCalculationInterval(int throughputCalculationInterval) {
-        if (throughputCalculationInterval < 0) {
-            throw new IllegalArgumentException(
-                    "throughputCalculationInterval: " + throughputCalculationInterval);
-        }
-
-        this.throughputCalculationInterval = throughputCalculationInterval;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getThroughputCalculationIntervalInMillis() {
-        return throughputCalculationInterval * 1000L;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getReadBytesThroughput() {
-        resetThroughput();
-        return readBytesThroughput;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getWrittenBytesThroughput() {
-        resetThroughput();
-        return writtenBytesThroughput;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getReadMessagesThroughput() {
-        resetThroughput();
-        return readMessagesThroughput;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getWrittenMessagesThroughput() {
-        resetThroughput();
-        return writtenMessagesThroughput;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getLargestReadBytesThroughput() {
-        return largestReadBytesThroughput;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getLargestWrittenBytesThroughput() {
-        return largestWrittenBytesThroughput;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final double getLargestReadMessagesThroughput() {
-        return largestReadMessagesThroughput;
+        return idleState;
     }
 
     /**
      * {@inheritDoc}
      */
-    public final double getLargestWrittenMessagesThroughput() {
-        return largestWrittenMessagesThroughput;
-    }
-
-    private void resetThroughput() {
-        if (getManagedSessionCount() == 0) {
-            readBytesThroughput = 0;
-            writtenBytesThroughput = 0;
-            readMessagesThroughput = 0;
-            writtenMessagesThroughput = 0;
-        }
-    }
-
-    private void updateThroughput(long currentTime) {
-        synchronized (throughputCalculationLock) {
-            int interval = (int) (currentTime - lastThroughputCalculationTime);
-            long minInterval = getThroughputCalculationIntervalInMillis();
-            if (minInterval == 0 || interval < minInterval) {
-                return;
-            }
-
-            long readBytes = this.readBytes.get();
-            long writtenBytes = this.writtenBytes.get();
-            long readMessages = this.readMessages.get();
-            long writtenMessages = this.writtenMessages.get();
-
-            readBytesThroughput = (readBytes - lastReadBytes) * 1000.0 / interval;
-            writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0 / interval;
-            readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0 / interval;
-            writtenMessagesThroughput = (writtenMessages - lastWrittenMessages) * 1000.0 / interval;
-
-            if (readBytesThroughput > largestReadBytesThroughput) {
-                largestReadBytesThroughput = readBytesThroughput;
-            }
-            if (writtenBytesThroughput > largestWrittenBytesThroughput) {
-                largestWrittenBytesThroughput = writtenBytesThroughput;
-            }
-            if (readMessagesThroughput > largestReadMessagesThroughput) {
-                largestReadMessagesThroughput = readMessagesThroughput;
-            }
-            if (writtenMessagesThroughput > largestWrittenMessagesThroughput) {
-                largestWrittenMessagesThroughput = writtenMessagesThroughput;
-            }
-
-            lastReadBytes = readBytes;
-            lastWrittenBytes = writtenBytes;
-            lastReadMessages = readMessages;
-            lastWrittenMessages = writtenMessages;
-
-            lastThroughputCalculationTime = currentTime;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getScheduledWriteBytes() {
-        return scheduledWriteBytes.get();
-    }
-
-    public final void increaseScheduledWriteBytes(int increment) {
-        scheduledWriteBytes.addAndGet(increment);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getScheduledWriteMessages() {
-        return scheduledWriteMessages.get();
-    }
-
-    public final void increaseScheduledWriteMessages() {
-        scheduledWriteMessages.incrementAndGet();
-    }
-
-    public final void decreaseScheduledWriteMessages() {
-        scheduledWriteMessages.decrementAndGet();
+    public IoServiceStatistics getStatistics() {
+        return stats;
     }
 
     /**
@@ -643,358 +419,12 @@
     /**
      * {@inheritDoc}
      */
-    public final long getLastIoTime() {
-        return Math.max(lastReadTime, lastWriteTime);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getLastReadTime() {
-        return lastReadTime;
-    }
-
-    protected final void setLastReadTime(long lastReadTime) {
-        this.lastReadTime = lastReadTime;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getLastWriteTime() {
-        return lastWriteTime;
-    }
-
-    protected final void setLastWriteTime(long lastWriteTime) {
-        this.lastWriteTime = lastWriteTime;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getWrittenBytes() {
-        return writtenBytes.get();
-    }
-
-    public final void increaseWrittenBytes(long increment, long currentTime) {
-        writtenBytes.addAndGet(increment);
-        lastWriteTime = currentTime;
-        idleCountForBoth = 0;
-        idleCountForWrite = 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getWrittenMessages() {
-        return writtenMessages.get();
-    }
-
-    public final void increaseWrittenMessages(long currentTime) {
-        writtenMessages.incrementAndGet();
-        lastWriteTime = currentTime;
-        idleCountForBoth = 0;
-        idleCountForWrite = 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getIdleTime(IdleStatus status) {
-        if (status == IdleStatus.BOTH_IDLE) {
-            return idleTimeForBoth;
-        }
-
-        if (status == IdleStatus.READER_IDLE) {
-            return idleTimeForRead;
-        }
-
-        if (status == IdleStatus.WRITER_IDLE) {
-            return idleTimeForWrite;
-        }
-
-        throw new IllegalArgumentException("Unknown idle status: " + status);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getIdleTimeInMillis(IdleStatus status) {
-        return getIdleTime(status) * 1000L;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final void setIdleTime(IdleStatus status, int idleTime) {
-        if (idleTime < 0) {
-            throw new IllegalArgumentException("Illegal idle time: " + idleTime);
-        }
-
-        if (status == IdleStatus.BOTH_IDLE) {
-            idleTimeForBoth = idleTime;
-        } else if (status == IdleStatus.READER_IDLE) {
-            idleTimeForRead = idleTime;
-        } else if (status == IdleStatus.WRITER_IDLE) {
-            idleTimeForWrite = idleTime;
-        } else {
-            throw new IllegalArgumentException("Unknown idle status: " + status);
-        }
-
-        if (idleTime == 0) {
-            if (status == IdleStatus.BOTH_IDLE) {
-                idleCountForBoth = 0;
-            } else if (status == IdleStatus.READER_IDLE) {
-                idleCountForRead = 0;
-            } else if (status == IdleStatus.WRITER_IDLE) {
-                idleCountForWrite = 0;
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final boolean isIdle(IdleStatus status) {
-        if (status == IdleStatus.BOTH_IDLE) {
-            return idleCountForBoth > 0;
-        }
-
-        if (status == IdleStatus.READER_IDLE) {
-            return idleCountForRead > 0;
-        }
-
-        if (status == IdleStatus.WRITER_IDLE) {
-            return idleCountForWrite > 0;
-        }
-
-        throw new IllegalArgumentException("Unknown idle status: " + status);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getIdleCount(IdleStatus status) {
-        if (status == IdleStatus.BOTH_IDLE) {
-            return idleCountForBoth;
-        }
-
-        if (status == IdleStatus.READER_IDLE) {
-            return idleCountForRead;
-        }
-
-        if (status == IdleStatus.WRITER_IDLE) {
-            return idleCountForWrite;
-        }
-
-        throw new IllegalArgumentException("Unknown idle status: " + status);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getLastIdleTime(IdleStatus status) {
-        if (status == IdleStatus.BOTH_IDLE) {
-            return lastIdleTimeForBoth;
-        }
-
-        if (status == IdleStatus.READER_IDLE) {
-            return lastIdleTimeForRead;
-        }
-
-        if (status == IdleStatus.WRITER_IDLE) {
-            return lastIdleTimeForWrite;
-        }
-
-        throw new IllegalArgumentException("Unknown idle status: " + status);
-    }
-
-    private void increaseIdleCount(IdleStatus status, long currentTime) {
-        if (status == IdleStatus.BOTH_IDLE) {
-            idleCountForBoth++;
-            lastIdleTimeForBoth = currentTime;
-        } else if (status == IdleStatus.READER_IDLE) {
-            idleCountForRead++;
-            lastIdleTimeForRead = currentTime;
-        } else if (status == IdleStatus.WRITER_IDLE) {
-            idleCountForWrite++;
-            lastIdleTimeForWrite = currentTime;
-        } else {
-            throw new IllegalArgumentException("Unknown idle status: " + status);
-        }
-    }
-
-    public final void notifyIdleness(long currentTime) {
-        updateThroughput(currentTime);
-
-        synchronized (idlenessCheckLock) {
-            notifyIdleness(
-                    currentTime,
-                    getIdleTimeInMillis(IdleStatus.BOTH_IDLE),
-                    IdleStatus.BOTH_IDLE, Math.max(
-                            getLastIoTime(),
-                            getLastIdleTime(IdleStatus.BOTH_IDLE)));
-
-            notifyIdleness(
-                    currentTime,
-                    getIdleTimeInMillis(IdleStatus.READER_IDLE),
-                    IdleStatus.READER_IDLE, Math.max(
-                            getLastReadTime(),
-                            getLastIdleTime(IdleStatus.READER_IDLE)));
-
-            notifyIdleness(
-                    currentTime,
-                    getIdleTimeInMillis(IdleStatus.WRITER_IDLE),
-                    IdleStatus.WRITER_IDLE, Math.max(
-                            getLastWriteTime(),
-                            getLastIdleTime(IdleStatus.WRITER_IDLE)));
-        }
-    }
-
-    private void notifyIdleness(
-            long currentTime, long idleTime, IdleStatus status, long lastIoTime) {
-        if (idleTime > 0 && lastIoTime != 0
-                && currentTime - lastIoTime >= idleTime) {
-            increaseIdleCount(status, currentTime);
-            listeners.fireServiceIdle(status);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getBothIdleCount() {
-        return getIdleCount(IdleStatus.BOTH_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getLastBothIdleTime() {
-        return getLastIdleTime(IdleStatus.BOTH_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getLastReaderIdleTime() {
-        return getLastIdleTime(IdleStatus.READER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getLastWriterIdleTime() {
-        return getLastIdleTime(IdleStatus.WRITER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getReaderIdleCount() {
-        return getIdleCount(IdleStatus.READER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getWriterIdleCount() {
-        return getIdleCount(IdleStatus.WRITER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getBothIdleTime() {
-        return getIdleTime(IdleStatus.BOTH_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getBothIdleTimeInMillis() {
-        return getIdleTimeInMillis(IdleStatus.BOTH_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getReaderIdleTime() {
-        return getIdleTime(IdleStatus.READER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getReaderIdleTimeInMillis() {
-        return getIdleTimeInMillis(IdleStatus.READER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final int getWriterIdleTime() {
-        return getIdleTime(IdleStatus.WRITER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final long getWriterIdleTimeInMillis() {
-        return getIdleTimeInMillis(IdleStatus.WRITER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final boolean isBothIdle() {
-        return isIdle(IdleStatus.BOTH_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final boolean isReaderIdle() {
-        return isIdle(IdleStatus.READER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final boolean isWriterIdle() {
-        return isIdle(IdleStatus.WRITER_IDLE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final void setBothIdleTime(int idleTime) {
-        setIdleTime(IdleStatus.BOTH_IDLE, idleTime);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final void setReaderIdleTime(int idleTime) {
-        setIdleTime(IdleStatus.READER_IDLE, idleTime);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public final void setWriterIdleTime(int idleTime) {
-        setIdleTime(IdleStatus.WRITER_IDLE, idleTime);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public final Set<WriteFuture> broadcast(Object message) {
         // Convert to Set.  We do not return a List here because only the
         // direct caller of MessageBroadcaster knows the order of write
         // operations.
-        final List<WriteFuture> futures = IoUtil.broadcast(
-                message, getManagedSessions().values());
+        final List<WriteFuture> futures = IoUtil.broadcast(message,
+                getManagedSessions().values());
         return new AbstractSet<WriteFuture>() {
             @Override
             public Iterator<WriteFuture> iterator() {
@@ -1030,14 +460,14 @@
 
     // TODO Figure out make it work without causing a compiler error / warning.
     @SuppressWarnings("unchecked")
-    protected final void finishSessionInitialization(
-            IoSession session, IoFuture future, IoSessionInitializer sessionInitializer) {
+    protected final void finishSessionInitialization(IoSession session,
+            IoFuture future, IoSessionInitializer sessionInitializer) {
         // Update lastIoTime if needed.
-        if (getLastReadTime() == 0) {
-            setLastReadTime(getActivationTime());
+        if (stats.getLastReadTime() == 0) {
+            ((IoServiceStatistics)stats).setLastReadTime(getActivationTime());
         }
-        if (getLastWriteTime() == 0) {
-            setLastWriteTime(getActivationTime());
+        if (stats.getLastWriteTime() == 0) {
+            ((IoServiceStatistics)stats).setLastWriteTime(getActivationTime());
         }
 
         // Every property but attributeMap should be set now.
@@ -1045,8 +475,8 @@
         // the attributeMap at last is to make sure all session properties
         // such as remoteAddress are provided to IoSessionDataStructureFactory.
         try {
-            ((AbstractIoSession) session).setAttributeMap(
-                    session.getService().getSessionDataStructureFactory().getAttributeMap(session));
+            ((AbstractIoSession) session).setAttributeMap(session.getService()
+                    .getSessionDataStructureFactory().getAttributeMap(session));
         } catch (IoSessionInitializationException e) {
             throw e;
         } catch (Exception e) {
@@ -1055,8 +485,9 @@
         }
 
         try {
-            ((AbstractIoSession) session).setWriteRequestQueue(
-                    session.getService().getSessionDataStructureFactory().getWriteRequestQueue(session));
+            ((AbstractIoSession) session).setWriteRequestQueue(session
+                    .getService().getSessionDataStructureFactory()
+                    .getWriteRequestQueue(session));
         } catch (IoSessionInitializationException e) {
             throw e;
         } catch (Exception e) {
@@ -1066,7 +497,8 @@
 
         if (future != null && future instanceof ConnectFuture) {
             // DefaultIoFilterChain will notify the future. (We support ConnectFuture only for now).
-            session.setAttribute(DefaultIoFilterChain.SESSION_CREATED_FUTURE, future);
+            session.setAttribute(DefaultIoFilterChain.SESSION_CREATED_FUTURE,
+                    future);
         }
 
         if (sessionInitializer != null) {
@@ -1082,7 +514,9 @@
      * {@link #finishSessionInitialization(IoSession, IoFuture, IoSessionInitializer)} will call
      * this method instead.
      */
-    protected void finishSessionInitialization0(IoSession session, IoFuture future) {}
+    protected void finishSessionInitialization0(IoSession session,
+            IoFuture future) {
+    }
 
     protected static class ServiceOperationFuture extends DefaultIoFuture {
         public ServiceOperationFuture() {
@@ -1112,4 +546,25 @@
             setValue(exception);
         }
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getScheduledWriteBytes() {
+        return stats.getScheduledWriteBytes();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getScheduledWriteMessages() {
+        return stats.getScheduledWriteMessages();
+    }
+    
+    /**
+     * TODO
+     */    
+    public void notifyIdleness(long currentTime) {
+        idleState.notifyIdleness(currentTime);
+    }
 }

Added: mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceIdleState.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceIdleState.java?rev=684597&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceIdleState.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceIdleState.java Sun Aug 10 14:20:07 2008
@@ -0,0 +1,385 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.mina.core.service;
+
+import org.apache.mina.core.session.IdleStatus;
+
+/**
+ * Provides the idle state information associated with an {@link AbstractIoService}.
+ * 
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ * @since 2.0.0-M3
+ */
+public class IoServiceIdleState {
+
+    private AbstractIoService service;
+    
+    private int idleTimeForRead;
+    private int idleTimeForWrite;
+    private int idleTimeForBoth;
+
+    private int idleCountForBoth;
+    private int idleCountForRead;
+    private int idleCountForWrite;
+
+    private long lastIdleTimeForBoth;
+    private long lastIdleTimeForRead;
+    private long lastIdleTimeForWrite;
+
+    private final Object idlenessCheckLock = new Object();
+
+    public IoServiceIdleState(AbstractIoService service) {
+        this.service = service;
+    }
+
+    /**
+     * Returns <code>true</code> if this service is idle for the specified
+     * {@link IdleStatus}.
+     */
+    public final boolean isIdle(IdleStatus status) {
+        if (status == IdleStatus.BOTH_IDLE) {
+            return idleCountForBoth > 0;
+        }
+
+        if (status == IdleStatus.READER_IDLE) {
+            return idleCountForRead > 0;
+        }
+
+        if (status == IdleStatus.WRITER_IDLE) {
+            return idleCountForWrite > 0;
+        }
+
+        throw new IllegalArgumentException("Unknown idle status: " + status);
+    }
+
+    /**
+     * Returns <code>true</code> if this service is {@link IdleStatus#READER_IDLE}.
+     * @see #isIdle(IdleStatus)
+     */
+    public final boolean isReaderIdle() {
+        return isIdle(IdleStatus.READER_IDLE);
+    }
+
+    /**
+     * Returns <code>true</code> if this service is {@link IdleStatus#WRITER_IDLE}.
+     * @see #isIdle(IdleStatus)
+     */
+    public final boolean isWriterIdle() {
+        return isIdle(IdleStatus.WRITER_IDLE);
+    }
+
+    /**
+     * Returns <code>true</code> if this service is {@link IdleStatus#BOTH_IDLE}.
+     * @see #isIdle(IdleStatus)
+     */
+    public final boolean isBothIdle() {
+        return isIdle(IdleStatus.BOTH_IDLE);
+    }
+
+    /**
+     * Returns the number of the fired continuous <tt>serviceIdle</tt> events
+     * for the specified {@link IdleStatus}.
+     * <p/>
+     * If <tt>serviceIdle</tt> event is fired first after some time after I/O,
+     * <tt>idleCount</tt> becomes <tt>1</tt>.  <tt>idleCount</tt> resets to
+     * <tt>0</tt> if any I/O occurs again, otherwise it increases to
+     * <tt>2</tt> and so on if <tt>serviceIdle</tt> event is fired again without
+     * any I/O between two (or more) <tt>serviceIdle</tt> events.
+     */
+    public final int getIdleCount(IdleStatus status) {
+        if (status == IdleStatus.BOTH_IDLE) {
+            return idleCountForBoth;
+        }
+
+        if (status == IdleStatus.READER_IDLE) {
+            return idleCountForRead;
+        }
+
+        if (status == IdleStatus.WRITER_IDLE) {
+            return idleCountForWrite;
+        }
+
+        throw new IllegalArgumentException("Unknown idle status: " + status);
+    }
+
+    /**
+     * Returns the number of the fired continuous <tt>serviceIdle</tt> events
+     * for {@link IdleStatus#READER_IDLE}.
+     * @see #getIdleCount(IdleStatus)
+     */
+    public final int getReaderIdleCount() {
+        return getIdleCount(IdleStatus.READER_IDLE);
+    }
+
+    /**
+     * Returns the number of the fired continuous <tt>serviceIdle</tt> events
+     * for {@link IdleStatus#WRITER_IDLE}.
+     * @see #getIdleCount(IdleStatus)
+     */
+    public final int getWriterIdleCount() {
+        return getIdleCount(IdleStatus.WRITER_IDLE);
+    }
+
+    /**
+     * Returns the number of the fired continuous <tt>serviceIdle</tt> events
+     * for {@link IdleStatus#BOTH_IDLE}.
+     * @see #getIdleCount(IdleStatus)
+     */
+    public final int getBothIdleCount() {
+        return getIdleCount(IdleStatus.BOTH_IDLE);
+    }
+
+    /**
+     * Returns the time in milliseconds when the last <tt>serviceIdle</tt> event
+     * is fired for the specified {@link IdleStatus}.
+     */
+    public final long getLastIdleTime(IdleStatus status) {
+        if (status == IdleStatus.BOTH_IDLE) {
+            return lastIdleTimeForBoth;
+        }
+
+        if (status == IdleStatus.READER_IDLE) {
+            return lastIdleTimeForRead;
+        }
+
+        if (status == IdleStatus.WRITER_IDLE) {
+            return lastIdleTimeForWrite;
+        }
+
+        throw new IllegalArgumentException("Unknown idle status: " + status);
+    }
+
+    /**
+     * Returns the time in milliseconds when the last <tt>serviceIdle</tt> event
+     * is fired for {@link IdleStatus#READER_IDLE}.
+     * @see #getLastIdleTime(IdleStatus)
+     */
+    public final long getLastReaderIdleTime() {
+        return getLastIdleTime(IdleStatus.READER_IDLE);
+    }
+
+    /**
+     * Returns the time in milliseconds when the last <tt>serviceIdle</tt> event
+     * is fired for {@link IdleStatus#WRITER_IDLE}.
+     * @see #getLastIdleTime(IdleStatus)
+     */
+    public final long getLastWriterIdleTime() {
+        return getLastIdleTime(IdleStatus.WRITER_IDLE);
+    }
+
+    /**
+     * Returns the time in milliseconds when the last <tt>serviceIdle</tt> event
+     * is fired for {@link IdleStatus#BOTH_IDLE}.
+     * @see #getLastIdleTime(IdleStatus)
+     */
+    public final long getLastBothIdleTime() {
+        return getLastIdleTime(IdleStatus.BOTH_IDLE);
+    }
+
+    /**
+     * Returns idle time for the specified type of idleness in seconds.
+     */
+    public final int getIdleTime(IdleStatus status) {
+        if (status == IdleStatus.BOTH_IDLE) {
+            return idleTimeForBoth;
+        }
+
+        if (status == IdleStatus.READER_IDLE) {
+            return idleTimeForRead;
+        }
+
+        if (status == IdleStatus.WRITER_IDLE) {
+            return idleTimeForWrite;
+        }
+
+        throw new IllegalArgumentException("Unknown idle status: " + status);
+    }
+
+    /**
+     * Returns idle time for the specified type of idleness in milliseconds.
+     */
+    public final long getIdleTimeInMillis(IdleStatus status) {
+        return getIdleTime(status) * 1000L;
+    }
+
+    /**
+     * Sets idle time for the specified type of idleness in seconds.
+     */
+    public final void setIdleTime(IdleStatus status, int idleTime) {
+        if (idleTime < 0) {
+            throw new IllegalArgumentException("Illegal idle time: " + idleTime);
+        }
+
+        if (status == IdleStatus.BOTH_IDLE) {
+            idleTimeForBoth = idleTime;
+        } else if (status == IdleStatus.READER_IDLE) {
+            idleTimeForRead = idleTime;
+        } else if (status == IdleStatus.WRITER_IDLE) {
+            idleTimeForWrite = idleTime;
+        } else {
+            throw new IllegalArgumentException("Unknown idle status: " + status);
+        }
+
+        if (idleTime == 0) {
+            if (status == IdleStatus.BOTH_IDLE) {
+                idleCountForBoth = 0;
+            } else if (status == IdleStatus.READER_IDLE) {
+                idleCountForRead = 0;
+            } else if (status == IdleStatus.WRITER_IDLE) {
+                idleCountForWrite = 0;
+            }
+        }
+    }
+
+    /**
+     * Returns idle time for {@link IdleStatus#READER_IDLE} in seconds.
+     */
+    public final int getReaderIdleTime() {
+        return getIdleTime(IdleStatus.READER_IDLE);
+    }
+
+    /**
+     * Returns idle time for {@link IdleStatus#READER_IDLE} in milliseconds.
+     */
+    public final long getReaderIdleTimeInMillis() {
+        return getIdleTimeInMillis(IdleStatus.READER_IDLE);
+    }
+
+    /**
+     * Sets idle time for {@link IdleStatus#READER_IDLE} in seconds.
+     */
+    public final void setReaderIdleTime(int idleTime) {
+        setIdleTime(IdleStatus.READER_IDLE, idleTime);
+    }
+
+    /**
+     * Returns idle time for {@link IdleStatus#WRITER_IDLE} in seconds.
+     */
+    public final int getWriterIdleTime() {
+        return getIdleTime(IdleStatus.WRITER_IDLE);
+    }
+
+    /**
+     * Returns idle time for {@link IdleStatus#WRITER_IDLE} in milliseconds.
+     */
+    public final long getWriterIdleTimeInMillis() {
+        return getIdleTimeInMillis(IdleStatus.WRITER_IDLE);
+    }
+
+    /**
+     * Sets idle time for {@link IdleStatus#WRITER_IDLE} in seconds.
+     */
+    public final void setWriterIdleTime(int idleTime) {
+        setIdleTime(IdleStatus.WRITER_IDLE, idleTime);
+    }
+
+    /**
+     * Returns idle time for {@link IdleStatus#BOTH_IDLE} in seconds.
+     */
+    public final int getBothIdleTime() {
+        return getIdleTime(IdleStatus.BOTH_IDLE);
+    }
+
+    /**
+     * Returns idle time for {@link IdleStatus#BOTH_IDLE} in milliseconds.
+     */
+    public final long getBothIdleTimeInMillis() {
+        return getIdleTimeInMillis(IdleStatus.BOTH_IDLE);
+    }
+
+    /**
+     * Sets idle time for {@link IdleStatus#WRITER_IDLE} in seconds.
+     */
+    public final void setBothIdleTime(int idleTime) {
+        setIdleTime(IdleStatus.BOTH_IDLE, idleTime);
+    }
+
+    /**
+     * TODO add documentation
+     */
+    private void increaseIdleCount(IdleStatus status, long currentTime) {
+        if (status == IdleStatus.BOTH_IDLE) {
+            idleCountForBoth++;
+            lastIdleTimeForBoth = currentTime;
+        } else if (status == IdleStatus.READER_IDLE) {
+            idleCountForRead++;
+            lastIdleTimeForRead = currentTime;
+        } else if (status == IdleStatus.WRITER_IDLE) {
+            idleCountForWrite++;
+            lastIdleTimeForWrite = currentTime;
+        } else {
+            throw new IllegalArgumentException("Unknown idle status: " + status);
+        }
+    }
+
+    /**
+     * TODO add documentation
+     */
+    public final void notifyIdleness(long currentTime) {
+        IoServiceStatistics stats = (IoServiceStatistics) service.getStatistics();
+        stats.updateThroughput(currentTime);
+
+        synchronized (idlenessCheckLock) {
+            notifyIdleness(currentTime,
+                    getIdleTimeInMillis(IdleStatus.BOTH_IDLE),
+                    IdleStatus.BOTH_IDLE, Math.max(stats.getLastIoTime(),
+                            getLastIdleTime(IdleStatus.BOTH_IDLE)));
+
+            notifyIdleness(currentTime,
+                    getIdleTimeInMillis(IdleStatus.READER_IDLE),
+                    IdleStatus.READER_IDLE, Math.max(stats.getLastReadTime(),
+                            getLastIdleTime(IdleStatus.READER_IDLE)));
+
+            notifyIdleness(currentTime,
+                    getIdleTimeInMillis(IdleStatus.WRITER_IDLE),
+                    IdleStatus.WRITER_IDLE, Math.max(stats.getLastWriteTime(),
+                            getLastIdleTime(IdleStatus.WRITER_IDLE)));
+        }
+    }
+
+    /**
+     * TODO add documentation
+     */
+    private void notifyIdleness(long currentTime, long idleTime,
+            IdleStatus status, long lastIoTime) {
+        if (idleTime > 0 && lastIoTime != 0
+                && currentTime - lastIoTime >= idleTime) {
+            increaseIdleCount(status, currentTime);
+            service.getListeners().fireServiceIdle(status);
+        }
+    }
+
+    /**
+     * TODO add documentation
+     */
+    protected void resetIdleCountForRead() {
+        idleCountForBoth = 0;
+        idleCountForRead = 0;
+    }
+
+    /**
+     * TODO add documentation
+     */
+    protected void resetIdleCountForWrite() {
+        idleCountForBoth = 0;
+        idleCountForWrite = 0;
+    }
+}
\ No newline at end of file

Propchange: mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceIdleState.java
------------------------------------------------------------------------------
    svn:mergeinfo = 

Added: mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java?rev=684597&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java Sun Aug 10 14:20:07 2008
@@ -0,0 +1,390 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.mina.core.service;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+
+/**
+ * Provides usage statistics for an {@link AbstractIoService} instance.
+ * 
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ * @since 2.0.0-M3
+ */
+public class IoServiceStatistics {
+    
+    private AbstractIoService service;
+    
+    private double readBytesThroughput;
+    private double writtenBytesThroughput;
+    private double readMessagesThroughput;
+    private double writtenMessagesThroughput;
+    private double largestReadBytesThroughput;
+    private double largestWrittenBytesThroughput;
+    private double largestReadMessagesThroughput;
+    private double largestWrittenMessagesThroughput;    
+    
+    private final AtomicLong readBytes = new AtomicLong();
+    private final AtomicLong writtenBytes = new AtomicLong();
+    private final AtomicLong readMessages = new AtomicLong();
+    private final AtomicLong writtenMessages = new AtomicLong();    
+    private long lastReadTime;
+    private long lastWriteTime;
+    
+    private long lastReadBytes;
+    private long lastWrittenBytes;
+    private long lastReadMessages;
+    private long lastWrittenMessages;
+    private long lastThroughputCalculationTime;
+
+    private final AtomicInteger scheduledWriteBytes = new AtomicInteger();
+    private final AtomicInteger scheduledWriteMessages = new AtomicInteger();
+    
+    private int throughputCalculationInterval = 3;
+    
+    private final Object throughputCalculationLock = new Object();
+    
+    public IoServiceStatistics(AbstractIoService service) {
+        this.service = service;
+    }
+    
+    /**
+     * Returns the maximum number of sessions which were being managed at the
+     * same time.
+     */
+    public final int getLargestManagedSessionCount() {
+        return service.getListeners().getLargestManagedSessionCount();
+    }
+
+    /**
+     * Returns the cumulative number of sessions which were managed (or are
+     * being managed) by this service, which means 'currently managed session
+     * count + closed session count'.
+     */
+    public final long getCumulativeManagedSessionCount() {
+        return service.getListeners().getCumulativeManagedSessionCount();
+    }
+    
+    /**
+     * Returns the time in millis when I/O occurred lastly.
+     */
+    public final long getLastIoTime() {
+        return Math.max(lastReadTime, lastWriteTime);
+    }
+
+    /**
+     * Returns the time in millis when read operation occurred lastly.
+     */
+    public final long getLastReadTime() {
+        return lastReadTime;
+    }
+
+    /**
+     * Returns the time in millis when write operation occurred lastly.
+     */
+    public final long getLastWriteTime() {
+        return lastWriteTime;
+    }
+    
+    /**
+     * Returns the number of bytes read by this service
+     *
+     * @return
+     *     The number of bytes this service has read
+     */
+    public final long getReadBytes() {
+        return readBytes.get();
+    }
+
+    /**
+     * Returns the number of bytes written out by this service
+     *
+     * @return
+     *     The number of bytes this service has written
+     */
+    public final long getWrittenBytes() {
+        return writtenBytes.get();
+    }
+
+    /**
+     * Returns the number of messages this services has read
+     *
+     * @return
+     *     The number of messages this services has read
+     */
+    public final long getReadMessages() {
+        return readMessages.get();
+    }
+
+    /**
+     * Returns the number of messages this service has written
+     *
+     * @return
+     *     The number of messages this service has written
+     */
+    public final long getWrittenMessages() {
+        return writtenMessages.get();
+    }
+
+    /**
+     * Returns the number of read bytes per second.
+     */
+    public final double getReadBytesThroughput() {
+        resetThroughput();
+        return readBytesThroughput;
+    }
+
+    /**
+     * Returns the number of written bytes per second.
+     */
+    public final double getWrittenBytesThroughput() {
+        resetThroughput();
+        return writtenBytesThroughput;
+    }
+
+    /**
+     * Returns the number of read messages per second.
+     */
+    public final double getReadMessagesThroughput() {
+        resetThroughput();
+        return readMessagesThroughput;
+    }
+
+    /**
+     * Returns the number of written messages per second.
+     */
+    public final double getWrittenMessagesThroughput() {
+        resetThroughput();
+        return writtenMessagesThroughput;
+    }
+
+    /**
+     * Returns the maximum of the {@link #getReadBytesThroughput() readBytesThroughput}.
+     */
+    public final double getLargestReadBytesThroughput() {
+        return largestReadBytesThroughput;
+    }
+
+    /**
+     * Returns the maximum of the {@link #getWrittenBytesThroughput() writtenBytesThroughput}.
+     */
+    public final double getLargestWrittenBytesThroughput() {
+        return largestWrittenBytesThroughput;
+    }
+
+    /**
+     * Returns the maximum of the {@link #getReadMessagesThroughput() readMessagesThroughput}.
+     */
+    public final double getLargestReadMessagesThroughput() {
+        return largestReadMessagesThroughput;
+    }
+
+    /**
+     * Returns the maximum of the {@link #getWrittenMessagesThroughput() writtenMessagesThroughput}.
+     */
+    public final double getLargestWrittenMessagesThroughput() {
+        return largestWrittenMessagesThroughput;
+    }
+
+    /**
+     * Returns the interval (seconds) between each throughput calculation.
+     * The default value is <tt>3</tt> seconds.
+     */
+    public final int getThroughputCalculationInterval() {
+        return throughputCalculationInterval;
+    }
+
+    /**
+     * Returns the interval (milliseconds) between each throughput calculation.
+     * The default value is <tt>3</tt> seconds.
+     */
+    public final long getThroughputCalculationIntervalInMillis() {
+        return throughputCalculationInterval * 1000L;
+    }
+
+    /**
+     * Sets the interval (seconds) between each throughput calculation.  The
+     * default value is <tt>3</tt> seconds.
+     */
+    public final void setThroughputCalculationInterval(
+            int throughputCalculationInterval) {
+        if (throughputCalculationInterval < 0) {
+            throw new IllegalArgumentException(
+                    "throughputCalculationInterval: "
+                            + throughputCalculationInterval);
+        }
+
+        this.throughputCalculationInterval = throughputCalculationInterval;
+    }
+
+    /**
+     * TODO add documentation
+     */
+    protected final void setLastReadTime(long lastReadTime) {
+        this.lastReadTime = lastReadTime;
+    }
+
+    /**
+     * TODO add documentation
+     */     
+    protected final void setLastWriteTime(long lastWriteTime) {
+        this.lastWriteTime = lastWriteTime;
+    }
+    
+    /**
+     * TODO add documentation
+     */
+    private void resetThroughput() {
+        if (service.getManagedSessionCount() == 0) {
+            readBytesThroughput = 0;
+            writtenBytesThroughput = 0;
+            readMessagesThroughput = 0;
+            writtenMessagesThroughput = 0;
+        }
+    }
+
+    /**
+     * TODO add documentation
+     */    
+    public void updateThroughput(long currentTime) {
+        synchronized (throughputCalculationLock) {
+            int interval = (int) (currentTime - lastThroughputCalculationTime);
+            long minInterval = getThroughputCalculationIntervalInMillis();
+            if (minInterval == 0 || interval < minInterval) {
+                return;
+            }
+
+            long readBytes = this.readBytes.get();
+            long writtenBytes = this.writtenBytes.get();
+            long readMessages = this.readMessages.get();
+            long writtenMessages = this.writtenMessages.get();
+
+            readBytesThroughput = (readBytes - lastReadBytes) * 1000.0
+                    / interval;
+            writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0
+                    / interval;
+            readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0
+                    / interval;
+            writtenMessagesThroughput = (writtenMessages - lastWrittenMessages)
+                    * 1000.0 / interval;
+
+            if (readBytesThroughput > largestReadBytesThroughput) {
+                largestReadBytesThroughput = readBytesThroughput;
+            }
+            if (writtenBytesThroughput > largestWrittenBytesThroughput) {
+                largestWrittenBytesThroughput = writtenBytesThroughput;
+            }
+            if (readMessagesThroughput > largestReadMessagesThroughput) {
+                largestReadMessagesThroughput = readMessagesThroughput;
+            }
+            if (writtenMessagesThroughput > largestWrittenMessagesThroughput) {
+                largestWrittenMessagesThroughput = writtenMessagesThroughput;
+            }
+
+            lastReadBytes = readBytes;
+            lastWrittenBytes = writtenBytes;
+            lastReadMessages = readMessages;
+            lastWrittenMessages = writtenMessages;
+
+            lastThroughputCalculationTime = currentTime;
+        }
+    }
+    
+    /**
+     * TODO add documentation
+     */ 
+    public final void increaseReadBytes(long increment, long currentTime) {
+        readBytes.addAndGet(increment);
+        lastReadTime = currentTime;
+        service.getIdleState().resetIdleCountForRead();
+    }
+
+    /**
+     * TODO add documentation
+     */     
+    public final void increaseReadMessages(long currentTime) {
+        readMessages.incrementAndGet();
+        lastReadTime = currentTime;
+        service.getIdleState().resetIdleCountForRead();
+    }
+    
+    /**
+     * TODO add documentation
+     */
+    public final void increaseWrittenBytes(int increment, long currentTime) {
+        writtenBytes.addAndGet(increment);
+        lastWriteTime = currentTime;
+        service.getIdleState().resetIdleCountForWrite();
+    }
+
+    /**
+     * TODO add documentation
+     */    
+    public final void increaseWrittenMessages(long currentTime) {
+        writtenMessages.incrementAndGet();
+        lastWriteTime = currentTime;
+        service.getIdleState().resetIdleCountForWrite();
+    }
+    
+    /**
+     * TODO add documentation
+     */
+    public final int getScheduledWriteBytes() {
+        return scheduledWriteBytes.get();
+    }
+
+    /**
+     * TODO add documentation
+     */    
+    public final void increaseScheduledWriteBytes(int increment) {
+        scheduledWriteBytes.addAndGet(increment);
+    }
+
+    /**
+     * TODO add documentation
+     */
+    public final int getScheduledWriteMessages() {
+        return scheduledWriteMessages.get();
+    }
+
+    /**
+     * TODO add documentation
+     */    
+    public final void increaseScheduledWriteMessages() {
+        scheduledWriteMessages.incrementAndGet();
+    }
+
+    /**
+     * TODO add documentation
+     */    
+    public final void decreaseScheduledWriteMessages() {
+        scheduledWriteMessages.decrementAndGet();
+    }
+
+    /**
+     * TODO add documentation
+     */        
+    protected void setLastThroughputCalculationTime(
+            long lastThroughputCalculationTime) {
+        this.lastThroughputCalculationTime = lastThroughputCalculationTime;
+    }    
+}

Propchange: mina/trunk/core/src/main/java/org/apache/mina/core/service/IoServiceStatistics.java
------------------------------------------------------------------------------
    svn:mergeinfo = 

Modified: mina/trunk/core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java?rev=684597&r1=684596&r2=684597&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java Sun Aug 10 14:20:07 2008
@@ -717,7 +717,7 @@
         idleCountForRead = 0;
 
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).increaseReadBytes(increment, currentTime);
+            ((AbstractIoService) getService()).getStatistics().increaseReadBytes(increment, currentTime);
         }
     }
 
@@ -731,7 +731,7 @@
         idleCountForRead = 0;
 
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).increaseReadMessages(currentTime);
+            ((AbstractIoService) getService()).getStatistics().increaseReadMessages(currentTime);
         }
     }
 
@@ -749,7 +749,7 @@
         idleCountForWrite = 0;
 
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).increaseWrittenBytes(increment, currentTime);
+            ((AbstractIoService) getService()).getStatistics().increaseWrittenBytes(increment, currentTime);
         }
 
         increaseScheduledWriteBytes(-increment);
@@ -771,7 +771,7 @@
         writtenMessages++;
         lastWriteTime = currentTime;
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).increaseWrittenMessages(currentTime);
+            ((AbstractIoService) getService()).getStatistics().increaseWrittenMessages(currentTime);
         }
 
         decreaseScheduledWriteMessages();
@@ -783,7 +783,7 @@
     public final void increaseScheduledWriteBytes(int increment) {
         scheduledWriteBytes.addAndGet(increment);
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).increaseScheduledWriteBytes(increment);
+            ((AbstractIoService) getService()).getStatistics().increaseScheduledWriteBytes(increment);
         }
     }
 
@@ -793,7 +793,7 @@
     public final void increaseScheduledWriteMessages() {
         scheduledWriteMessages.incrementAndGet();
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).increaseScheduledWriteMessages();
+            ((AbstractIoService) getService()).getStatistics().increaseScheduledWriteMessages();
         }
     }
 
@@ -803,7 +803,7 @@
     private void decreaseScheduledWriteMessages() {
         scheduledWriteMessages.decrementAndGet();
         if (getService() instanceof AbstractIoService) {
-            ((AbstractIoService) getService()).decreaseScheduledWriteMessages();
+            ((AbstractIoService) getService()).getStatistics().decreaseScheduledWriteMessages();
         }
     }