blob: ae97b76ad6ed6945784db81cbe1290e2a5ec49ba [file] [log] [blame]
toma7083182014-09-25 21:38:03 -07001package org.onlab.util;
2
3import java.util.Objects;
4
5import static com.google.common.base.MoreObjects.toStringHelper;
6import static com.google.common.base.Preconditions.checkArgument;
7
8/**
9 * Counting mechanism capable of tracking occurrences and rates.
10 */
11public class Counter {
12
13 private long total = 0;
14 private long start = System.currentTimeMillis();
15 private long end = 0;
16
17 /**
18 * Creates a new counter.
19 */
20 public Counter() {
21 }
22
23 /**
24 * Creates a new counter in a specific state. If non-zero end time is
25 * specified, the counter will be frozen.
26 *
27 * @param start start time
28 * @param total total number of items to start with
29 * @param end end time; if non-ze
30 */
31 public Counter(long start, long total, long end) {
32 checkArgument(start <= end, "Malformed interval: start > end");
33 checkArgument(total >= 0, "Total must be non-negative");
34 this.start = start;
35 this.total = total;
36 this.end = end;
37 }
38
39 /**
40 * Resets the counter, by zeroing out the count and restarting the timer.
41 */
42 public synchronized void reset() {
43 end = 0;
44 total = 0;
45 start = System.currentTimeMillis();
46 }
47
48 /**
49 * Freezes the counter in the current state including the counts and times.
50 */
51 public synchronized void freeze() {
52 end = System.currentTimeMillis();
53 }
54
55 /**
56 * Adds the specified number of occurrences to the counter. No-op if the
57 * counter has been frozen.
58 *
59 * @param count number of occurrences
60 */
61 public synchronized void add(long count) {
62 checkArgument(count >= 0, "Count must be non-negative");
63 if (end == 0L) {
64 total += count;
65 }
66 }
67
68 /**
69 * Returns the number of occurrences per second.
70 *
71 * @return throughput in occurrences per second
72 */
73 public synchronized double throughput() {
74 return total / duration();
75 }
76
77 /**
78 * Returns the total number of occurrences counted.
79 *
80 * @return number of counted occurrences
81 */
82 public synchronized long total() {
83 return total;
84 }
85
86 /**
87 * Returns the duration expressed in fractional number of seconds.
88 *
89 * @return fractional number of seconds since the last reset
90 */
91 public synchronized double duration() {
92 // Protect against 0 return by artificially setting duration to 1ms
93 long duration = (end == 0L ? System.currentTimeMillis() : end) - start;
94 return (duration == 0 ? 1 : duration) / 1000.0;
95 }
96
97 @Override
98 public int hashCode() {
99 return Objects.hash(total, start, end);
100 }
101
102 @Override
103 public boolean equals(Object obj) {
104 if (this == obj) {
105 return true;
106 }
107 if (obj instanceof Counter) {
108 final Counter other = (Counter) obj;
109 return Objects.equals(this.total, other.total) &&
110 Objects.equals(this.start, other.start) &&
111 Objects.equals(this.end, other.end);
112 }
113 return false;
114 }
115
116 @Override
117 public String toString() {
118 return toStringHelper(this)
119 .add("total", total)
120 .add("start", start)
121 .add("end", end)
122 .toString();
123 }
124}