blob: e849f0022343293736beccb8a296c4a81e05f455 [file] [log] [blame]
Bertrand SIMONNET52e5b992015-08-10 15:18:00 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080016
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -070017#include "persistent_integer.h"
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080018
19#include <fcntl.h>
20
21#include <base/logging.h>
22#include <base/posix/eintr_wrapper.h>
23
Bertrand SIMONNETbd3505e2015-08-04 14:04:51 -070024#include "constants.h"
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -070025#include "metrics/metrics_library.h"
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080026
Luigi Semenzatoe5c7eb12014-04-16 17:05:05 -070027
28namespace chromeos_metrics {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080029
30// Static class member instantiation.
Bertrand SIMONNET12531862015-08-31 11:11:57 -070031std::string PersistentInteger::metrics_directory_ = metrics::kMetricsDirectory;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080032
33PersistentInteger::PersistentInteger(const std::string& name) :
34 value_(0),
35 version_(kVersion),
36 name_(name),
37 synced_(false) {
Bertrand SIMONNET12531862015-08-31 11:11:57 -070038 backing_file_name_ = metrics_directory_ + name_;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080039}
40
41PersistentInteger::~PersistentInteger() {}
42
Ben Chanf05ab402014-08-07 00:54:59 -070043void PersistentInteger::Set(int64_t value) {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080044 value_ = value;
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070045 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080046}
47
Ben Chanf05ab402014-08-07 00:54:59 -070048int64_t PersistentInteger::Get() {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080049 // If not synced, then read. If the read fails, it's a good idea to write.
50 if (!synced_ && !Read())
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070051 Write();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080052 return value_;
53}
54
Ben Chanf05ab402014-08-07 00:54:59 -070055int64_t PersistentInteger::GetAndClear() {
56 int64_t v = Get();
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080057 Set(0);
58 return v;
59}
60
Ben Chanf05ab402014-08-07 00:54:59 -070061void PersistentInteger::Add(int64_t x) {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080062 Set(Get() + x);
63}
64
Luigi Semenzatoa5f4fe62014-04-15 09:31:47 -070065void PersistentInteger::Write() {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080066 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(),
67 O_WRONLY | O_CREAT | O_TRUNC,
68 S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
69 PCHECK(fd >= 0) << "cannot open " << backing_file_name_ << " for writing";
70 PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
71 sizeof(version_)) &&
72 (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
73 sizeof(value_)))
74 << "cannot write to " << backing_file_name_;
75 close(fd);
76 synced_ = true;
77}
78
79bool PersistentInteger::Read() {
80 int fd = HANDLE_EINTR(open(backing_file_name_.c_str(), O_RDONLY));
81 if (fd < 0) {
82 PLOG(WARNING) << "cannot open " << backing_file_name_ << " for reading";
83 return false;
84 }
Ben Chanf05ab402014-08-07 00:54:59 -070085 int32_t version;
86 int64_t value;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080087 bool read_succeeded = false;
88 if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
89 version == version_ &&
90 HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
91 value_ = value;
92 read_succeeded = true;
93 synced_ = true;
94 }
95 close(fd);
96 return read_succeeded;
97}
98
Bertrand SIMONNET12531862015-08-31 11:11:57 -070099void PersistentInteger::SetMetricsDirectory(const std::string& directory) {
100 metrics_directory_ = directory;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800101}
102
103
104} // namespace chromeos_metrics