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