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 The Apache MINA Project (dev@mina.apache.org)
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      * TODO add documentation
240      */
241     protected final void setLastReadTime(long lastReadTime) {
242         this.lastReadTime = lastReadTime;
243     }
244 
245     /**
246      * TODO add documentation
247      */     
248     protected final void setLastWriteTime(long lastWriteTime) {
249         this.lastWriteTime = lastWriteTime;
250     }
251     
252     /**
253      * TODO add documentation
254      */
255     private void resetThroughput() {
256         if (service.getManagedSessionCount() == 0) {
257             readBytesThroughput = 0;
258             writtenBytesThroughput = 0;
259             readMessagesThroughput = 0;
260             writtenMessagesThroughput = 0;
261         }
262     }
263 
264     /**
265      * TODO add documentation
266      */    
267     public void updateThroughput(long currentTime) {
268         synchronized (throughputCalculationLock) {
269             int interval = (int) (currentTime - lastThroughputCalculationTime);
270             long minInterval = getThroughputCalculationIntervalInMillis();
271             if (minInterval == 0 || interval < minInterval) {
272                 return;
273             }
274 
275             long readBytes = this.readBytes.get();
276             long writtenBytes = this.writtenBytes.get();
277             long readMessages = this.readMessages.get();
278             long writtenMessages = this.writtenMessages.get();
279 
280             readBytesThroughput = (readBytes - lastReadBytes) * 1000.0
281                     / interval;
282             writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0
283                     / interval;
284             readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0
285                     / interval;
286             writtenMessagesThroughput = (writtenMessages - lastWrittenMessages)
287                     * 1000.0 / interval;
288 
289             if (readBytesThroughput > largestReadBytesThroughput) {
290                 largestReadBytesThroughput = readBytesThroughput;
291             }
292             if (writtenBytesThroughput > largestWrittenBytesThroughput) {
293                 largestWrittenBytesThroughput = writtenBytesThroughput;
294             }
295             if (readMessagesThroughput > largestReadMessagesThroughput) {
296                 largestReadMessagesThroughput = readMessagesThroughput;
297             }
298             if (writtenMessagesThroughput > largestWrittenMessagesThroughput) {
299                 largestWrittenMessagesThroughput = writtenMessagesThroughput;
300             }
301 
302             lastReadBytes = readBytes;
303             lastWrittenBytes = writtenBytes;
304             lastReadMessages = readMessages;
305             lastWrittenMessages = writtenMessages;
306 
307             lastThroughputCalculationTime = currentTime;
308         }
309     }
310     
311     /**
312      * TODO add documentation
313      */ 
314     public final void increaseReadBytes(long increment, long currentTime) {
315         readBytes.addAndGet(increment);
316         lastReadTime = currentTime;
317     }
318 
319     /**
320      * TODO add documentation
321      */     
322     public final void increaseReadMessages(long currentTime) {
323         readMessages.incrementAndGet();
324         lastReadTime = currentTime;
325     }
326     
327     /**
328      * TODO add documentation
329      */
330     public final void increaseWrittenBytes(int increment, long currentTime) {
331         writtenBytes.addAndGet(increment);
332         lastWriteTime = currentTime;
333     }
334 
335     /**
336      * TODO add documentation
337      */    
338     public final void increaseWrittenMessages(long currentTime) {
339         writtenMessages.incrementAndGet();
340         lastWriteTime = currentTime;
341     }
342     
343     /**
344      * TODO add documentation
345      */
346     public final int getScheduledWriteBytes() {
347         return scheduledWriteBytes.get();
348     }
349 
350     /**
351      * TODO add documentation
352      */    
353     public final void increaseScheduledWriteBytes(int increment) {
354         scheduledWriteBytes.addAndGet(increment);
355     }
356 
357     /**
358      * TODO add documentation
359      */
360     public final int getScheduledWriteMessages() {
361         return scheduledWriteMessages.get();
362     }
363 
364     /**
365      * TODO add documentation
366      */    
367     public final void increaseScheduledWriteMessages() {
368         scheduledWriteMessages.incrementAndGet();
369     }
370 
371     /**
372      * TODO add documentation
373      */    
374     public final void decreaseScheduledWriteMessages() {
375         scheduledWriteMessages.decrementAndGet();
376     }
377 
378     /**
379      * TODO add documentation
380      */        
381     protected void setLastThroughputCalculationTime(
382             long lastThroughputCalculationTime) {
383         this.lastThroughputCalculationTime = lastThroughputCalculationTime;
384     }    
385 }