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 }