001    /*
002     * Copyright 2009-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2016 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     */
021    package com.unboundid.ldap.sdk;
022    
023    
024    
025    import java.io.Serializable;
026    import java.util.concurrent.atomic.AtomicLong;
027    
028    import com.unboundid.util.Mutable;
029    import com.unboundid.util.ThreadSafety;
030    import 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)
072    public 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    }