metrics: refactor counters
The metrics daemon had counter classes that represented
persistent, tagged values, and UMA stats. To create some
derived UMA stats we need to separate persistency and UMA stats,
and the tagging doesn't help either.
This rewrite is supposed to keep the same functionality.
BUG=chromium:339588
TEST=ran and checked a few histograms
BRANCH=none
Change-Id: Ia1121ab2db391d71edffab9f52afe29ce17686ba
Reviewed-on: https://chromium-review.googlesource.com/188082
Tested-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Commit-Queue: Luigi Semenzato <semenzato@chromium.org>
diff --git a/metrics/persistent_integer.cc b/metrics/persistent_integer.cc
new file mode 100644
index 0000000..c6ccf0e
--- /dev/null
+++ b/metrics/persistent_integer.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2014 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.
+
+#include "persistent_integer.h"
+
+#include <fcntl.h>
+
+#include <base/logging.h>
+#include <base/posix/eintr_wrapper.h>
+
+#include "metrics_library.h"
+
+namespace chromeos_metrics {
+
+// The directory for the persistent storage.
+const char* const kBackingFilesDirectory = "/var/log/metrics/";
+
+// Static class member instantiation.
+bool PersistentInteger::testing_ = false;
+
+PersistentInteger::PersistentInteger(const std::string& name) :
+ value_(0),
+ version_(kVersion),
+ name_(name),
+ synced_(false) {
+ if (testing_) {
+ backing_file_name_ = name_;
+ } else {
+ backing_file_name_ = kBackingFilesDirectory + name_;
+ }
+}
+
+PersistentInteger::~PersistentInteger() {}
+
+void PersistentInteger::Set(int64 value) {
+ value_ = value;
+ Write(value);
+}
+
+int64 PersistentInteger::Get() {
+ // If not synced, then read. If the read fails, it's a good idea to write.
+ if (!synced_ && !Read())
+ Write(value_);
+ return value_;
+}
+
+int64 PersistentInteger::GetAndClear() {
+ int64 v = Get();
+ Set(0);
+ return v;
+}
+
+void PersistentInteger::Add(int64 x) {
+ Set(Get() + x);
+}
+
+void PersistentInteger::Write(int64 value) {
+ int fd = HANDLE_EINTR(open(backing_file_name_.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
+ PCHECK(fd >= 0) << "cannot open " << backing_file_name_ << " for writing";
+ PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
+ sizeof(version_)) &&
+ (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
+ sizeof(value_)))
+ << "cannot write to " << backing_file_name_;
+ close(fd);
+ synced_ = true;
+}
+
+bool PersistentInteger::Read() {
+ int fd = HANDLE_EINTR(open(backing_file_name_.c_str(), O_RDONLY));
+ if (fd < 0) {
+ PLOG(WARNING) << "cannot open " << backing_file_name_ << " for reading";
+ return false;
+ }
+ int32 version;
+ int64 value;
+ bool read_succeeded = false;
+ if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
+ version == version_ &&
+ HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
+ value_ = value;
+ read_succeeded = true;
+ synced_ = true;
+ }
+ close(fd);
+ return read_succeeded;
+}
+
+void PersistentInteger::SetTestingMode(bool testing) {
+ testing_ = testing;
+}
+
+
+} // namespace chromeos_metrics