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