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