Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(908)

Unified Diff: counter.h

Issue 2731008: Implement a persistent storage aggregation counter class. (Closed) Base URL: ssh://git@chromiumos-git/metrics.git
Patch Set: Address kmixter's comments. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Makefile ('k') | counter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: counter.h
diff --git a/counter.h b/counter.h
new file mode 100644
index 0000000000000000000000000000000000000000..aac00af730e0716950d0506083a0cdc9c5310572
--- /dev/null
+++ b/counter.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef METRICS_COUNTER_H_
+#define METRICS_COUNTER_H_
+
+#include <gtest/gtest_prod.h> // for FRIEND_TEST
+
+namespace chromeos_metrics {
+
+// TaggedCounter maintains a persistent storage (i.e., a file)
+// aggregation counter for a given tag (e.g., day, hour) that survives
+// system shutdowns, reboots and crashes, as well as daemon process
+// restarts. The counter object is initialized by pointing to the
+// persistent storage file and providing a callback used for reporting
+// aggregated data. The counter can then be updated with additional
+// event counts. The aggregated count is reported through the
+// callback when the counter is explicitly flushed or when data for a
+// new tag arrives.
+class TaggedCounterInterface {
+ public:
+ // Callback type used for reporting aggregated or flushed data.
+ // Once this callback is invoked by the counter, the reported
+ // aggregated data is discarded. Only aggregated data with positive
+ // counts is reported.
+ //
+ // |handle| is the |reporter_handle| pointer passed through Init.
+ // |tag| is the tag associated with the aggregated count.
+ // |count| is aggregated count.
+ typedef void (*Reporter)(void* handle, int tag, int count);
+
+ virtual ~TaggedCounterInterface() {}
+
+ // Initializes the counter by providing the persistent storage
+ // location |filename| and a |reporter| callback for reporting
+ // aggregated counts. |reporter_handle| is sent to the |reporter|
+ // along with the aggregated counts.
+ //
+ // NOTE: The assumption is that this object is the sole owner of the
+ // persistent storage file so no locking is currently implemented.
+ virtual void Init(const char* filename,
+ Reporter reporter, void* reporter_handle) = 0;
+
+ // Adds |count| of events for the given |tag|. If there's an
+ // existing aggregated count for a different tag, it's reported
+ // through the reporter callback and discarded.
+ virtual void Update(int tag, int count) = 0;
+
+ // Reports the current aggregated count (if any) through the
+ // reporter callback and discards it.
+ virtual void Flush() = 0;
+};
+
+class TaggedCounter : public TaggedCounterInterface {
+ public:
+ TaggedCounter();
+ ~TaggedCounter();
+
+ // Implementation of interface methods.
+ void Init(const char* filename, Reporter reporter, void* reporter_handle);
+ void Update(int tag, int count);
+ void Flush();
+
+ private:
+ friend class RecordTest;
+ friend class TaggedCounterTest;
+ FRIEND_TEST(TaggedCounterTest, BadFileLocation);
+ FRIEND_TEST(TaggedCounterTest, Flush);
+ FRIEND_TEST(TaggedCounterTest, InitFromFile);
+ FRIEND_TEST(TaggedCounterTest, Update);
+
+ // The current tag/count record is cached by the counter object to
+ // avoid potentially unnecessary I/O. The cached record can be in
+ // one of the following states:
+ enum RecordState {
+ kRecordInvalid, // Invalid record, sync from persistent storage needed.
+ kRecordNull, // No current record, persistent storage synced.
+ kRecordNullDirty, // No current record, persistent storage is invalid.
+ kRecordValid, // Current record valid, persistent storage synced.
+ kRecordValidDirty // Current record valid, persistent storage is invalid.
+ };
+
+ // Defines the tag/count record. Objects of this class are synced
+ // with the persistent storage through binary reads/writes.
+ class Record {
+ public:
+ // Creates a new Record with |tag_| and |count_| reset to 0.
+ Record() : tag_(0), count_(0) {}
+
+ // Initializes with |tag| and |count|. If |count| is negative,
+ // |count_| is set to 0.
+ void Init(int tag, int count);
+
+ // Adds |count| to the current |count_|. Negative |count| is
+ // ignored. In case of positive overflow, |count_| is saturated to
+ // INT_MAX.
+ void Add(int count);
+
+ int tag() const { return tag_; }
+ int count() const { return count_; }
+
+ private:
+ int tag_;
+ int count_;
+ };
+
+ // Implementation of the Update and Flush methods. Goes through the
+ // necessary steps to read, report, update, and sync the aggregated
+ // record.
+ void UpdateInternal(int tag, int count, bool flush);
+
+ // If the current cached record is invalid, reads it from persistent
+ // storage specified through file descriptor |fd| and updates the
+ // cached record state to either null, or valid depending on the
+ // persistent storage contents.
+ void ReadRecord(int fd);
+
+ // If there's an existing valid record and either |flush| is true,
+ // or the new |tag| is different than the old one, reports the
+ // aggregated data through the reporter callback and resets the
+ // cached record.
+ void ReportRecord(int tag, bool flush);
+
+ // Updates the cached record given the new |tag| and |count|. This
+ // method expects either a null cached record, or a valid cached
+ // record with the same tag as |tag|.
+ void UpdateRecord(int tag, int count);
+
+ // If the cached record state is dirty, updates the persistent
+ // storage specified through file descriptor |fd| and switches the
+ // record state to non-dirty.
+ void WriteRecord(int fd);
+
+ // Persistent storage file path.
+ const char* filename_;
+
+ // Aggregated data reporter callback and handle to pass-through.
+ Reporter reporter_;
+ void* reporter_handle_;
+
+ // Current cached aggregation record.
+ Record record_;
+
+ // Current cached aggregation record state.
+ RecordState record_state_;
+};
+
+} // namespace chromeos_metrics
+
+#endif // METRICS_COUNTER_H_
« no previous file with comments | « Makefile ('k') | counter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698