001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.core.service; 021 022import java.util.concurrent.atomic.AtomicInteger; 023import java.util.concurrent.locks.Lock; 024import java.util.concurrent.locks.ReentrantLock; 025 026/** 027 * Provides usage statistics for an {@link AbstractIoService} instance. 028 * 029 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 030 * @since 2.0.0-M3 031 */ 032public class IoServiceStatistics { 033 034 private AbstractIoService service; 035 036 /** The number of bytes read per second */ 037 private double readBytesThroughput; 038 039 /** The number of bytes written per second */ 040 private double writtenBytesThroughput; 041 042 /** The number of messages read per second */ 043 private double readMessagesThroughput; 044 045 /** The number of messages written per second */ 046 private double writtenMessagesThroughput; 047 048 /** The biggest number of bytes read per second */ 049 private double largestReadBytesThroughput; 050 051 /** The biggest number of bytes written per second */ 052 private double largestWrittenBytesThroughput; 053 054 /** The biggest number of messages read per second */ 055 private double largestReadMessagesThroughput; 056 057 /** The biggest number of messages written per second */ 058 private double largestWrittenMessagesThroughput; 059 060 /** The number of read bytes since the service has been started */ 061 private long readBytes; 062 063 /** The number of written bytes since the service has been started */ 064 private long writtenBytes; 065 066 /** The number of read messages since the service has been started */ 067 private long readMessages; 068 069 /** The number of written messages since the service has been started */ 070 private long writtenMessages; 071 072 /** The time the last read operation occurred */ 073 private long lastReadTime; 074 075 /** The time the last write operation occurred */ 076 private long lastWriteTime; 077 078 private long lastReadBytes; 079 080 private long lastWrittenBytes; 081 082 private long lastReadMessages; 083 084 private long lastWrittenMessages; 085 086 private long lastThroughputCalculationTime; 087 088 private int scheduledWriteBytes; 089 090 private int scheduledWriteMessages; 091 092 /** The time (in second) between the computation of the service's statistics */ 093 private final AtomicInteger throughputCalculationInterval = new AtomicInteger(3); 094 095 private final Lock throughputCalculationLock = new ReentrantLock(); 096 097 public IoServiceStatistics(AbstractIoService service) { 098 this.service = service; 099 } 100 101 /** 102 * @return The maximum number of sessions which were being managed at the 103 * same time. 104 */ 105 public final int getLargestManagedSessionCount() { 106 return service.getListeners().getLargestManagedSessionCount(); 107 } 108 109 /** 110 * @return The cumulative number of sessions which were managed (or are 111 * being managed) by this service, which means 'currently managed 112 * session count + closed session count'. 113 */ 114 public final long getCumulativeManagedSessionCount() { 115 return service.getListeners().getCumulativeManagedSessionCount(); 116 } 117 118 /** 119 * @return the time in millis when the last I/O operation (read or write) 120 * occurred. 121 */ 122 public final long getLastIoTime() { 123 throughputCalculationLock.lock(); 124 125 try { 126 return Math.max(lastReadTime, lastWriteTime); 127 } finally { 128 throughputCalculationLock.unlock(); 129 } 130 } 131 132 /** 133 * @return The time in millis when the last read operation occurred. 134 */ 135 public final long getLastReadTime() { 136 throughputCalculationLock.lock(); 137 138 try { 139 return lastReadTime; 140 } finally { 141 throughputCalculationLock.unlock(); 142 } 143 } 144 145 /** 146 * @return The time in millis when the last write operation occurred. 147 */ 148 public final long getLastWriteTime() { 149 throughputCalculationLock.lock(); 150 151 try { 152 return lastWriteTime; 153 } finally { 154 throughputCalculationLock.unlock(); 155 } 156 } 157 158 /** 159 * @return The number of bytes this service has read so far 160 */ 161 public final long getReadBytes() { 162 throughputCalculationLock.lock(); 163 164 try { 165 return readBytes; 166 } finally { 167 throughputCalculationLock.unlock(); 168 } 169 } 170 171 /** 172 * @return The number of bytes this service has written so far 173 */ 174 public final long getWrittenBytes() { 175 throughputCalculationLock.lock(); 176 177 try { 178 return writtenBytes; 179 } finally { 180 throughputCalculationLock.unlock(); 181 } 182 } 183 184 /** 185 * @return The number of messages this services has read so far 186 */ 187 public final long getReadMessages() { 188 throughputCalculationLock.lock(); 189 190 try { 191 return readMessages; 192 } finally { 193 throughputCalculationLock.unlock(); 194 } 195 } 196 197 /** 198 * @return The number of messages this service has written so far 199 */ 200 public final long getWrittenMessages() { 201 throughputCalculationLock.lock(); 202 203 try { 204 return writtenMessages; 205 } finally { 206 throughputCalculationLock.unlock(); 207 } 208 } 209 210 /** 211 * @return The number of read bytes per second. 212 */ 213 public final double getReadBytesThroughput() { 214 throughputCalculationLock.lock(); 215 216 try { 217 resetThroughput(); 218 return readBytesThroughput; 219 } finally { 220 throughputCalculationLock.unlock(); 221 } 222 } 223 224 /** 225 * @return The number of written bytes per second. 226 */ 227 public final double getWrittenBytesThroughput() { 228 throughputCalculationLock.lock(); 229 230 try { 231 resetThroughput(); 232 return writtenBytesThroughput; 233 } finally { 234 throughputCalculationLock.unlock(); 235 } 236 } 237 238 /** 239 * @return The number of read messages per second. 240 */ 241 public final double getReadMessagesThroughput() { 242 throughputCalculationLock.lock(); 243 244 try { 245 resetThroughput(); 246 return readMessagesThroughput; 247 } finally { 248 throughputCalculationLock.unlock(); 249 } 250 } 251 252 /** 253 * @return The number of written messages per second. 254 */ 255 public final double getWrittenMessagesThroughput() { 256 throughputCalculationLock.lock(); 257 258 try { 259 resetThroughput(); 260 return writtenMessagesThroughput; 261 } finally { 262 throughputCalculationLock.unlock(); 263 } 264 } 265 266 /** 267 * @return The maximum number of bytes read per second since the service has 268 * been started. 269 */ 270 public final double getLargestReadBytesThroughput() { 271 throughputCalculationLock.lock(); 272 273 try { 274 return largestReadBytesThroughput; 275 } finally { 276 throughputCalculationLock.unlock(); 277 } 278 } 279 280 /** 281 * @return The maximum number of bytes written per second since the service 282 * has been started. 283 */ 284 public final double getLargestWrittenBytesThroughput() { 285 throughputCalculationLock.lock(); 286 287 try { 288 return largestWrittenBytesThroughput; 289 } finally { 290 throughputCalculationLock.unlock(); 291 } 292 } 293 294 /** 295 * @return The maximum number of messages read per second since the service 296 * has been started. 297 */ 298 public final double getLargestReadMessagesThroughput() { 299 throughputCalculationLock.lock(); 300 301 try { 302 return largestReadMessagesThroughput; 303 } finally { 304 throughputCalculationLock.unlock(); 305 } 306 } 307 308 /** 309 * @return The maximum number of messages written per second since the 310 * service has been started. 311 */ 312 public final double getLargestWrittenMessagesThroughput() { 313 throughputCalculationLock.lock(); 314 315 try { 316 return largestWrittenMessagesThroughput; 317 } finally { 318 throughputCalculationLock.unlock(); 319 } 320 } 321 322 /** 323 * @return the interval (seconds) between each throughput calculation. The 324 * default value is <tt>3</tt> seconds. 325 */ 326 public final int getThroughputCalculationInterval() { 327 return throughputCalculationInterval.get(); 328 } 329 330 /** 331 * @return the interval (milliseconds) between each throughput calculation. 332 * The default value is <tt>3</tt> seconds. 333 */ 334 public final long getThroughputCalculationIntervalInMillis() { 335 return throughputCalculationInterval.get() * 1000L; 336 } 337 338 /** 339 * Sets the interval (seconds) between each throughput calculation. The 340 * default value is <tt>3</tt> seconds. 341 * 342 * @param throughputCalculationInterval The interval between two calculation 343 */ 344 public final void setThroughputCalculationInterval(int throughputCalculationInterval) { 345 if (throughputCalculationInterval < 0) { 346 throw new IllegalArgumentException("throughputCalculationInterval: " + throughputCalculationInterval); 347 } 348 349 this.throughputCalculationInterval.set(throughputCalculationInterval); 350 } 351 352 /** 353 * Sets last time at which a read occurred on the service. 354 * 355 * @param lastReadTime 356 * The last time a read has occurred 357 */ 358 protected final void setLastReadTime(long lastReadTime) { 359 throughputCalculationLock.lock(); 360 361 try { 362 this.lastReadTime = lastReadTime; 363 } finally { 364 throughputCalculationLock.unlock(); 365 } 366 } 367 368 /** 369 * Sets last time at which a write occurred on the service. 370 * 371 * @param lastWriteTime 372 * The last time a write has occurred 373 */ 374 protected final void setLastWriteTime(long lastWriteTime) { 375 throughputCalculationLock.lock(); 376 377 try { 378 this.lastWriteTime = lastWriteTime; 379 } finally { 380 throughputCalculationLock.unlock(); 381 } 382 } 383 384 /** 385 * Resets the throughput counters of the service if no session is currently 386 * managed. 387 */ 388 private void resetThroughput() { 389 if (service.getManagedSessionCount() == 0) { 390 readBytesThroughput = 0; 391 writtenBytesThroughput = 0; 392 readMessagesThroughput = 0; 393 writtenMessagesThroughput = 0; 394 } 395 } 396 397 /** 398 * Updates the throughput counters. 399 * 400 * @param currentTime The current time 401 */ 402 public void updateThroughput(long currentTime) { 403 throughputCalculationLock.lock(); 404 405 try { 406 int interval = (int) (currentTime - lastThroughputCalculationTime); 407 long minInterval = getThroughputCalculationIntervalInMillis(); 408 409 if ((minInterval == 0) || (interval < minInterval)) { 410 return; 411 } 412 413 long readBytes = this.readBytes; 414 long writtenBytes = this.writtenBytes; 415 long readMessages = this.readMessages; 416 long writtenMessages = this.writtenMessages; 417 418 readBytesThroughput = (readBytes - lastReadBytes) * 1000.0 / interval; 419 writtenBytesThroughput = (writtenBytes - lastWrittenBytes) * 1000.0 / interval; 420 readMessagesThroughput = (readMessages - lastReadMessages) * 1000.0 / interval; 421 writtenMessagesThroughput = (writtenMessages - lastWrittenMessages) * 1000.0 / interval; 422 423 if (readBytesThroughput > largestReadBytesThroughput) { 424 largestReadBytesThroughput = readBytesThroughput; 425 } 426 427 if (writtenBytesThroughput > largestWrittenBytesThroughput) { 428 largestWrittenBytesThroughput = writtenBytesThroughput; 429 } 430 431 if (readMessagesThroughput > largestReadMessagesThroughput) { 432 largestReadMessagesThroughput = readMessagesThroughput; 433 } 434 435 if (writtenMessagesThroughput > largestWrittenMessagesThroughput) { 436 largestWrittenMessagesThroughput = writtenMessagesThroughput; 437 } 438 439 lastReadBytes = readBytes; 440 lastWrittenBytes = writtenBytes; 441 lastReadMessages = readMessages; 442 lastWrittenMessages = writtenMessages; 443 444 lastThroughputCalculationTime = currentTime; 445 } finally { 446 throughputCalculationLock.unlock(); 447 } 448 } 449 450 /** 451 * Increases the count of read bytes by <code>nbBytesRead</code> and sets 452 * the last read time to <code>currentTime</code>. 453 * 454 * @param nbBytesRead 455 * The number of bytes read 456 * @param currentTime 457 * The date those bytes were read 458 */ 459 public final void increaseReadBytes(long nbBytesRead, long currentTime) { 460 throughputCalculationLock.lock(); 461 462 try { 463 readBytes += nbBytesRead; 464 lastReadTime = currentTime; 465 } finally { 466 throughputCalculationLock.unlock(); 467 } 468 } 469 470 /** 471 * Increases the count of read messages by 1 and sets the last read time to 472 * <code>currentTime</code>. 473 * 474 * @param currentTime 475 * The time the message has been read 476 */ 477 public final void increaseReadMessages(long currentTime) { 478 throughputCalculationLock.lock(); 479 480 try { 481 readMessages++; 482 lastReadTime = currentTime; 483 } finally { 484 throughputCalculationLock.unlock(); 485 } 486 } 487 488 /** 489 * Increases the count of written bytes by <code>nbBytesWritten</code> and 490 * sets the last write time to <code>currentTime</code>. 491 * 492 * @param nbBytesWritten 493 * The number of bytes written 494 * @param currentTime 495 * The date those bytes were written 496 */ 497 public final void increaseWrittenBytes(int nbBytesWritten, long currentTime) { 498 throughputCalculationLock.lock(); 499 500 try { 501 writtenBytes += nbBytesWritten; 502 lastWriteTime = currentTime; 503 } finally { 504 throughputCalculationLock.unlock(); 505 } 506 } 507 508 /** 509 * Increases the count of written messages by 1 and sets the last write time 510 * to <code>currentTime</code>. 511 * 512 * @param currentTime 513 * The date the message were written 514 */ 515 public final void increaseWrittenMessages(long currentTime) { 516 throughputCalculationLock.lock(); 517 518 try { 519 writtenMessages++; 520 lastWriteTime = currentTime; 521 } finally { 522 throughputCalculationLock.unlock(); 523 } 524 } 525 526 /** 527 * @return The count of bytes scheduled for write. 528 */ 529 public final int getScheduledWriteBytes() { 530 throughputCalculationLock.lock(); 531 532 try { 533 return scheduledWriteBytes; 534 } finally { 535 throughputCalculationLock.unlock(); 536 } 537 } 538 539 /** 540 * Increments by <code>increment</code> the count of bytes scheduled for write. 541 * 542 * @param increment The number of added bytes fro write 543 */ 544 public final void increaseScheduledWriteBytes(int increment) { 545 throughputCalculationLock.lock(); 546 547 try { 548 scheduledWriteBytes += increment; 549 } finally { 550 throughputCalculationLock.unlock(); 551 } 552 } 553 554 /** 555 * @return the count of messages scheduled for write. 556 */ 557 public final int getScheduledWriteMessages() { 558 throughputCalculationLock.lock(); 559 560 try { 561 return scheduledWriteMessages; 562 } finally { 563 throughputCalculationLock.unlock(); 564 } 565 } 566 567 /** 568 * Increments the count of messages scheduled for write. 569 */ 570 public final void increaseScheduledWriteMessages() { 571 throughputCalculationLock.lock(); 572 573 try { 574 scheduledWriteMessages++; 575 } finally { 576 throughputCalculationLock.unlock(); 577 } 578 } 579 580 /** 581 * Decrements the count of messages scheduled for write. 582 */ 583 public final void decreaseScheduledWriteMessages() { 584 throughputCalculationLock.lock(); 585 586 try { 587 scheduledWriteMessages--; 588 } finally { 589 throughputCalculationLock.unlock(); 590 } 591 } 592 593 /** 594 * Sets the time at which throughput counters where updated. 595 * 596 * @param lastThroughputCalculationTime The time at which throughput counters where updated. 597 */ 598 protected void setLastThroughputCalculationTime(long lastThroughputCalculationTime) { 599 throughputCalculationLock.lock(); 600 601 try { 602 this.lastThroughputCalculationTime = lastThroughputCalculationTime; 603 } finally { 604 throughputCalculationLock.unlock(); 605 } 606 } 607}