Organize Imports to be Checkstyle compliant in utils
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / ConcurrentDurationStatisticsTracker.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.util;
9
10 import com.google.common.primitives.UnsignedLong;
11 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
12 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
13
14 /**
15  * Concurrent version of {@link DurationStatisticsTracker}.
16  */
17 // TODO: once DurationStatsTracker is gone make this class final
18 class ConcurrentDurationStatisticsTracker extends DurationStatisticsTracker {
19     private static final AtomicReferenceFieldUpdater<ConcurrentDurationStatisticsTracker, DurationWithTime> LONGEST_UPDATER =
20             AtomicReferenceFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, DurationWithTime.class, "longest");
21     private static final AtomicReferenceFieldUpdater<ConcurrentDurationStatisticsTracker, DurationWithTime> SHORTEST_UPDATER =
22             AtomicReferenceFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, DurationWithTime.class, "shortest");
23     private static final AtomicLongFieldUpdater<ConcurrentDurationStatisticsTracker> COUNT_UPDATER =
24             AtomicLongFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, "count");
25     private static final AtomicLongFieldUpdater<ConcurrentDurationStatisticsTracker> SUM_UPDATER =
26             AtomicLongFieldUpdater.newUpdater(ConcurrentDurationStatisticsTracker.class, "sum");
27
28     private volatile long sum = 0;
29     private volatile long count = 0;
30     private volatile DurationWithTime longest = null;
31     private volatile DurationWithTime shortest = null;
32
33     ConcurrentDurationStatisticsTracker() {
34         // Hidden on purpose
35     }
36
37     @Override
38     public final void addDuration(final long duration) {
39         // First update the quick stats
40         SUM_UPDATER.addAndGet(this, duration);
41         COUNT_UPDATER.incrementAndGet(this);
42
43         /*
44          * Now the hairy 'min/max' things. The notion of "now" we cache,
45          * so the first time we use it, we do not call it twice. We populate
46          * it lazily, though.
47          *
48          * The longest/shortest stats both are encapsulated in an object,
49          * so we update them atomically and we minimize the number of volatile
50          * operations.
51          */
52         DurationWithTime current = shortest;
53         if (current == null || duration < current.getDuration()) {
54             final DurationWithTime newObj = new DurationWithTime(duration, System.currentTimeMillis());
55             while (!SHORTEST_UPDATER.weakCompareAndSet(this, current, newObj)) {
56                 current = shortest;
57                 if (current != null && duration >= current.getDuration()) {
58                     break;
59                 }
60             }
61         }
62
63         current = longest;
64         if (current == null || duration > current.getDuration()) {
65             final DurationWithTime newObj = new DurationWithTime(duration, System.currentTimeMillis());
66             while (!LONGEST_UPDATER.weakCompareAndSet(this, current, newObj)) {
67                 current = longest;
68                 if (current != null && duration <= current.getDuration()) {
69                     break;
70                 }
71             }
72         }
73     }
74
75     @Override
76     public final long getTotalDurations() {
77         return count;
78     }
79
80     @Override
81     public final double getAverageDuration() {
82         final long myCount = count;
83         return myCount == 0 ? 0 : UnsignedLong.fromLongBits(sum).doubleValue() / myCount;
84     }
85
86     @Override
87     public final synchronized void reset() {
88         // Synchronized is just to make sure we do not have concurrent resets :)
89         longest = null;
90         shortest = null;
91         count = 0;
92         sum = 0;
93     }
94
95     @Override
96     protected final DurationWithTime getLongest() {
97         return longest;
98     }
99
100     @Override
101     protected final DurationWithTime getShortest() {
102         return shortest;
103     }
104 }