001    /*
002     * Copyright 2009-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2015 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.text.DecimalFormat;
027    import java.util.concurrent.atomic.AtomicLong;
028    
029    import com.unboundid.util.Mutable;
030    import com.unboundid.util.ThreadSafety;
031    import com.unboundid.util.ThreadSafetyLevel;
032    
033    
034    
035    /**
036     * This class provides a data structure with information about operations
037     * performed on an associated LDAP connection.  Calls to update statistics
038     * maintained by this class are threadsafe, but attempts to access different
039     * statistics may not be consistent if other operations may be in progress on
040     * the connection.
041     * <BR><BR>
042     * The set of statistics maintained for connections:
043     * <UL>
044     *   <LI>The number of attempts made to establish the connection.</LI>
045     *   <LI>The number of times the connection has been closed.</LI>
046     *   <LI>The number of requests of each type that have been sent over the
047     *       connection.</LI>
048     *   <LI>The number of responses of each type that have been received over the
049     *       connection.</LI>
050     *   <LI>The average response time (in milliseconds or nanoseconds) for each
051     *       type of operation processed on the connection.</LI>
052     * </UL>
053     */
054    @Mutable()
055    @ThreadSafety(level=ThreadSafetyLevel.MOSTLY_THREADSAFE)
056    public final class LDAPConnectionStatistics
057           implements Serializable
058    {
059      /**
060       * The serial version UID for this serializable class.
061       */
062      private static final long serialVersionUID = -1096417617572481790L;
063    
064    
065    
066      // The number of abandon requests sent over the associated connection.
067      private final AtomicLong numAbandonRequests;
068    
069      // The number of add requests sent over the associated connection.
070      private final AtomicLong numAddRequests;
071    
072      // The number of add responses received on the associated connection.
073      private final AtomicLong numAddResponses;
074    
075      // The number of bind requests sent over the associated connection.
076      private final AtomicLong numBindRequests;
077    
078      // The number of bind responses received on the associated connection.
079      private final AtomicLong numBindResponses;
080    
081      // The number of compare requests sent over the associated connection.
082      private final AtomicLong numCompareRequests;
083    
084      // The number of compare responses received on the associated connection.
085      private final AtomicLong numCompareResponses;
086    
087      // The number of times the associated connection has been connected to a
088      // server.
089      private final AtomicLong numConnects;
090    
091      // The number of delete requests sent over the associated connection.
092      private final AtomicLong numDeleteRequests;
093    
094      // The number of delete responses received on the associated connection.
095      private final AtomicLong numDeleteResponses;
096    
097      // The number of times the associated connection has been disconnected from a
098      // server.
099      private final AtomicLong numDisconnects;
100    
101      // The number of extended requests sent over the associated connection.
102      private final AtomicLong numExtendedRequests;
103    
104      // The number of extended responses received on the associated connection.
105      private final AtomicLong numExtendedResponses;
106    
107      // The number of modify requests sent over the associated connection.
108      private final AtomicLong numModifyRequests;
109    
110      // The number of modify responses received on the associated connection.
111      private final AtomicLong numModifyResponses;
112    
113      // The number of modify DN requests sent over the associated connection.
114      private final AtomicLong numModifyDNRequests;
115    
116      // The number of modify DN responses received on the associated connection.
117      private final AtomicLong numModifyDNResponses;
118    
119      // The number of search requests sent over the associated connection.
120      private final AtomicLong numSearchRequests;
121    
122      // The number of search result entry responses received on the associated
123      // connection.
124      private final AtomicLong numSearchEntryResponses;
125    
126      // The number of search result reference responses received on the associated
127      // connection.
128      private final AtomicLong numSearchReferenceResponses;
129    
130      // The number of search result done responses received on the associated
131      // connection.
132      private final AtomicLong numSearchDoneResponses;
133    
134      // The number of unbind requests sent over the associated connection.
135      private final AtomicLong numUnbindRequests;
136    
137      // The total length of time spent waiting for add responses.
138      private final AtomicLong totalAddResponseTime;
139    
140      // The total length of time spent waiting for bind responses.
141      private final AtomicLong totalBindResponseTime;
142    
143      // The total length of time spent waiting for compare responses.
144      private final AtomicLong totalCompareResponseTime;
145    
146      // The total length of time spent waiting for delete responses.
147      private final AtomicLong totalDeleteResponseTime;
148    
149      // The total length of time spent waiting for extended responses.
150      private final AtomicLong totalExtendedResponseTime;
151    
152      // The total length of time spent waiting for modify responses.
153      private final AtomicLong totalModifyResponseTime;
154    
155      // The total length of time spent waiting for modify DN responses.
156      private final AtomicLong totalModifyDNResponseTime;
157    
158      // The total length of time spent waiting for search done responses.
159      private final AtomicLong totalSearchResponseTime;
160    
161    
162    
163      /**
164       * Creates a new instance of this LDAP connection statistics object.  All of
165       * the counts will be initialized to zero.
166       */
167      public LDAPConnectionStatistics()
168      {
169        numAbandonRequests          = new AtomicLong(0L);
170        numAddRequests              = new AtomicLong(0L);
171        numAddResponses             = new AtomicLong(0L);
172        numBindRequests             = new AtomicLong(0L);
173        numBindResponses            = new AtomicLong(0L);
174        numCompareRequests          = new AtomicLong(0L);
175        numCompareResponses         = new AtomicLong(0L);
176        numConnects                 = new AtomicLong(0L);
177        numDeleteRequests           = new AtomicLong(0L);
178        numDeleteResponses          = new AtomicLong(0L);
179        numDisconnects              = new AtomicLong(0L);
180        numExtendedRequests         = new AtomicLong(0L);
181        numExtendedResponses        = new AtomicLong(0L);
182        numModifyRequests           = new AtomicLong(0L);
183        numModifyResponses          = new AtomicLong(0L);
184        numModifyDNRequests         = new AtomicLong(0L);
185        numModifyDNResponses        = new AtomicLong(0L);
186        numSearchRequests           = new AtomicLong(0L);
187        numSearchEntryResponses     = new AtomicLong(0L);
188        numSearchReferenceResponses = new AtomicLong(0L);
189        numSearchDoneResponses      = new AtomicLong(0L);
190        numUnbindRequests           = new AtomicLong(0L);
191        totalAddResponseTime        = new AtomicLong(0L);
192        totalBindResponseTime       = new AtomicLong(0L);
193        totalCompareResponseTime    = new AtomicLong(0L);
194        totalDeleteResponseTime     = new AtomicLong(0L);
195        totalExtendedResponseTime   = new AtomicLong(0L);
196        totalModifyResponseTime     = new AtomicLong(0L);
197        totalModifyDNResponseTime   = new AtomicLong(0L);
198        totalSearchResponseTime     = new AtomicLong(0L);
199      }
200    
201    
202    
203      /**
204       * Resets all counters back to zero.
205       */
206      public void reset()
207      {
208        numAbandonRequests.set(0L);
209        numAddRequests.set(0L);
210        numAddResponses.set(0L);
211        numBindRequests.set(0L);
212        numBindResponses.set(0L);
213        numCompareRequests.set(0L);
214        numCompareResponses.set(0L);
215        numConnects.set(0L);
216        numDeleteRequests.set(0L);
217        numDeleteResponses.set(0L);
218        numDisconnects.set(0L);
219        numExtendedRequests.set(0L);
220        numExtendedResponses.set(0L);
221        numModifyRequests.set(0L);
222        numModifyResponses.set(0L);
223        numModifyDNRequests.set(0L);
224        numModifyDNResponses.set(0L);
225        numSearchRequests.set(0L);
226        numSearchEntryResponses.set(0L);
227        numSearchReferenceResponses.set(0L);
228        numSearchDoneResponses.set(0L);
229        numUnbindRequests.set(0L);
230        totalAddResponseTime.set(0L);
231        totalBindResponseTime.set(0L);
232        totalCompareResponseTime.set(0L);
233        totalDeleteResponseTime.set(0L);
234        totalExtendedResponseTime.set(0L);
235        totalModifyResponseTime.set(0L);
236        totalModifyDNResponseTime.set(0L);
237        totalSearchResponseTime.set(0L);
238      }
239    
240    
241    
242      /**
243       * Retrieves the number of times an attempt has been made to establish the
244       * associated connection.
245       *
246       * @return  The number of times an attempt has been made to establish the
247       *          associated connection.
248       */
249      public long getNumConnects()
250      {
251        return numConnects.get();
252      }
253    
254    
255    
256      /**
257       * Increments the number of times an attempt has been made to establish the
258       * associated connection.
259       */
260      void incrementNumConnects()
261      {
262        numConnects.incrementAndGet();
263      }
264    
265    
266    
267      /**
268       * Retrieves the number of times the associated connection has been
269       * terminated.  Note that this may exceed the number of connection attempts
270       * because there may be cases in which an attempt is made to close a
271       * connection after it has already been closed or otherwise disconnected.
272       *
273       * @return  The number of times the associated connection has been terminated.
274       */
275      public long getNumDisconnects()
276      {
277        return numDisconnects.get();
278      }
279    
280    
281    
282      /**
283       * Increments the number of times an attempt has been made to terminate the
284       * associated connection.
285       */
286      void incrementNumDisconnects()
287      {
288        numDisconnects.incrementAndGet();
289      }
290    
291    
292    
293      /**
294       * Retrieves the number of abandon requests sent on the associated connection.
295       *
296       * @return  The number of abandon requests sent on the associated connection.
297       */
298      public long getNumAbandonRequests()
299      {
300        return numAbandonRequests.get();
301      }
302    
303    
304    
305      /**
306       * Increments the number of abandon requests sent on the associated
307       * connection.
308       */
309      void incrementNumAbandonRequests()
310      {
311        numAbandonRequests.incrementAndGet();
312      }
313    
314    
315    
316      /**
317       * Retrieves the number of add requests sent on the associated connection.
318       *
319       * @return  The number of add requests sent on the associated connection.
320       */
321      public long getNumAddRequests()
322      {
323        return numAddRequests.get();
324      }
325    
326    
327    
328      /**
329       * Increments the number of add requests sent on the associated connection.
330       */
331      void incrementNumAddRequests()
332      {
333        numAddRequests.incrementAndGet();
334      }
335    
336    
337    
338      /**
339       * Retrieves the number of add responses sent on the associated connection.
340       *
341       * @return  The number of add responses sent on the associated connection.
342       */
343      public long getNumAddResponses()
344      {
345        return numAddResponses.get();
346      }
347    
348    
349    
350      /**
351       * Increments the number of add responses sent on the associated connection.
352       *
353       * @param  responseTime  The length of time in nanoseconds between sending
354       *                       the request and receiving the response.
355       */
356      void incrementNumAddResponses(final long responseTime)
357      {
358        numAddResponses.incrementAndGet();
359    
360        if (responseTime > 0)
361        {
362          totalAddResponseTime.addAndGet(responseTime);
363        }
364      }
365    
366    
367    
368      /**
369       * Retrieves the total response time in nanoseconds for all add operations
370       * processed on the associated connection.
371       *
372       * @return  The total response time in nanoseconds for all add operations
373       *          processed on the associated connection.
374       */
375      public long getTotalAddResponseTimeNanos()
376      {
377        return totalAddResponseTime.get();
378      }
379    
380    
381    
382      /**
383       * Retrieves the total response time in milliseconds for all add operations
384       * processed on the associated connection.
385       *
386       * @return  The total response time in milliseconds for all add operations
387       *          processed on the associated connection.
388       */
389      public long getTotalAddResponseTimeMillis()
390      {
391        return Math.round(totalAddResponseTime.get() / 1000000.0d);
392      }
393    
394    
395    
396      /**
397       * Retrieves the average response time in nanoseconds for all add operations
398       * processed on the associated connection.
399       *
400       * @return  The average response time in nanoseconds for all add operations
401       *          processed on the associated connection, or {@code Double.NaN} if
402       *          no add operations have yet been performed.
403       */
404      public double getAverageAddResponseTimeNanos()
405      {
406        final long totalTime  = totalAddResponseTime.get();
407        final long totalCount = numAddResponses.get();
408    
409        if (totalTime > 0)
410        {
411          return (1.0d * totalTime / totalCount);
412        }
413        else
414        {
415          return Double.NaN;
416        }
417      }
418    
419    
420    
421      /**
422       * Retrieves the average response time in milliseconds for all add operations
423       * processed on the associated connection.
424       *
425       * @return  The average response time in milliseconds for all add operations
426       *          processed on the associated connection, or {@code Double.NaN} if
427       *          no add operations have yet been performed.
428       */
429      public double getAverageAddResponseTimeMillis()
430      {
431        final long totalTime  = totalAddResponseTime.get();
432        final long totalCount = numAddResponses.get();
433    
434        if (totalTime > 0)
435        {
436          return (totalTime / 1000000.0d / totalCount);
437        }
438        else
439        {
440          return Double.NaN;
441        }
442      }
443    
444    
445    
446      /**
447       * Retrieves the number of bind requests sent on the associated connection.
448       *
449       * @return  The number of bind requests sent on the associated connection.
450       */
451      public long getNumBindRequests()
452      {
453        return numBindRequests.get();
454      }
455    
456    
457    
458      /**
459       * Increments the number of bind requests sent on the associated connection.
460       */
461      void incrementNumBindRequests()
462      {
463        numBindRequests.incrementAndGet();
464      }
465    
466    
467    
468      /**
469       * Retrieves the number of bind responses sent on the associated connection.
470       *
471       * @return  The number of bind responses sent on the associated connection.
472       */
473      public long getNumBindResponses()
474      {
475        return numBindResponses.get();
476      }
477    
478    
479    
480      /**
481       * Increments the number of bind responses sent on the associated connection.
482       *
483       * @param  responseTime  The length of time in nanoseconds between sending
484       *                       the request and receiving the response.
485       */
486      void incrementNumBindResponses(final long responseTime)
487      {
488        numBindResponses.incrementAndGet();
489    
490        if (responseTime > 0)
491        {
492          totalBindResponseTime.addAndGet(responseTime);
493        }
494      }
495    
496    
497    
498      /**
499       * Retrieves the total response time in nanoseconds for all bind operations
500       * processed on the associated connection.
501       *
502       * @return  The total response time in nanoseconds for all bind operations
503       *          processed on the associated connection.
504       */
505      public long getTotalBindResponseTimeNanos()
506      {
507        return totalBindResponseTime.get();
508      }
509    
510    
511    
512      /**
513       * Retrieves the total response time in milliseconds for all bind operations
514       * processed on the associated connection.
515       *
516       * @return  The total response time in milliseconds for all bind operations
517       *          processed on the associated connection.
518       */
519      public long getTotalBindResponseTimeMillis()
520      {
521        return Math.round(totalBindResponseTime.get() / 1000000.0d);
522      }
523    
524    
525    
526      /**
527       * Retrieves the average response time in nanoseconds for all bind operations
528       * processed on the associated connection.
529       *
530       * @return  The average response time in nanoseconds for all bind operations
531       *          processed on the associated connection, or {@code Double.NaN} if
532       *          no bind operations have yet been performed.
533       */
534      public double getAverageBindResponseTimeNanos()
535      {
536        final long totalTime  = totalBindResponseTime.get();
537        final long totalCount = numBindResponses.get();
538    
539        if (totalTime > 0)
540        {
541          return (1.0d * totalTime / totalCount);
542        }
543        else
544        {
545          return Double.NaN;
546        }
547      }
548    
549    
550    
551      /**
552       * Retrieves the average response time in milliseconds for all bind operations
553       * processed on the associated connection.
554       *
555       * @return  The average response time in milliseconds for all bind operations
556       *          processed on the associated connection, or {@code Double.NaN} if
557       *          no bind operations have yet been performed.
558       */
559      public double getAverageBindResponseTimeMillis()
560      {
561        final long totalTime  = totalBindResponseTime.get();
562        final long totalCount = numBindResponses.get();
563    
564        if (totalTime > 0)
565        {
566          return (totalTime / 1000000.0d / totalCount);
567        }
568        else
569        {
570          return Double.NaN;
571        }
572      }
573    
574    
575    
576      /**
577       * Retrieves the number of compare requests sent on the associated connection.
578       *
579       * @return  The number of compare requests sent on the associated connection.
580       */
581      public long getNumCompareRequests()
582      {
583        return numCompareRequests.get();
584      }
585    
586    
587    
588      /**
589       * Increments the number of compare requests sent on the associated
590       * connection.
591       */
592      void incrementNumCompareRequests()
593      {
594        numCompareRequests.incrementAndGet();
595      }
596    
597    
598    
599      /**
600       * Retrieves the number of compare responses sent on the associated
601       * connection.
602       *
603       * @return  The number of compare responses sent on the associated connection.
604       */
605      public long getNumCompareResponses()
606      {
607        return numCompareResponses.get();
608      }
609    
610    
611    
612      /**
613       * Increments the number of compare responses sent on the associated
614       * connection.
615       *
616       * @param  responseTime  The length of time in nanoseconds between sending
617       *                       the request and receiving the response.
618       */
619      void incrementNumCompareResponses(final long responseTime)
620      {
621        numCompareResponses.incrementAndGet();
622    
623        if (responseTime > 0)
624        {
625          totalCompareResponseTime.addAndGet(responseTime);
626        }
627      }
628    
629    
630    
631      /**
632       * Retrieves the total response time in nanoseconds for all compare
633       * operations processed on the associated connection.
634       *
635       * @return  The total response time in nanoseconds for all compare operations
636       *          processed on the associated connection.
637       */
638      public long getTotalCompareResponseTimeNanos()
639      {
640        return totalCompareResponseTime.get();
641      }
642    
643    
644    
645      /**
646       * Retrieves the total response time in milliseconds for all compare
647       * operations processed on the associated connection.
648       *
649       * @return  The total response time in milliseconds for all compare operations
650       *          processed on the associated connection.
651       */
652      public long getTotalCompareResponseTimeMillis()
653      {
654        return Math.round(totalCompareResponseTime.get() / 1000000.0d);
655      }
656    
657    
658    
659      /**
660       * Retrieves the average response time in nanoseconds for all compare
661       * operations processed on the associated connection.
662       *
663       * @return  The average response time in nanoseconds for all compare
664       *          operations processed on the associated connection, or
665       *          {@code Double.NaN} if no compare operations have yet been
666       *          performed.
667       */
668      public double getAverageCompareResponseTimeNanos()
669      {
670        final long totalTime  = totalCompareResponseTime.get();
671        final long totalCount = numCompareResponses.get();
672    
673        if (totalTime > 0)
674        {
675          return (1.0d * totalTime / totalCount);
676        }
677        else
678        {
679          return Double.NaN;
680        }
681      }
682    
683    
684    
685      /**
686       * Retrieves the average response time in milliseconds for all compare
687       * operations processed on the associated connection.
688       *
689       * @return  The average response time in milliseconds for all compare
690       *          operations processed on the associated connection, or
691       *          {@code Double.NaN} if no compare operations have yet been
692       *          performed.
693       */
694      public double getAverageCompareResponseTimeMillis()
695      {
696        final long totalTime  = totalCompareResponseTime.get();
697        final long totalCount = numCompareResponses.get();
698    
699        if (totalTime > 0)
700        {
701          return (totalTime / 1000000.0d / totalCount);
702        }
703        else
704        {
705          return Double.NaN;
706        }
707      }
708    
709    
710    
711      /**
712       * Retrieves the number of delete requests sent on the associated connection.
713       *
714       * @return  The number of delete requests sent on the associated connection.
715       */
716      public long getNumDeleteRequests()
717      {
718        return numDeleteRequests.get();
719      }
720    
721    
722    
723      /**
724       * Increments the number of delete requests sent on the associated connection.
725       */
726      void incrementNumDeleteRequests()
727      {
728        numDeleteRequests.incrementAndGet();
729      }
730    
731    
732    
733      /**
734       * Retrieves the number of delete responses sent on the associated connection.
735       *
736       * @return  The number of delete responses sent on the associated connection.
737       */
738      public long getNumDeleteResponses()
739      {
740        return numDeleteResponses.get();
741      }
742    
743    
744    
745      /**
746       * Increments the number of delete responses sent on the associated
747       * connection.
748       *
749       * @param  responseTime  The length of time in nanoseconds between sending
750       *                       the request and receiving the response.
751       */
752      void incrementNumDeleteResponses(final long responseTime)
753      {
754        numDeleteResponses.incrementAndGet();
755    
756        if (responseTime > 0)
757        {
758          totalDeleteResponseTime.addAndGet(responseTime);
759        }
760      }
761    
762    
763    
764      /**
765       * Retrieves the total response time in nanoseconds for all delete
766       * operations processed on the associated connection.
767       *
768       * @return  The total response time in nanoseconds for all delete operations
769       *          processed on the associated connection.
770       */
771      public long getTotalDeleteResponseTimeNanos()
772      {
773        return totalDeleteResponseTime.get();
774      }
775    
776    
777    
778      /**
779       * Retrieves the total response time in milliseconds for all delete
780       * operations processed on the associated connection.
781       *
782       * @return  The total response time in milliseconds for all delete operations
783       *          processed on the associated connection.
784       */
785      public long getTotalDeleteResponseTimeMillis()
786      {
787        return Math.round(totalDeleteResponseTime.get() / 1000000.0d);
788      }
789    
790    
791    
792      /**
793       * Retrieves the average response time in nanoseconds for all delete
794       * operations processed on the associated connection.
795       *
796       * @return  The average response time in nanoseconds for all delete
797       *          operations processed on the associated connection, or
798       *          {@code Double.NaN} if no delete operations have yet been
799       *          performed.
800       */
801      public double getAverageDeleteResponseTimeNanos()
802      {
803        final long totalTime  = totalDeleteResponseTime.get();
804        final long totalCount = numDeleteResponses.get();
805    
806        if (totalTime > 0)
807        {
808          return (1.0d * totalTime / totalCount);
809        }
810        else
811        {
812          return Double.NaN;
813        }
814      }
815    
816    
817    
818      /**
819       * Retrieves the average response time in milliseconds for all delete
820       * operations processed on the associated connection.
821       *
822       * @return  The average response time in milliseconds for all delete
823       *          operations processed on the associated connection, or
824       *          {@code Double.NaN} if no delete operations have yet been
825       *          performed.
826       */
827      public double getAverageDeleteResponseTimeMillis()
828      {
829        final long totalTime  = totalDeleteResponseTime.get();
830        final long totalCount = numDeleteResponses.get();
831    
832        if (totalTime > 0)
833        {
834          return (totalTime / 1000000.0d / totalCount);
835        }
836        else
837        {
838          return Double.NaN;
839        }
840      }
841    
842    
843    
844      /**
845       * Retrieves the number of extended requests sent on the associated
846       * connection.
847       *
848       * @return  The number of extended requests sent on the associated connection.
849       */
850      public long getNumExtendedRequests()
851      {
852        return numExtendedRequests.get();
853      }
854    
855    
856    
857      /**
858       * Increments the number of extended requests sent on the associated
859       * connection.
860       */
861      void incrementNumExtendedRequests()
862      {
863        numExtendedRequests.incrementAndGet();
864      }
865    
866    
867    
868      /**
869       * Retrieves the number of extended responses sent on the associated
870       * connection.
871       *
872       * @return  The number of extended responses sent on the associated
873       *          connection.
874       */
875      public long getNumExtendedResponses()
876      {
877        return numExtendedResponses.get();
878      }
879    
880    
881    
882      /**
883       * Increments the number of extended responses sent on the associated
884       * connection.
885       *
886       * @param  responseTime  The length of time in nanoseconds between sending
887       *                       the request and receiving the response.
888       */
889      void incrementNumExtendedResponses(final long responseTime)
890      {
891        numExtendedResponses.incrementAndGet();
892    
893        if (responseTime > 0)
894        {
895          totalExtendedResponseTime.addAndGet(responseTime);
896        }
897      }
898    
899    
900    
901      /**
902       * Retrieves the total response time in nanoseconds for all extended
903       * operations processed on the associated connection.
904       *
905       * @return  The total response time in nanoseconds for all extended
906       *          operations processed on the associated connection.
907       */
908      public long getTotalExtendedResponseTimeNanos()
909      {
910        return totalExtendedResponseTime.get();
911      }
912    
913    
914    
915      /**
916       * Retrieves the total response time in milliseconds for all extended
917       * operations processed on the associated connection.
918       *
919       * @return  The total response time in milliseconds for all extended
920       *          operations processed on the associated connection.
921       */
922      public long getTotalExtendedResponseTimeMillis()
923      {
924        return Math.round(totalExtendedResponseTime.get() / 1000000.0d);
925      }
926    
927    
928    
929      /**
930       * Retrieves the average response time in nanoseconds for all extended
931       * operations processed on the associated connection.
932       *
933       * @return  The average response time in nanoseconds for all extended
934       *          operations processed on the associated connection, or
935       *          {@code Double.NaN} if no extended operations have yet been
936       *          performed.
937       */
938      public double getAverageExtendedResponseTimeNanos()
939      {
940        final long totalTime  = totalExtendedResponseTime.get();
941        final long totalCount = numExtendedResponses.get();
942    
943        if (totalTime > 0)
944        {
945          return (1.0d * totalTime / totalCount);
946        }
947        else
948        {
949          return Double.NaN;
950        }
951      }
952    
953    
954    
955      /**
956       * Retrieves the average response time in milliseconds for all extended
957       * operations processed on the associated connection.
958       *
959       * @return  The average response time in milliseconds for all extended
960       *          operations processed on the associated connection, or
961       *          {@code Double.NaN} if no extended operations have yet been
962       *          performed.
963       */
964      public double getAverageExtendedResponseTimeMillis()
965      {
966        final long totalTime  = totalExtendedResponseTime.get();
967        final long totalCount = numExtendedResponses.get();
968    
969        if (totalTime > 0)
970        {
971          return (totalTime / 1000000.0d / totalCount);
972        }
973        else
974        {
975          return Double.NaN;
976        }
977      }
978    
979    
980    
981      /**
982       * Retrieves the number of modify requests sent on the associated connection.
983       *
984       * @return  The number of modify requests sent on the associated connection.
985       */
986      public long getNumModifyRequests()
987      {
988        return numModifyRequests.get();
989      }
990    
991    
992    
993      /**
994       * Increments the number of modify requests sent on the associated connection.
995       */
996      void incrementNumModifyRequests()
997      {
998        numModifyRequests.incrementAndGet();
999      }
1000    
1001    
1002    
1003      /**
1004       * Retrieves the number of modify responses sent on the associated connection.
1005       *
1006       * @return  The number of modify responses sent on the associated connection.
1007       */
1008      public long getNumModifyResponses()
1009      {
1010        return numModifyResponses.get();
1011      }
1012    
1013    
1014    
1015      /**
1016       * Increments the number of modify responses sent on the associated
1017       * connection.
1018       *
1019       * @param  responseTime  The length of time in nanoseconds between sending
1020       *                       the request and receiving the response.
1021       */
1022      void incrementNumModifyResponses(final long responseTime)
1023      {
1024        numModifyResponses.incrementAndGet();
1025    
1026        if (responseTime > 0)
1027        {
1028          totalModifyResponseTime.addAndGet(responseTime);
1029        }
1030      }
1031    
1032    
1033    
1034      /**
1035       * Retrieves the total response time in nanoseconds for all modify
1036       * operations processed on the associated connection.
1037       *
1038       * @return  The total response time in nanoseconds for all modify operations
1039       *          processed on the associated connection.
1040       */
1041      public long getTotalModifyResponseTimeNanos()
1042      {
1043        return totalModifyResponseTime.get();
1044      }
1045    
1046    
1047    
1048      /**
1049       * Retrieves the total response time in milliseconds for all modify
1050       * operations processed on the associated connection.
1051       *
1052       * @return  The total response time in milliseconds for all modify operations
1053       *          processed on the associated connection.
1054       */
1055      public long getTotalModifyResponseTimeMillis()
1056      {
1057        return Math.round(totalModifyResponseTime.get() / 1000000.0d);
1058      }
1059    
1060    
1061    
1062      /**
1063       * Retrieves the average response time in nanoseconds for all modify
1064       * operations processed on the associated connection.
1065       *
1066       * @return  The average response time in nanoseconds for all modify
1067       *          operations processed on the associated connection, or
1068       *          {@code Double.NaN} if no modify operations have yet been
1069       *          performed.
1070       */
1071      public double getAverageModifyResponseTimeNanos()
1072      {
1073        final long totalTime  = totalModifyResponseTime.get();
1074        final long totalCount = numModifyResponses.get();
1075    
1076        if (totalTime > 0)
1077        {
1078          return (1.0d * totalTime / totalCount);
1079        }
1080        else
1081        {
1082          return Double.NaN;
1083        }
1084      }
1085    
1086    
1087    
1088      /**
1089       * Retrieves the average response time in milliseconds for all modify
1090       * operations processed on the associated connection.
1091       *
1092       * @return  The average response time in milliseconds for all modify
1093       *          operations processed on the associated connection, or
1094       *          {@code Double.NaN} if no modify operations have yet been
1095       *          performed.
1096       */
1097      public double getAverageModifyResponseTimeMillis()
1098      {
1099        final long totalTime  = totalModifyResponseTime.get();
1100        final long totalCount = numModifyResponses.get();
1101    
1102        if (totalTime > 0)
1103        {
1104          return (totalTime / 1000000.0d / totalCount);
1105        }
1106        else
1107        {
1108          return Double.NaN;
1109        }
1110      }
1111    
1112    
1113    
1114      /**
1115       * Retrieves the number of modify DN requests sent on the associated
1116       * connection.
1117       *
1118       * @return  The number of modify DN requests sent on the associated
1119       *          connection.
1120       */
1121      public long getNumModifyDNRequests()
1122      {
1123        return numModifyDNRequests.get();
1124      }
1125    
1126    
1127    
1128      /**
1129       * Increments the number of modify DN requests sent on the associated
1130       * connection.
1131       */
1132      void incrementNumModifyDNRequests()
1133      {
1134        numModifyDNRequests.incrementAndGet();
1135      }
1136    
1137    
1138    
1139      /**
1140       * Retrieves the number of modify DN responses sent on the associated
1141       * connection.
1142       *
1143       * @return  The number of modify DN responses sent on the associated
1144       *          connection.
1145       */
1146      public long getNumModifyDNResponses()
1147      {
1148        return numModifyDNResponses.get();
1149      }
1150    
1151    
1152    
1153      /**
1154       * Increments the number of modify DN responses sent on the associated
1155       * connection.
1156       *
1157       * @param  responseTime  The length of time in nanoseconds between sending
1158       *                       the request and receiving the response.
1159       */
1160      void incrementNumModifyDNResponses(final long responseTime)
1161      {
1162        numModifyDNResponses.incrementAndGet();
1163    
1164        if (responseTime > 0)
1165        {
1166          totalModifyDNResponseTime.addAndGet(responseTime);
1167        }
1168      }
1169    
1170    
1171    
1172      /**
1173       * Retrieves the total response time in nanoseconds for all modify DN
1174       * operations processed on the associated connection.
1175       *
1176       * @return  The total response time in nanoseconds for all modify DN
1177       *          operations processed on the associated connection.
1178       */
1179      public long getTotalModifyDNResponseTimeNanos()
1180      {
1181        return totalModifyDNResponseTime.get();
1182      }
1183    
1184    
1185    
1186      /**
1187       * Retrieves the total response time in milliseconds for all modify DN
1188       * operations processed on the associated connection.
1189       *
1190       * @return  The total response time in milliseconds for all modify DN
1191       *          operations processed on the associated connection.
1192       */
1193      public long getTotalModifyDNResponseTimeMillis()
1194      {
1195        return Math.round(totalModifyDNResponseTime.get() / 1000000.0d);
1196      }
1197    
1198    
1199    
1200      /**
1201       * Retrieves the average response time in nanoseconds for all modify DN
1202       * operations processed on the associated connection.
1203       *
1204       * @return  The average response time in nanoseconds for all modify DN
1205       *          operations processed on the associated connection, or
1206       *          {@code Double.NaN} if no modify DN operations have yet been
1207       *          performed.
1208       */
1209      public double getAverageModifyDNResponseTimeNanos()
1210      {
1211        final long totalTime  = totalModifyDNResponseTime.get();
1212        final long totalCount = numModifyDNResponses.get();
1213    
1214        if (totalTime > 0)
1215        {
1216          return (1.0d * totalTime / totalCount);
1217        }
1218        else
1219        {
1220          return Double.NaN;
1221        }
1222      }
1223    
1224    
1225    
1226      /**
1227       * Retrieves the average response time in milliseconds for all modify DN
1228       * operations processed on the associated connection.
1229       *
1230       * @return  The average response time in milliseconds for all modify DN
1231       *          operations processed on the associated connection, or
1232       *          {@code Double.NaN} if no modify DN operations have yet been
1233       *          performed.
1234       */
1235      public double getAverageModifyDNResponseTimeMillis()
1236      {
1237        final long totalTime  = totalModifyDNResponseTime.get();
1238        final long totalCount = numModifyDNResponses.get();
1239    
1240        if (totalTime > 0)
1241        {
1242          return (totalTime / 1000000.0d / totalCount);
1243        }
1244        else
1245        {
1246          return Double.NaN;
1247        }
1248      }
1249    
1250    
1251    
1252      /**
1253       * Retrieves the number of search requests sent on the associated connection.
1254       *
1255       * @return  The number of search requests sent on the associated connection.
1256       */
1257      public long getNumSearchRequests()
1258      {
1259        return numSearchRequests.get();
1260      }
1261    
1262    
1263    
1264      /**
1265       * Increments the number of search requests sent on the associated
1266       * connection.
1267       */
1268      void incrementNumSearchRequests()
1269      {
1270        numSearchRequests.incrementAndGet();
1271      }
1272    
1273    
1274    
1275      /**
1276       * Retrieves the number of search result entry responses received on the
1277       * associated connection.
1278       *
1279       * @return  The number of search result entry responses received on the
1280       *          associated connection.
1281       */
1282      public long getNumSearchEntryResponses()
1283      {
1284        return numSearchEntryResponses.get();
1285      }
1286    
1287    
1288    
1289      /**
1290       * Retrieves the number of search result reference responses received on the
1291       * associated connection.
1292       *
1293       * @return  The number of search result reference responses received on the
1294       *          associated connection.
1295       */
1296      public long getNumSearchReferenceResponses()
1297      {
1298        return numSearchReferenceResponses.get();
1299      }
1300    
1301    
1302    
1303      /**
1304       * Retrieves the number of search result done responses received on the
1305       * associated connection.
1306       *
1307       * @return  The number of search result done responses received on the
1308       *          associated connection.
1309       */
1310      public long getNumSearchDoneResponses()
1311      {
1312        return numSearchDoneResponses.get();
1313      }
1314    
1315    
1316    
1317      /**
1318       * Increments the number of search result done responses received on the
1319       * associated connection.
1320       *
1321       * @param  numEntries     The number of search result entries returned for the
1322       *                        search.
1323       * @param  numReferences  The number of search result references returned for
1324       *                        the search.
1325       * @param  responseTime   The length of time in nanoseconds between sending
1326       *                        the search request and receiving the search result
1327       *                        done response.
1328       */
1329      void incrementNumSearchResponses(final int numEntries,
1330                                       final int numReferences,
1331                                       final long responseTime)
1332      {
1333        numSearchEntryResponses.addAndGet(numEntries);
1334        numSearchReferenceResponses.addAndGet(numReferences);
1335        numSearchDoneResponses.incrementAndGet();
1336    
1337        if (responseTime > 0)
1338        {
1339          totalSearchResponseTime.addAndGet(responseTime);
1340        }
1341      }
1342    
1343    
1344    
1345      /**
1346       * Retrieves the total response time in nanoseconds for all search
1347       * operations processed on the associated connection.
1348       *
1349       * @return  The total response time in nanoseconds for all search operations
1350       *          processed on the associated connection.
1351       */
1352      public long getTotalSearchResponseTimeNanos()
1353      {
1354        return totalSearchResponseTime.get();
1355      }
1356    
1357    
1358    
1359      /**
1360       * Retrieves the total response time in milliseconds for all search
1361       * operations processed on the associated connection.
1362       *
1363       * @return  The total response time in milliseconds for all search operations
1364       *          processed on the associated connection.
1365       */
1366      public long getTotalSearchResponseTimeMillis()
1367      {
1368        return Math.round(totalSearchResponseTime.get() / 1000000.0d);
1369      }
1370    
1371    
1372    
1373      /**
1374       * Retrieves the average response time in nanoseconds for all search
1375       * operations processed on the associated connection.
1376       *
1377       * @return  The average response time in nanoseconds for all search
1378       *          operations processed on the associated connection, or
1379       *          {@code Double.NaN} if no compare operations have yet been
1380       *          performed.
1381       */
1382      public double getAverageSearchResponseTimeNanos()
1383      {
1384        final long totalTime  = totalSearchResponseTime.get();
1385        final long totalCount = numSearchDoneResponses.get();
1386    
1387        if (totalTime > 0)
1388        {
1389          return (1.0d * totalTime / totalCount);
1390        }
1391        else
1392        {
1393          return Double.NaN;
1394        }
1395      }
1396    
1397    
1398    
1399      /**
1400       * Retrieves the average response time in milliseconds for all search
1401       * operations processed on the associated connection.
1402       *
1403       * @return  The average response time in milliseconds for all search
1404       *          operations processed on the associated connection, or
1405       *          {@code Double.NaN} if no compare operations have yet been
1406       *          performed.
1407       */
1408      public double getAverageSearchResponseTimeMillis()
1409      {
1410        final long totalTime  = totalSearchResponseTime.get();
1411        final long totalCount = numSearchDoneResponses.get();
1412    
1413        if (totalTime > 0)
1414        {
1415          return (totalTime / 1000000.0d / totalCount);
1416        }
1417        else
1418        {
1419          return Double.NaN;
1420        }
1421      }
1422    
1423    
1424    
1425      /**
1426       * Retrieves the number of unbind requests sent on the associated connection.
1427       *
1428       * @return  The number of unbind requests sent on the associated connection.
1429       */
1430      public long getNumUnbindRequests()
1431      {
1432        return numUnbindRequests.get();
1433      }
1434    
1435    
1436    
1437      /**
1438       * Increments the number of unbind requests sent on the associated
1439       * connection.
1440       */
1441      void incrementNumUnbindRequests()
1442      {
1443        numUnbindRequests.incrementAndGet();
1444      }
1445    
1446    
1447    
1448      /**
1449       * Retrieves a string representation of this LDAP connection statistics
1450       * object.
1451       *
1452       * @return  A string representation of this LDAP connection statistics object.
1453       */
1454      @Override()
1455      public String toString()
1456      {
1457        final StringBuilder buffer = new StringBuilder();
1458        toString(buffer);
1459        return buffer.toString();
1460      }
1461    
1462    
1463    
1464      /**
1465       * Appends a string representation of this LDAP connection statistics object
1466       * to the provided buffer.
1467       *
1468       * @param  buffer  The buffer to which the string representation should be
1469       *                 appended.
1470       */
1471      public void toString(final StringBuilder buffer)
1472      {
1473        final long connects          = numConnects.get();
1474        final long disconnects       = numDisconnects.get();
1475        final long abandonRequests   = numAbandonRequests.get();
1476        final long addRequests       = numAddRequests.get();
1477        final long addResponses      = numAddResponses.get();
1478        final long addTimes          = totalAddResponseTime.get();
1479        final long bindRequests      = numBindRequests.get();
1480        final long bindResponses     = numBindResponses.get();
1481        final long bindTimes         = totalBindResponseTime.get();
1482        final long compareRequests   = numCompareRequests.get();
1483        final long compareResponses  = numCompareResponses.get();
1484        final long compareTimes      = totalCompareResponseTime.get();
1485        final long deleteRequests    = numDeleteRequests.get();
1486        final long deleteResponses   = numDeleteResponses.get();
1487        final long deleteTimes       = totalDeleteResponseTime.get();
1488        final long extendedRequests  = numExtendedRequests.get();
1489        final long extendedResponses = numExtendedResponses.get();
1490        final long extendedTimes     = totalExtendedResponseTime.get();
1491        final long modifyRequests    = numModifyRequests.get();
1492        final long modifyResponses   = numModifyResponses.get();
1493        final long modifyTimes       = totalModifyResponseTime.get();
1494        final long modifyDNRequests  = numModifyDNRequests.get();
1495        final long modifyDNResponses = numModifyDNResponses.get();
1496        final long modifyDNTimes     = totalModifyDNResponseTime.get();
1497        final long searchRequests    = numSearchRequests.get();
1498        final long searchEntries     = numSearchEntryResponses.get();
1499        final long searchReferences  = numSearchReferenceResponses.get();
1500        final long searchDone        = numSearchDoneResponses.get();
1501        final long searchTimes       = totalSearchResponseTime.get();
1502        final long unbindRequests    = numUnbindRequests.get();
1503    
1504        final DecimalFormat f = new DecimalFormat("0.000");
1505    
1506        buffer.append("LDAPConnectionStatistics(numConnects=");
1507        buffer.append(connects);
1508        buffer.append(", numDisconnects=");
1509        buffer.append(disconnects);
1510    
1511        buffer.append(", numAbandonRequests=");
1512        buffer.append(abandonRequests);
1513    
1514        buffer.append(", numAddRequests=");
1515        buffer.append(addRequests);
1516        buffer.append(", numAddResponses=");
1517        buffer.append(addResponses);
1518        buffer.append(", totalAddResponseTimeNanos=");
1519        buffer.append(addTimes);
1520        if (addTimes > 0L)
1521        {
1522          buffer.append(", averageAddResponseTimeNanos=");
1523          buffer.append(f.format(1.0d * addResponses / addTimes));
1524        }
1525    
1526        buffer.append(", numBindRequests=");
1527        buffer.append(bindRequests);
1528        buffer.append(", numBindResponses=");
1529        buffer.append(bindResponses);
1530        buffer.append(", totalBindResponseTimeNanos=");
1531        buffer.append(bindTimes);
1532        if (bindTimes > 0L)
1533        {
1534          buffer.append(", averageBindResponseTimeNanos=");
1535          buffer.append(f.format(1.0d * bindResponses / bindTimes));
1536        }
1537    
1538        buffer.append(", numCompareRequests=");
1539        buffer.append(compareRequests);
1540        buffer.append(", numCompareResponses=");
1541        buffer.append(compareResponses);
1542        buffer.append(", totalCompareResponseTimeNanos=");
1543        buffer.append(compareTimes);
1544        if (compareTimes > 0L)
1545        {
1546          buffer.append(", averageCompareResponseTimeNanos=");
1547          buffer.append(f.format(1.0d * compareResponses / compareTimes));
1548        }
1549    
1550        buffer.append(", numDeleteRequests=");
1551        buffer.append(deleteRequests);
1552        buffer.append(", numDeleteResponses=");
1553        buffer.append(deleteResponses);
1554        buffer.append(", totalDeleteResponseTimeNanos=");
1555        buffer.append(deleteTimes);
1556        if (deleteTimes > 0L)
1557        {
1558          buffer.append(", averageDeleteResponseTimeNanos=");
1559          buffer.append(f.format(1.0d * deleteResponses / deleteTimes));
1560        }
1561    
1562        buffer.append(", numExtendedRequests=");
1563        buffer.append(extendedRequests);
1564        buffer.append(", numExtendedResponses=");
1565        buffer.append(extendedResponses);
1566        buffer.append(", totalExtendedResponseTimeNanos=");
1567        buffer.append(extendedTimes);
1568        if (extendedTimes > 0L)
1569        {
1570          buffer.append(", averageExtendedResponseTimeNanos=");
1571          buffer.append(f.format(1.0d * extendedResponses / extendedTimes));
1572        }
1573    
1574        buffer.append(", numModifyRequests=");
1575        buffer.append(modifyRequests);
1576        buffer.append(", numModifyResponses=");
1577        buffer.append(modifyResponses);
1578        buffer.append(", totalModifyResponseTimeNanos=");
1579        buffer.append(modifyTimes);
1580        if (modifyTimes > 0L)
1581        {
1582          buffer.append(", averageModifyResponseTimeNanos=");
1583          buffer.append(f.format(1.0d * modifyResponses / modifyTimes));
1584        }
1585    
1586        buffer.append(", numModifyDNRequests=");
1587        buffer.append(modifyDNRequests);
1588        buffer.append(", numModifyDNResponses=");
1589        buffer.append(modifyDNResponses);
1590        buffer.append(", totalModifyDNResponseTimeNanos=");
1591        buffer.append(modifyDNTimes);
1592        if (modifyDNTimes > 0L)
1593        {
1594          buffer.append(", averageModifyDNResponseTimeNanos=");
1595          buffer.append(f.format(1.0d * modifyDNResponses / modifyDNTimes));
1596        }
1597    
1598        buffer.append(", numSearchRequests=");
1599        buffer.append(searchRequests);
1600        buffer.append(", numSearchEntries=");
1601        buffer.append(searchEntries);
1602        buffer.append(", numSearchReferences=");
1603        buffer.append(searchReferences);
1604        buffer.append(", numSearchDone=");
1605        buffer.append(searchDone);
1606        buffer.append(", totalSearchResponseTimeNanos=");
1607        buffer.append(searchTimes);
1608        if (searchTimes > 0L)
1609        {
1610          buffer.append(", averageSearchResponseTimeNanos=");
1611          buffer.append(f.format(1.0d * searchDone / searchTimes));
1612        }
1613    
1614        buffer.append(", numUnbindRequests=");
1615        buffer.append(unbindRequests);
1616    
1617        buffer.append(')');
1618      }
1619    }