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