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