View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.core.service;
    21
    22  import java.util.concurrent.atomic.AtomicInteger;
    23  import java.util.concurrent.atomic.AtomicLong;
    24
    25  /**
    26   * Provides usage statistics for an {@link AbstractIoService} instance.
    27   *
    28   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    29   * @since 2.0.0-M3
    30   */
    31  public class IoServiceStatistics {
    32
    33      private AbstractIoService service;
    34
    35      private double readBytesThroughput;
    36
    37      private double writtenBytesThroughput;
    38
    39      private double readMessagesThroughput;
    40
    41      private double writtenMessagesThroughput;
    42
    43      private double largestReadBytesThroughput;
    44
    45      private double largestWrittenBytesThroughput;
    46
    47      private double largestReadMessagesThroughput;
    48
    49      private double largestWrittenMessagesThroughput;
    50
    51      private final AtomicLong readBytes = new AtomicLong();
    52
    53      private final AtomicLong writtenBytes = new AtomicLong();
    54
    55      private final AtomicLong readMessages = new AtomicLong();
    56
    57      private final AtomicLong writtenMessages = new AtomicLong();
    58
    59      private long lastReadTime;
    60
    61      private long lastWriteTime;
    62
    63      private long lastReadBytes;
    64
    65      private long lastWrittenBytes;
    66
    67      private long lastReadMessages;
    68
    69      private long lastWrittenMessages;
    70
    71      private long lastThroughputCalculationTime;
    72
    73      private final AtomicInteger scheduledWriteBytes = new AtomicInteger();
    74
    75      private final AtomicInteger scheduledWriteMessages = new AtomicInteger();
    76
    77      private int throughputCalculationInterval = 3;
    78
    79      private final Object throughputCalculationLock = new Object();
    80
    81      public IoServiceStatistics(AbstractIoService service) {
    82          this.service = service;
    83      }
    84
    85      /**
    86       * Returns the maximum number of sessions which were being managed at the
    87       * same time.
    88       */
    89      public final int getLargestManagedSessionCount() {
    90          return service.getListeners().getLargestManagedSessionCount();
    91      }
    92
    93      /**
    94       * Returns the cumulative number of sessions which were managed (or are
    95       * being managed) by this service, which means 'currently managed session
    96       * count + closed session count'.
    97       */
    98      public final long getCumulativeManagedSessionCount() {
    99          return service.getListeners().getCumulativeManagedSessionCount();
    100     }
    101
    102     /**
    103      * Returns the time in millis when I/O occurred lastly.
    104      */
    105     public final long getLastIoTime() {
    106         return Math.max(lastReadTime, lastWriteTime);
    107     }
    108
    109     /**
    110      * Returns the time in millis when read operation occurred lastly.
    111      */
    112     public final long getLastReadTime() {
    113         return lastReadTime;
    114     }
    115
    116     /**
    117      * Returns the time in millis when write operation occurred lastly.
    118      */
    119     public final long getLastWriteTime() {
    120         return lastWriteTime;
    121     }
    122
    123     /**
    124      * Returns the number of bytes read by this service
    125      *
    126      * @return
    127      *     The number of bytes this service has read
    128      */
    129     public final long getReadBytes() {
    130         return readBytes.get();
    131     }
    132
    133     /**
    134      * Returns the number of bytes written out by this service
    135      *
    136      * @return
    137      *     The number of bytes this service has written
    138      */
    139     public final long getWrittenBytes() {
    140         return writtenBytes.get();
    141     }
    142
    143     /**
    144      * Returns the number of messages this services has read
    145      *
    146      * @return
    147      *     The number of messages this services has read
    148      */
    149     public final long getReadMessages() {
    150         return readMessages.get();
    151     }
    152
    153     /**
    154      * Returns the number of messages this service has written
    155      *
    156      * @return
    157      *     The number of messages this service has written
    158      */
    159     public final long getWrittenMessages() {
    160         return writtenMessages.get();
    161     }
    162
    163     /**
    164      * Returns the number of read bytes per second.
    165      */
    166     public final double getReadBytesThroughput() {
    167         resetThroughput();
    168         return readBytesThroughput;
    169     }
    170
    171     /**
    172      * Returns the number of written bytes per second.
    173      */
    174     public final double getWrittenBytesThroughput() {
    175         resetThroughput();
    176         return writtenBytesThroughput;
    177     }
    178
    179     /**
    180      * Returns the number of read messages per second.
    181      */
    182     public final double getReadMessagesThroughput() {
    183         resetThroughput();
    184         return readMessagesThroughput;
    185     }
    186
    187     /**
    188      * Returns the number of written messages per second.
    189      */
    190     public final double getWrittenMessagesThroughput() {
    191         resetThroughput();
    192         return writtenMessagesThroughput;
    193     }
    194
    195     /**
    196      * Returns the maximum of the {@link #getReadBytesThroughput() readBytesThroughput}.
    197      */
    198     public final double getLargestReadBytesThroughput() {
    199         return largestReadBytesThroughput;
    200     }
    201
    202     /**
    203      * Returns the maximum of the {@link #getWrittenBytesThroughput() writtenBytesThroughput}.
    204      */
    205     public final double getLargestWrittenBytesThroughput() {
    206         return largestWrittenBytesThroughput;
    207     }
    208
    209     /**
    210      * Returns the maximum of the {@link #getReadMessagesThroughput() readMessagesThroughput}.
    211      */
    212     public final double getLargestReadMessagesThroughput() {
    213         return largestReadMessagesThroughput;
    214     }
    215
    216     /**
    217      * Returns the maximum of the {@link #getWrittenMessagesThroughput() writtenMessagesThroughput}.
    218      */
    219     public final double getLargestWrittenMessagesThroughput() {
    220         return largestWrittenMessagesThroughput;
    221     }
    222
    223     /**
    224      * Returns the interval (seconds) between each throughput calculation.
    225      * The default value is <tt>3</tt> seconds.
    226      */
    227     public final int getThroughputCalculationInterval() {
    228         return throughputCalculationInterval;
    229     }
    230
    231     /**
    232      * Returns the interval (milliseconds) between each throughput calculation.
    233      * The default value is <tt>3</tt> seconds.
    234      */
    235     public final long getThroughputCalculationIntervalInMillis() {
    236         return throughputCalculationInterval * 1000L;
    237     }
    238
    239     /**
    240      * Sets the interval (seconds) between each throughput calculation.  The
    241      * default value is <tt>3</tt> seconds.
    242      */
    243     public final void setThroughputCalculationInterval(int throughputCalculationInterval) {
    244         if (throughputCalculationInterval < 0) {
    245             throw new IllegalArgumentException("throughputCalculationInterval: " + throughputCalculationInterval);
    246         }
    247
    248         this.throughputCalculationInterval = throughputCalculationInterval;
    249     }
    250
    251     /**
    252      * Sets last time at which a read occurred on the service.
    253      */
    254     protected final void setLastReadTime(long lastReadTime) {
    255         this.lastReadTime = lastReadTime;
    256     }
    257
    258     /**
    259      * Sets last time at which a write occurred on the service.
    260      */
    261     protected final void setLastWriteTime(long lastWriteTime) {
    262         this.lastWriteTime = lastWriteTime;
    263     }
    264
    265     /**
    266      * Resets the throughput counters of the service if none session
    267      * is currently managed.
    268      */
    269     private void resetThroughput() {
    270         if (service.getManagedSessionCount() == 0) {
    271             readBytesThroughput = 0;
    272             writtenBytesThroughput = 0;
    273             readMessagesThroughput = 0;
    274             writtenMessagesThroughput = 0;
    275         }
    276     }
    277
    278     /**
    279      * Updates the throughput counters.
    280      */
    281     public void updateThroughput(long currentTime) {
    282         synchronized (throughputCalculationLock) {
    283             int interval = (int) (currentTime - lastThroughputCalculationTime);
    284             long minInterval = getThroughputCalculationIntervalInMillis();
    285             if (minInterval == 0 || interval < minInterval) {
    286                 return;
    287             }
    288
    289             long readBytes = this.readBytes.get();
    290             long writtenBytes = this.writtenBytes.get();
    291             long readMessages = this.readMessages.get();
    292             long writtenMessages = this.writtenMessages.get();
    293
    294             readBytesThroughput = (readBytes - lastReadBytes) * 1000.0 / interval;
    295             writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0 / interval;
    296             readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0 / interval;
    297             writtenMessagesThroughput = (writtenMessages - lastWrittenMessages) * 1000.0 / interval;
    298
    299             if (readBytesThroughput > largestReadBytesThroughput) {
    300                 largestReadBytesThroughput = readBytesThroughput;
    301             }
    302             if (writtenBytesThroughput > largestWrittenBytesThroughput) {
    303                 largestWrittenBytesThroughput = writtenBytesThroughput;
    304             }
    305             if (readMessagesThroughput > largestReadMessagesThroughput) {
    306                 largestReadMessagesThroughput = readMessagesThroughput;
    307             }
    308             if (writtenMessagesThroughput > largestWrittenMessagesThroughput) {
    309                 largestWrittenMessagesThroughput = writtenMessagesThroughput;
    310             }
    311
    312             lastReadBytes = readBytes;
    313             lastWrittenBytes = writtenBytes;
    314             lastReadMessages = readMessages;
    315             lastWrittenMessages = writtenMessages;
    316
    317             lastThroughputCalculationTime = currentTime;
    318         }
    319     }
    320
    321     /**
    322      * Increases the count of read bytes by <code>increment</code> and sets
    323      * the last read time to <code>currentTime</code>.
    324      */
    325     public final void increaseReadBytes(long increment, long currentTime) {
    326         readBytes.addAndGet(increment);
    327         lastReadTime = currentTime;
    328     }
    329
    330     /**
    331      * Increases the count of read messages by 1 and sets the last read time to
    332      * <code>currentTime</code>.
    333      */
    334     public final void increaseReadMessages(long currentTime) {
    335         readMessages.incrementAndGet();
    336         lastReadTime = currentTime;
    337     }
    338
    339     /**
    340      * Increases the count of written bytes by <code>increment</code> and sets
    341      * the last write time to <code>currentTime</code>.
    342      */
    343     public final void increaseWrittenBytes(int increment, long currentTime) {
    344         writtenBytes.addAndGet(increment);
    345         lastWriteTime = currentTime;
    346     }
    347
    348     /**
    349      * Increases the count of written messages by 1 and sets the last write time to
    350      * <code>currentTime</code>.
    351      */
    352     public final void increaseWrittenMessages(long currentTime) {
    353         writtenMessages.incrementAndGet();
    354         lastWriteTime = currentTime;
    355     }
    356
    357     /**
    358      * Returns the count of bytes scheduled for write.
    359      */
    360     public final int getScheduledWriteBytes() {
    361         return scheduledWriteBytes.get();
    362     }
    363
    364     /**
    365      * Increments by <code>increment</code> the count of bytes scheduled for write.
    366      */
    367     public final void increaseScheduledWriteBytes(int increment) {
    368         scheduledWriteBytes.addAndGet(increment);
    369     }
    370
    371     /**
    372      * Returns the count of messages scheduled for write.
    373      */
    374     public final int getScheduledWriteMessages() {
    375         return scheduledWriteMessages.get();
    376     }
    377
    378     /**
    379      * Increments by 1 the count of messages scheduled for write.
    380      */
    381     public final void increaseScheduledWriteMessages() {
    382         scheduledWriteMessages.incrementAndGet();
    383     }
    384
    385     /**
    386      * Decrements by 1 the count of messages scheduled for write.
    387      */
    388     public final void decreaseScheduledWriteMessages() {
    389         scheduledWriteMessages.decrementAndGet();
    390     }
    391
    392     /**
    393      * Sets the time at which throughtput counters where updated.
    394      */
    395     protected void setLastThroughputCalculationTime(long lastThroughputCalculationTime) {
    396         this.lastThroughputCalculationTime = lastThroughputCalculationTime;
    397     }
    398 }