blob: 658c9d3918c692d0e6c8233678c338ab4d2c317f [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
14namespace chromeos_metrics {
15
16// The directory for the persistent storage.
17const char* const kBackingFilesDirectory = "/var/log/metrics/";
18
19// Static class member instantiation.
20bool PersistentInteger::testing_ = false;
21
22PersistentInteger::PersistentInteger(const std::string& name) :
23 value_(0),
24 version_(kVersion),
25 name_(name),
26 synced_(false) {
27 if (testing_) {
28 backing_file_name_ = name_;
29 } else {
30 backing_file_name_ = kBackingFilesDirectory + name_;
31 }
32}
33
34PersistentInteger::~PersistentInteger() {}
35
36void PersistentInteger::Set(int64 value) {
37 value_ = value;
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070038 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080039}
40
41int64 PersistentInteger::Get() {
42 // If not synced, then read. If the read fails, it's a good idea to write.
43 if (!synced_ && !Read())
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070044 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080045 return value_;
46}
47
48int64 PersistentInteger::GetAndClear() {
49 int64 v = Get();
50 Set(0);
51 return v;
52}
53
54void PersistentInteger::Add(int64 x) {
55 Set(Get() + x);
56}
57
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070058void PersistentInteger::Write() {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080059 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(),
60 O_WRONLY | O_CREAT | O_TRUNC,
61 S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
62 PCHECK(fd >= 0) << "cannot open " << backing_file_name_ << " for writing";
63 PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
64 sizeof(version_)) &&
65 (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
66 sizeof(value_)))
67 << "cannot write to " << backing_file_name_;
68 close(fd);
69 synced_ = true;
70}
71
72bool PersistentInteger::Read() {
73 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(), O_RDONLY));
74 if (fd < 0) {
75 PLOG(WARNING) << "cannot open " << backing_file_name_ << " for reading";
76 return false;
77 }
78 int32 version;
79 int64 value;
80 bool read_succeeded = false;
81 if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
82 version == version_ &&
83 HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
84 value_ = value;
85 read_succeeded = true;
86 synced_ = true;
87 }
88 close(fd);
89 return read_succeeded;
90}
91
92void PersistentInteger::SetTestingMode(bool testing) {
93 testing_ = testing;
94}
95
96
97} // namespace chromeos_metrics