2015-08-11 00:18:00 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2014-02-26 20:53:16 +01:00
|
|
|
|
2015-07-29 00:38:14 +02:00
|
|
|
#include "persistent_integer.h"
|
2014-02-26 20:53:16 +01:00
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include <base/logging.h>
|
|
|
|
#include <base/posix/eintr_wrapper.h>
|
|
|
|
|
2015-08-04 23:04:51 +02:00
|
|
|
#include "constants.h"
|
2014-02-26 20:53:16 +01:00
|
|
|
|
2014-04-17 02:05:05 +02:00
|
|
|
namespace chromeos_metrics {
|
2014-02-26 20:53:16 +01:00
|
|
|
|
2015-11-25 22:29:48 +01:00
|
|
|
PersistentInteger::PersistentInteger(const std::string& name,
|
|
|
|
const base::FilePath& directory)
|
|
|
|
: value_(0),
|
2014-02-26 20:53:16 +01:00
|
|
|
version_(kVersion),
|
|
|
|
name_(name),
|
2015-11-25 22:29:48 +01:00
|
|
|
backing_file_path_(directory.Append(name_)),
|
|
|
|
synced_(false) {}
|
2014-02-26 20:53:16 +01:00
|
|
|
|
|
|
|
PersistentInteger::~PersistentInteger() {}
|
|
|
|
|
2014-08-07 09:54:59 +02:00
|
|
|
void PersistentInteger::Set(int64_t value) {
|
2014-02-26 20:53:16 +01:00
|
|
|
value_ = value;
|
2014-04-15 18:31:47 +02:00
|
|
|
Write();
|
2014-02-26 20:53:16 +01:00
|
|
|
}
|
|
|
|
|
2014-08-07 09:54:59 +02:00
|
|
|
int64_t PersistentInteger::Get() {
|
2014-02-26 20:53:16 +01:00
|
|
|
// If not synced, then read. If the read fails, it's a good idea to write.
|
|
|
|
if (!synced_ && !Read())
|
2014-04-15 18:31:47 +02:00
|
|
|
Write();
|
2014-02-26 20:53:16 +01:00
|
|
|
return value_;
|
|
|
|
}
|
|
|
|
|
2014-08-07 09:54:59 +02:00
|
|
|
int64_t PersistentInteger::GetAndClear() {
|
|
|
|
int64_t v = Get();
|
2014-02-26 20:53:16 +01:00
|
|
|
Set(0);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2014-08-07 09:54:59 +02:00
|
|
|
void PersistentInteger::Add(int64_t x) {
|
2014-02-26 20:53:16 +01:00
|
|
|
Set(Get() + x);
|
|
|
|
}
|
|
|
|
|
2014-04-15 18:31:47 +02:00
|
|
|
void PersistentInteger::Write() {
|
2015-11-25 22:29:48 +01:00
|
|
|
int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(),
|
2014-02-26 20:53:16 +01:00
|
|
|
O_WRONLY | O_CREAT | O_TRUNC,
|
|
|
|
S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
|
2015-11-25 22:29:48 +01:00
|
|
|
PCHECK(fd >= 0) << "cannot open " << backing_file_path_.value()
|
|
|
|
<< " for writing";
|
2014-02-26 20:53:16 +01:00
|
|
|
PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
|
|
|
|
sizeof(version_)) &&
|
|
|
|
(HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
|
|
|
|
sizeof(value_)))
|
2015-11-25 22:29:48 +01:00
|
|
|
<< "cannot write to " << backing_file_path_.value();
|
2014-02-26 20:53:16 +01:00
|
|
|
close(fd);
|
|
|
|
synced_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PersistentInteger::Read() {
|
2015-11-25 22:29:48 +01:00
|
|
|
int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(), O_RDONLY));
|
2014-02-26 20:53:16 +01:00
|
|
|
if (fd < 0) {
|
2015-11-25 22:29:48 +01:00
|
|
|
PLOG(WARNING) << "cannot open " << backing_file_path_.value()
|
|
|
|
<< " for reading";
|
2014-02-26 20:53:16 +01:00
|
|
|
return false;
|
|
|
|
}
|
2014-08-07 09:54:59 +02:00
|
|
|
int32_t version;
|
|
|
|
int64_t value;
|
2014-02-26 20:53:16 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace chromeos_metrics
|