OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef METRICS_COUNTER_H_ | 5 #ifndef METRICS_COUNTER_H_ |
6 #define METRICS_COUNTER_H_ | 6 #define METRICS_COUNTER_H_ |
7 | 7 |
| 8 #include <base/basictypes.h> |
8 #include <gtest/gtest_prod.h> // for FRIEND_TEST | 9 #include <gtest/gtest_prod.h> // for FRIEND_TEST |
9 | 10 |
10 namespace chromeos_metrics { | 11 namespace chromeos_metrics { |
11 | 12 |
12 // TaggedCounter maintains a persistent storage (i.e., a file) | 13 // TaggedCounter maintains a persistent storage (i.e., a file) |
13 // aggregation counter for a given tag (e.g., day, hour) that survives | 14 // aggregation counter for a given tag (e.g., day, hour) that survives |
14 // system shutdowns, reboots and crashes, as well as daemon process | 15 // system shutdowns, reboots and crashes, as well as daemon process |
15 // restarts. The counter object is initialized by pointing to the | 16 // restarts. The counter object is initialized by pointing to the |
16 // persistent storage file and providing a callback used for reporting | 17 // persistent storage file and providing a callback used for reporting |
17 // aggregated data. The counter can then be updated with additional | 18 // aggregated data. The counter can then be updated with additional |
18 // event counts. The aggregated count is reported through the | 19 // event counts. The aggregated count is reported through the |
19 // callback when the counter is explicitly flushed or when data for a | 20 // callback when the counter is explicitly flushed or when data for a |
20 // new tag arrives. | 21 // new tag arrives. |
| 22 // |
| 23 // The primary reason for using an interface is to allow easier unit |
| 24 // testing in clients through mocking thus avoiding file access and |
| 25 // callbacks. Of course, it also enables alternative implementations |
| 26 // of the counter with additional features. |
21 class TaggedCounterInterface { | 27 class TaggedCounterInterface { |
22 public: | 28 public: |
23 // Callback type used for reporting aggregated or flushed data. | 29 // Callback type used for reporting aggregated or flushed data. |
24 // Once this callback is invoked by the counter, the reported | 30 // Once this callback is invoked by the counter, the reported |
25 // aggregated data is discarded. Only aggregated data with positive | 31 // aggregated data is discarded. Only aggregated data with positive |
26 // counts is reported. | 32 // counts is reported. |
27 // | 33 // |
28 // |handle| is the |reporter_handle| pointer passed through Init. | 34 // |handle| is the |reporter_handle| pointer passed through Init. |
29 // |tag| is the tag associated with the aggregated count. | 35 // |tag| is the tag associated with the aggregated count. |
30 // |count| is aggregated count. | 36 // |count| is aggregated count. |
31 typedef void (*Reporter)(void* handle, int tag, int count); | 37 typedef void (*Reporter)(void* handle, int32 tag, int32 count); |
32 | 38 |
33 virtual ~TaggedCounterInterface() {} | 39 virtual ~TaggedCounterInterface() {} |
34 | 40 |
35 // Initializes the counter by providing the persistent storage | 41 // Initializes the counter by providing the persistent storage |
36 // location |filename| and a |reporter| callback for reporting | 42 // location |filename| and a |reporter| callback for reporting |
37 // aggregated counts. |reporter_handle| is sent to the |reporter| | 43 // aggregated counts. |reporter_handle| is sent to the |reporter| |
38 // along with the aggregated counts. | 44 // along with the aggregated counts. |
39 // | 45 // |
40 // NOTE: The assumption is that this object is the sole owner of the | 46 // NOTE: The assumption is that this object is the sole owner of the |
41 // persistent storage file so no locking is currently implemented. | 47 // persistent storage file so no locking is currently implemented. |
42 virtual void Init(const char* filename, | 48 virtual void Init(const char* filename, |
43 Reporter reporter, void* reporter_handle) = 0; | 49 Reporter reporter, void* reporter_handle) = 0; |
44 | 50 |
45 // Adds |count| of events for the given |tag|. If there's an | 51 // Adds |count| of events for the given |tag|. If there's an |
46 // existing aggregated count for a different tag, it's reported | 52 // existing aggregated count for a different tag, it's reported |
47 // through the reporter callback and discarded. | 53 // through the reporter callback and discarded. |
48 virtual void Update(int tag, int count) = 0; | 54 virtual void Update(int32 tag, int32 count) = 0; |
49 | 55 |
50 // Reports the current aggregated count (if any) through the | 56 // Reports the current aggregated count (if any) through the |
51 // reporter callback and discards it. | 57 // reporter callback and discards it. |
52 virtual void Flush() = 0; | 58 virtual void Flush() = 0; |
53 }; | 59 }; |
54 | 60 |
55 class TaggedCounter : public TaggedCounterInterface { | 61 class TaggedCounter : public TaggedCounterInterface { |
56 public: | 62 public: |
57 TaggedCounter(); | 63 TaggedCounter(); |
58 ~TaggedCounter(); | 64 ~TaggedCounter(); |
59 | 65 |
60 // Implementation of interface methods. | 66 // Implementation of interface methods. |
61 void Init(const char* filename, Reporter reporter, void* reporter_handle); | 67 void Init(const char* filename, Reporter reporter, void* reporter_handle); |
62 void Update(int tag, int count); | 68 void Update(int32 tag, int32 count); |
63 void Flush(); | 69 void Flush(); |
64 | 70 |
65 private: | 71 private: |
66 friend class RecordTest; | 72 friend class RecordTest; |
67 friend class TaggedCounterTest; | 73 friend class TaggedCounterTest; |
68 FRIEND_TEST(TaggedCounterTest, BadFileLocation); | 74 FRIEND_TEST(TaggedCounterTest, BadFileLocation); |
69 FRIEND_TEST(TaggedCounterTest, Flush); | 75 FRIEND_TEST(TaggedCounterTest, Flush); |
70 FRIEND_TEST(TaggedCounterTest, InitFromFile); | 76 FRIEND_TEST(TaggedCounterTest, InitFromFile); |
71 FRIEND_TEST(TaggedCounterTest, Update); | 77 FRIEND_TEST(TaggedCounterTest, Update); |
72 | 78 |
(...skipping 10 matching lines...) Expand all Loading... |
83 | 89 |
84 // Defines the tag/count record. Objects of this class are synced | 90 // Defines the tag/count record. Objects of this class are synced |
85 // with the persistent storage through binary reads/writes. | 91 // with the persistent storage through binary reads/writes. |
86 class Record { | 92 class Record { |
87 public: | 93 public: |
88 // Creates a new Record with |tag_| and |count_| reset to 0. | 94 // Creates a new Record with |tag_| and |count_| reset to 0. |
89 Record() : tag_(0), count_(0) {} | 95 Record() : tag_(0), count_(0) {} |
90 | 96 |
91 // Initializes with |tag| and |count|. If |count| is negative, | 97 // Initializes with |tag| and |count|. If |count| is negative, |
92 // |count_| is set to 0. | 98 // |count_| is set to 0. |
93 void Init(int tag, int count); | 99 void Init(int32 tag, int32 count); |
94 | 100 |
95 // Adds |count| to the current |count_|. Negative |count| is | 101 // Adds |count| to the current |count_|. Negative |count| is |
96 // ignored. In case of positive overflow, |count_| is saturated to | 102 // ignored. In case of positive overflow, |count_| is saturated to |
97 // INT_MAX. | 103 // kint32max. |
98 void Add(int count); | 104 void Add(int32 count); |
99 | 105 |
100 int tag() const { return tag_; } | 106 int32 tag() const { return tag_; } |
101 int count() const { return count_; } | 107 int32 count() const { return count_; } |
102 | 108 |
103 private: | 109 private: |
104 int tag_; | 110 int32 tag_; |
105 int count_; | 111 int32 count_; |
106 }; | 112 }; |
107 | 113 |
108 // Implementation of the Update and Flush methods. Goes through the | 114 // Implementation of the Update and Flush methods. Goes through the |
109 // necessary steps to read, report, update, and sync the aggregated | 115 // necessary steps to read, report, update, and sync the aggregated |
110 // record. | 116 // record. |
111 void UpdateInternal(int tag, int count, bool flush); | 117 void UpdateInternal(int32 tag, int32 count, bool flush); |
112 | 118 |
113 // If the current cached record is invalid, reads it from persistent | 119 // If the current cached record is invalid, reads it from persistent |
114 // storage specified through file descriptor |fd| and updates the | 120 // storage specified through file descriptor |fd| and updates the |
115 // cached record state to either null, or valid depending on the | 121 // cached record state to either null, or valid depending on the |
116 // persistent storage contents. | 122 // persistent storage contents. |
117 void ReadRecord(int fd); | 123 void ReadRecord(int fd); |
118 | 124 |
119 // If there's an existing valid record and either |flush| is true, | 125 // If there's an existing valid record and either |flush| is true, |
120 // or the new |tag| is different than the old one, reports the | 126 // or the new |tag| is different than the old one, reports the |
121 // aggregated data through the reporter callback and resets the | 127 // aggregated data through the reporter callback and resets the |
122 // cached record. | 128 // cached record. |
123 void ReportRecord(int tag, bool flush); | 129 void ReportRecord(int32 tag, bool flush); |
124 | 130 |
125 // Updates the cached record given the new |tag| and |count|. This | 131 // Updates the cached record given the new |tag| and |count|. This |
126 // method expects either a null cached record, or a valid cached | 132 // method expects either a null cached record, or a valid cached |
127 // record with the same tag as |tag|. | 133 // record with the same tag as |tag|. |
128 void UpdateRecord(int tag, int count); | 134 void UpdateRecord(int32 tag, int32 count); |
129 | 135 |
130 // If the cached record state is dirty, updates the persistent | 136 // If the cached record state is dirty, updates the persistent |
131 // storage specified through file descriptor |fd| and switches the | 137 // storage specified through file descriptor |fd| and switches the |
132 // record state to non-dirty. | 138 // record state to non-dirty. |
133 void WriteRecord(int fd); | 139 void WriteRecord(int fd); |
134 | 140 |
135 // Persistent storage file path. | 141 // Persistent storage file path. |
136 const char* filename_; | 142 const char* filename_; |
137 | 143 |
138 // Aggregated data reporter callback and handle to pass-through. | 144 // Aggregated data reporter callback and handle to pass-through. |
139 Reporter reporter_; | 145 Reporter reporter_; |
140 void* reporter_handle_; | 146 void* reporter_handle_; |
141 | 147 |
142 // Current cached aggregation record. | 148 // Current cached aggregation record. |
143 Record record_; | 149 Record record_; |
144 | 150 |
145 // Current cached aggregation record state. | 151 // Current cached aggregation record state. |
146 RecordState record_state_; | 152 RecordState record_state_; |
147 }; | 153 }; |
148 | 154 |
149 } // namespace chromeos_metrics | 155 } // namespace chromeos_metrics |
150 | 156 |
151 #endif // METRICS_COUNTER_H_ | 157 #endif // METRICS_COUNTER_H_ |
OLD | NEW |