persistent_integer.cc revision 2fd51cc42dddba7568baec97f6b3701e2a77253b
12fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
22fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato// Use of this source code is governed by a BSD-style license that can be
32fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato// found in the LICENSE file.
42fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
52fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include "persistent_integer.h"
62fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
72fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include <fcntl.h>
82fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
92fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include <base/logging.h>
102fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include <base/posix/eintr_wrapper.h>
112fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
122fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include "metrics_library.h"
132fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
142fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatonamespace chromeos_metrics {
152fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
162fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato// The directory for the persistent storage.
172fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatoconst char* const kBackingFilesDirectory = "/var/log/metrics/";
182fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
192fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato// Static class member instantiation.
202fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatobool PersistentInteger::testing_ = false;
212fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
222fd51cc42dddba7568baec97f6b3701e2a77253bLuigi SemenzatoPersistentInteger::PersistentInteger(const std::string& name) :
232fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      value_(0),
242fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      version_(kVersion),
252fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      name_(name),
262fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      synced_(false) {
272fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (testing_) {
282fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    backing_file_name_ = name_;
292fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  } else {
302fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    backing_file_name_ = kBackingFilesDirectory + name_;
312fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  }
322fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
332fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
342fd51cc42dddba7568baec97f6b3701e2a77253bLuigi SemenzatoPersistentInteger::~PersistentInteger() {}
352fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
362fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatovoid PersistentInteger::Set(int64 value) {
372fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  value_ = value;
382fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  Write(value);
392fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
402fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
412fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatoint64 PersistentInteger::Get() {
422fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  // If not synced, then read.  If the read fails, it's a good idea to write.
432fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (!synced_ && !Read())
442fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    Write(value_);
452fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  return value_;
462fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
472fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
482fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatoint64 PersistentInteger::GetAndClear() {
492fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  int64 v = Get();
502fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  Set(0);
512fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  return v;
522fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
532fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
542fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatovoid PersistentInteger::Add(int64 x) {
552fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  Set(Get() + x);
562fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
572fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
582fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatovoid PersistentInteger::Write(int64 value) {
592fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  int fd = HANDLE_EINTR(open(backing_file_name_.c_str(),
602fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato                             O_WRONLY | O_CREAT | O_TRUNC,
612fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato                             S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
622fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  PCHECK(fd >= 0) << "cannot open " << backing_file_name_ << " for writing";
632fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
642fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato          sizeof(version_)) &&
652fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato         (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
662fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato          sizeof(value_)))
672fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      << "cannot write to " << backing_file_name_;
682fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  close(fd);
692fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  synced_ = true;
702fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
712fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
722fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatobool PersistentInteger::Read() {
732fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  int fd = HANDLE_EINTR(open(backing_file_name_.c_str(), O_RDONLY));
742fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (fd < 0) {
752fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    PLOG(WARNING) << "cannot open " << backing_file_name_ << " for reading";
762fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    return false;
772fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  }
782fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  int32 version;
792fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  int64 value;
802fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  bool read_succeeded = false;
812fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
822fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      version == version_ &&
832fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
842fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    value_ = value;
852fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    read_succeeded = true;
862fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    synced_ = true;
872fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  }
882fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  close(fd);
892fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  return read_succeeded;
902fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
912fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
922fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatovoid PersistentInteger::SetTestingMode(bool testing) {
932fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  testing_ = testing;
942fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
952fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
962fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
972fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}  // namespace chromeos_metrics
98