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