001/* 002 * Copyright 2009-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk; 037 038 039 040import java.io.Serializable; 041import java.util.concurrent.atomic.AtomicLong; 042 043import com.unboundid.util.Mutable; 044import com.unboundid.util.NotNull; 045import com.unboundid.util.ThreadSafety; 046import com.unboundid.util.ThreadSafetyLevel; 047 048 049 050/** 051 * This class provides a data structure with information about usage of an LDAP 052 * connection pool. Calls to update statistics maintained by this class are 053 * threadsafe, but attempts to access different statistics may not be consistent 054 * if operations may be in progress in the connection pool. 055 * <BR><BR> 056 * The set of statistics maintained for connection pools include: 057 * <UL> 058 * <LI>The current number of connections that are available within the 059 * pool.</LI> 060 * <LI>The maximum number of connections that may be available within the 061 * pool.</LI> 062 * <LI>The total number of connections that have been successfully checked out 063 * of the pool.</LI> 064 * <LI>The number of connections that have been successfully checked out of 065 * of the pool without needing to wait for a connection to become 066 * available. 067 * <LI>The number of connections that have been successfully checked out of 068 * the pool after waiting for a connection to become available.</LI> 069 * <LI>The number of connections that have been successfully checked out of 070 * the pool after creating a new connection to service the request.</LI> 071 * <LI>The number of failed attempts to check a connection out of the 072 * pool.</LI> 073 * <LI>The number of connections that have been released back to the pool as 074 * valid.</LI> 075 * <LI>The number of connections that have been closed as defunct.</LI> 076 * <LI>The number of connections that have been closed as expired (i.e., that 077 * had been established for the maximum connection age).</LI> 078 * <LI>The number of connections that have been closed as unneeded (because 079 * the pool already had the maximum number of available connections).</LI> 080 * <LI>The number of successful attempts to create a new connection for use in 081 * the pool.</LI> 082 * <LI>The number of failed attempts to create a new connection for use in the 083 * pool.</LI> 084 * </UL> 085 */ 086@Mutable() 087@ThreadSafety(level=ThreadSafetyLevel.MOSTLY_THREADSAFE) 088public final class LDAPConnectionPoolStatistics 089 implements Serializable 090{ 091 /** 092 * The serial version UID for this serializable class. 093 */ 094 private static final long serialVersionUID = 1493039391352814874L; 095 096 097 098 // The number of connections that have been closed as defunct. 099 @NotNull private final AtomicLong numConnectionsClosedDefunct; 100 101 // The number of connections that have been closed because they were expired. 102 @NotNull private final AtomicLong numConnectionsClosedExpired; 103 104 // The number of connections that have been closed because they were no longer 105 // needed. 106 @NotNull private final AtomicLong numConnectionsClosedUnneeded; 107 108 // The number of failed attempts to check out a connection from the pool. 109 @NotNull private final AtomicLong numFailedCheckouts; 110 111 // The number of failed attempts to create a connection for use in the pool. 112 @NotNull private final AtomicLong numFailedConnectionAttempts; 113 114 // The number of valid connections released back to the pool. 115 @NotNull private final AtomicLong numReleasedValid; 116 117 // The number of successful attempts to check out a connection from the pool. 118 @NotNull private final AtomicLong numSuccessfulCheckouts; 119 120 // The number of successful checkout attempts that retrieved a connection from 121 // the pool after waiting for it to become available. 122 @NotNull private final AtomicLong numSuccessfulCheckoutsAfterWait; 123 124 // The number of successful checkout attempts that had to create a new 125 // connection because none were available. 126 @NotNull private final AtomicLong numSuccessfulCheckoutsNewConnection; 127 128 // The number of successful checkout attempts that were able to take an 129 // existing connection without waiting. 130 @NotNull private final AtomicLong numSuccessfulCheckoutsWithoutWait; 131 132 // The number successful attempts to create a connection for use in the pool. 133 @NotNull private final AtomicLong numSuccessfulConnectionAttempts; 134 135 // The connection pool with which these statistics are associated. 136 @NotNull private final AbstractConnectionPool pool; 137 138 139 140 /** 141 * Creates a new instance of this LDAP connection pool statistics object. All 142 * of the counts will be initialized to zero. 143 * 144 * @param pool The connection pool with which these statistics are 145 * associated. 146 */ 147 public LDAPConnectionPoolStatistics( 148 @NotNull final AbstractConnectionPool pool) 149 { 150 this.pool = pool; 151 152 numSuccessfulConnectionAttempts = new AtomicLong(0L); 153 numFailedConnectionAttempts = new AtomicLong(0L); 154 numConnectionsClosedDefunct = new AtomicLong(0L); 155 numConnectionsClosedExpired = new AtomicLong(0L); 156 numConnectionsClosedUnneeded = new AtomicLong(0L); 157 numSuccessfulCheckouts = new AtomicLong(0L); 158 numSuccessfulCheckoutsAfterWait = new AtomicLong(0L); 159 numSuccessfulCheckoutsNewConnection = new AtomicLong(0L); 160 numSuccessfulCheckoutsWithoutWait = new AtomicLong(0L); 161 numFailedCheckouts = new AtomicLong(0L); 162 numReleasedValid = new AtomicLong(0L); 163 } 164 165 166 167 /** 168 * Resets all counters back to zero. 169 */ 170 public void reset() 171 { 172 numSuccessfulConnectionAttempts.set(0L); 173 numFailedConnectionAttempts.set(0L); 174 numConnectionsClosedDefunct.set(0L); 175 numConnectionsClosedExpired.set(0L); 176 numConnectionsClosedUnneeded.set(0L); 177 numSuccessfulCheckouts.set(0L); 178 numSuccessfulCheckoutsAfterWait.set(0L); 179 numSuccessfulCheckoutsNewConnection.set(0L); 180 numSuccessfulCheckoutsWithoutWait.set(0L); 181 numFailedCheckouts.set(0L); 182 numReleasedValid.set(0L); 183 } 184 185 186 187 /** 188 * Retrieves the number of connections that have been successfully created for 189 * use in conjunction with the connection pool. 190 * 191 * @return The number of connections that have been created for use in 192 * conjunction with the connection pool. 193 */ 194 public long getNumSuccessfulConnectionAttempts() 195 { 196 return numSuccessfulConnectionAttempts.get(); 197 } 198 199 200 201 /** 202 * Increments the number of connections that have been successfully created 203 * for use in conjunction with the connection pool. 204 */ 205 void incrementNumSuccessfulConnectionAttempts() 206 { 207 numSuccessfulConnectionAttempts.incrementAndGet(); 208 } 209 210 211 212 /** 213 * Retrieves the number of failed attempts to create a connection for use in 214 * the connection pool. 215 * 216 * @return The number of failed attempts to create a connection for use in 217 * the connection pool. 218 */ 219 public long getNumFailedConnectionAttempts() 220 { 221 return numFailedConnectionAttempts.get(); 222 } 223 224 225 226 /** 227 * Increments the number of failed attempts to create a connection for use in 228 * the connection pool. 229 */ 230 void incrementNumFailedConnectionAttempts() 231 { 232 numFailedConnectionAttempts.incrementAndGet(); 233 } 234 235 236 237 /** 238 * Retrieves the number of connections that have been closed as defunct (i.e., 239 * they are no longer believed to be valid). 240 * 241 * @return The number of connections that have been closed as defunct. 242 */ 243 public long getNumConnectionsClosedDefunct() 244 { 245 return numConnectionsClosedDefunct.get(); 246 } 247 248 249 250 /** 251 * Increments the number of connections that have been closed as defunct. 252 */ 253 void incrementNumConnectionsClosedDefunct() 254 { 255 numConnectionsClosedDefunct.incrementAndGet(); 256 } 257 258 259 260 /** 261 * Retrieves the number of connections that have been closed as expired (i.e., 262 * they have been established for longer than the maximum connection age for 263 * the pool). 264 * 265 * @return The number of connections that have been closed as expired. 266 */ 267 public long getNumConnectionsClosedExpired() 268 { 269 return numConnectionsClosedExpired.get(); 270 } 271 272 273 274 /** 275 * Increments the number of connections that have been closed as expired. 276 */ 277 void incrementNumConnectionsClosedExpired() 278 { 279 numConnectionsClosedExpired.incrementAndGet(); 280 } 281 282 283 284 /** 285 * Retrieves the number of connections that have been closed as unneeded 286 * (i.e., they were created in response to heavy load but are no longer needed 287 * to meet the current load, or they were closed when the pool was closed). 288 * 289 * @return The number of connections that have been closed as unneeded. 290 */ 291 public long getNumConnectionsClosedUnneeded() 292 { 293 return numConnectionsClosedUnneeded.get(); 294 } 295 296 297 298 /** 299 * Increments the number of connections that have been closed as unneeded. 300 */ 301 void incrementNumConnectionsClosedUnneeded() 302 { 303 numConnectionsClosedUnneeded.incrementAndGet(); 304 } 305 306 307 308 /** 309 * Retrieves the number of successful attempts to check out a connection from 310 * the pool (including connections checked out for internal use by operations 311 * processed as part of the pool). 312 * 313 * @return The number of successful attempts to check out a connection from 314 * the pool. 315 */ 316 public long getNumSuccessfulCheckouts() 317 { 318 return numSuccessfulCheckouts.get(); 319 } 320 321 322 323 /** 324 * Retrieves the number of successful attempts to check out a connection from 325 * the pool that were able to obtain an existing connection without waiting. 326 * 327 * @return The number of successful attempts to check out a connection from 328 * the pool that were able to obtain an existing connection without 329 * waiting. 330 */ 331 public long getNumSuccessfulCheckoutsWithoutWaiting() 332 { 333 return numSuccessfulCheckoutsWithoutWait.get(); 334 } 335 336 337 338 /** 339 * Retrieves the number of successful attempts to check out a connection from 340 * the pool that had to wait for a connection to become available. 341 * 342 * @return The number of successful attempts to check out a connection from 343 * the pool that had to wait for a connection to become available. 344 */ 345 public long getNumSuccessfulCheckoutsAfterWaiting() 346 { 347 return numSuccessfulCheckoutsAfterWait.get(); 348 } 349 350 351 352 /** 353 * Retrieves the number of successful attempts to check out a connection from 354 * the pool that had to create a new connection because no existing 355 * connections were available. 356 * 357 * @return The number of successful attempts to check out a connection from 358 * the pool that had to create a new connection because no existing 359 * connections were available. 360 */ 361 public long getNumSuccessfulCheckoutsNewConnection() 362 { 363 return numSuccessfulCheckoutsNewConnection.get(); 364 } 365 366 367 368 /** 369 * Increments the number of successful attempts to check out a connection from 370 * the pool without waiting. 371 */ 372 void incrementNumSuccessfulCheckoutsWithoutWaiting() 373 { 374 numSuccessfulCheckouts.incrementAndGet(); 375 numSuccessfulCheckoutsWithoutWait.incrementAndGet(); 376 } 377 378 379 380 /** 381 * Increments the number of successful attempts to check out a connection from 382 * the pool after waiting. 383 */ 384 void incrementNumSuccessfulCheckoutsAfterWaiting() 385 { 386 numSuccessfulCheckouts.incrementAndGet(); 387 numSuccessfulCheckoutsAfterWait.incrementAndGet(); 388 } 389 390 391 392 /** 393 * Increments the number of successful attempts to check out a connection from 394 * the pool after creating a new connection. 395 */ 396 void incrementNumSuccessfulCheckoutsNewConnection() 397 { 398 numSuccessfulCheckouts.incrementAndGet(); 399 numSuccessfulCheckoutsNewConnection.incrementAndGet(); 400 } 401 402 403 404 /** 405 * Retrieves the number of failed attempts to check out a connection from 406 * the pool (including connections checked out for internal use by operations 407 * processed as part of the pool). 408 * 409 * @return The number of failed attempts to check out a connection from 410 * the pool. 411 */ 412 public long getNumFailedCheckouts() 413 { 414 return numFailedCheckouts.get(); 415 } 416 417 418 419 /** 420 * Increments the number of failed attempts to check out a connection from 421 * the pool. 422 */ 423 void incrementNumFailedCheckouts() 424 { 425 numFailedCheckouts.incrementAndGet(); 426 } 427 428 429 430 /** 431 * Retrieves the number of times a valid, usable connection has been released 432 * back to the pool after being checked out (including connections checked out 433 * for internal use by operations processed within the pool). 434 * 435 * @return The number of times a valid connection has been released back to 436 * the pool. 437 */ 438 public long getNumReleasedValid() 439 { 440 return numReleasedValid.get(); 441 } 442 443 444 445 /** 446 * Increments the number of times a valid, usable connection has been released 447 * back to the pool. 448 */ 449 void incrementNumReleasedValid() 450 { 451 numReleasedValid.incrementAndGet(); 452 } 453 454 455 456 /** 457 * Retrieves the number of connections currently available for use in the 458 * pool, if that information is available. 459 * 460 * @return The number of connections currently available for use in the pool, 461 * or -1 if that is not applicable for the associated connection pool 462 * implementation. 463 */ 464 public int getNumAvailableConnections() 465 { 466 return pool.getCurrentAvailableConnections(); 467 } 468 469 470 471 /** 472 * Retrieves the maximum number of connections that may be available in the 473 * pool at any time, if that information is available. 474 * 475 * @return The maximum number of connections that may be available in the 476 * pool at any time, or -1 if that is not applicable for the 477 * associated connection pool implementation. 478 */ 479 public int getMaximumAvailableConnections() 480 { 481 return pool.getMaximumAvailableConnections(); 482 } 483 484 485 486 /** 487 * Retrieves a string representation of this LDAP connection pool statistics 488 * object. 489 * 490 * @return A string representation of this LDAP connection pool statistics 491 * object. 492 */ 493 @Override() 494 @NotNull() 495 public String toString() 496 { 497 final StringBuilder buffer = new StringBuilder(); 498 toString(buffer); 499 return buffer.toString(); 500 } 501 502 503 504 /** 505 * Appends a string representation of this LDAP connection pool statistics 506 * object to the provided buffer. 507 * 508 * @param buffer The buffer to which the string representation should be 509 * appended. 510 */ 511 public void toString(@NotNull final StringBuilder buffer) 512 { 513 final long availableConns = pool.getCurrentAvailableConnections(); 514 final long maxConns = pool.getMaximumAvailableConnections(); 515 final long successfulConns = numSuccessfulConnectionAttempts.get(); 516 final long failedConns = numFailedConnectionAttempts.get(); 517 final long connsClosedDefunct = numConnectionsClosedDefunct.get(); 518 final long connsClosedExpired = numConnectionsClosedExpired.get(); 519 final long connsClosedUnneeded = numConnectionsClosedUnneeded.get(); 520 final long successfulCheckouts = numSuccessfulCheckouts.get(); 521 final long failedCheckouts = numFailedCheckouts.get(); 522 final long releasedValid = numReleasedValid.get(); 523 524 buffer.append("LDAPConnectionPoolStatistics(numAvailableConnections="); 525 buffer.append(availableConns); 526 buffer.append(", maxAvailableConnections="); 527 buffer.append(maxConns); 528 buffer.append(", numSuccessfulConnectionAttempts="); 529 buffer.append(successfulConns); 530 buffer.append(", numFailedConnectionAttempts="); 531 buffer.append(failedConns); 532 buffer.append(", numConnectionsClosedDefunct="); 533 buffer.append(connsClosedDefunct); 534 buffer.append(", numConnectionsClosedExpired="); 535 buffer.append(connsClosedExpired); 536 buffer.append(", numConnectionsClosedUnneeded="); 537 buffer.append(connsClosedUnneeded); 538 buffer.append(", numSuccessfulCheckouts="); 539 buffer.append(successfulCheckouts); 540 buffer.append(", numFailedCheckouts="); 541 buffer.append(failedCheckouts); 542 buffer.append(", numReleasedValid="); 543 buffer.append(releasedValid); 544 buffer.append(')'); 545 } 546}