blob: 0dcd52af19e6abf93b03adf9eeeef08ca7ff3650 [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
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -07005#include "persistent_integer.h"
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -08006
7#include <fcntl.h>
8
9#include <base/logging.h>
10#include <base/posix/eintr_wrapper.h>
11
Bertrand SIMONNETbd3505e2015-08-04 14:04:51 -070012#include "constants.h"
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -070013#include "metrics/metrics_library.h"
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080014
Luigi Semenzatoe5c7eb12014-04-16 17:05:05 -070015
16namespace chromeos_metrics {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080017
18// Static class member instantiation.
19bool PersistentInteger::testing_ = false;
20
21PersistentInteger::PersistentInteger(const std::string& name) :
22 value_(0),
23 version_(kVersion),
24 name_(name),
25 synced_(false) {
26 if (testing_) {
27 backing_file_name_ = name_;
28 } else {
Bertrand SIMONNETbd3505e2015-08-04 14:04:51 -070029 backing_file_name_ = metrics::kMetricsDirectory + name_;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080030 }
31}
32
33PersistentInteger::~PersistentInteger() {}
34
Ben Chanf05ab402014-08-07 00:54:59 -070035void PersistentInteger::Set(int64_t value) {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080036 value_ = value;
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070037 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080038}
39
Ben Chanf05ab402014-08-07 00:54:59 -070040int64_t PersistentInteger::Get() {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080041 // If not synced, then read. If the read fails, it's a good idea to write.
42 if (!synced_ && !Read())
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070043 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080044 return value_;
45}
46
Ben Chanf05ab402014-08-07 00:54:59 -070047int64_t PersistentInteger::GetAndClear() {
48 int64_t v = Get();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080049 Set(0);
50 return v;
51}
52
Ben Chanf05ab402014-08-07 00:54:59 -070053void PersistentInteger::Add(int64_t x) {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080054 Set(Get() + x);
55}
56
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070057void PersistentInteger::Write() {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080058 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(),
59 O_WRONLY | O_CREAT | O_TRUNC,
60 S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
61 PCHECK(fd >= 0) << "cannot open " << backing_file_name_ << " for writing";
62 PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
63 sizeof(version_)) &&
64 (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
65 sizeof(value_)))
66 << "cannot write to " << backing_file_name_;
67 close(fd);
68 synced_ = true;
69}
70
71bool PersistentInteger::Read() {
72 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(), O_RDONLY));
73 if (fd < 0) {
74 PLOG(WARNING) << "cannot open " << backing_file_name_ << " for reading";
75 return false;
76 }
Ben Chanf05ab402014-08-07 00:54:59 -070077 int32_t version;
78 int64_t value;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080079 bool read_succeeded = false;
80 if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
81 version == version_ &&
82 HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
83 value_ = value;
84 read_succeeded = true;
85 synced_ = true;
86 }
87 close(fd);
88 return read_succeeded;
89}
90
91void PersistentInteger::SetTestingMode(bool testing) {
92 testing_ = testing;
93}
94
95
96} // namespace chromeos_metrics