blob: d4ef8b216524957871822b3849853a45b6048a0b [file] [log] [blame]
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -08001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "persistent_integer.h"
6
7#include <fcntl.h>
8
9#include <base/logging.h>
10#include <base/posix/eintr_wrapper.h>
11
12#include "metrics_library.h"
13
Luigi Semenzatoe5c7eb12014-04-16 17:05:05 -070014namespace {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080015
16// The directory for the persistent storage.
Luigi Semenzatoe5c7eb12014-04-16 17:05:05 -070017const char kBackingFilesDirectory[] = "/var/lib/metrics/";
18
19}
20
21namespace chromeos_metrics {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080022
23// Static class member instantiation.
24bool PersistentInteger::testing_ = false;
25
26PersistentInteger::PersistentInteger(const std::string& name) :
27 value_(0),
28 version_(kVersion),
29 name_(name),
30 synced_(false) {
31 if (testing_) {
32 backing_file_name_ = name_;
33 } else {
34 backing_file_name_ = kBackingFilesDirectory + name_;
35 }
36}
37
38PersistentInteger::~PersistentInteger() {}
39
40void PersistentInteger::Set(int64 value) {
41 value_ = value;
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070042 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080043}
44
45int64 PersistentInteger::Get() {
46 // If not synced, then read. If the read fails, it's a good idea to write.
47 if (!synced_ && !Read())
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070048 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080049 return value_;
50}
51
52int64 PersistentInteger::GetAndClear() {
53 int64 v = Get();
54 Set(0);
55 return v;
56}
57
58void PersistentInteger::Add(int64 x) {
59 Set(Get() + x);
60}
61
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070062void PersistentInteger::Write() {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080063 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(),
64 O_WRONLY | O_CREAT | O_TRUNC,
65 S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
66 PCHECK(fd >= 0) << "cannot open " << backing_file_name_ << " for writing";
67 PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
68 sizeof(version_)) &&
69 (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
70 sizeof(value_)))
71 << "cannot write to " << backing_file_name_;
72 close(fd);
73 synced_ = true;
74}
75
76bool PersistentInteger::Read() {
77 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(), O_RDONLY));
78 if (fd < 0) {
79 PLOG(WARNING) << "cannot open " << backing_file_name_ << " for reading";
80 return false;
81 }
82 int32 version;
83 int64 value;
84 bool read_succeeded = false;
85 if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
86 version == version_ &&
87 HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
88 value_ = value;
89 read_succeeded = true;
90 synced_ = true;
91 }
92 close(fd);
93 return read_succeeded;
94}
95
96void PersistentInteger::SetTestingMode(bool testing) {
97 testing_ = testing;
98}
99
100
101} // namespace chromeos_metrics