152e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET/*
252e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * Copyright (C) 2015 The Android Open Source Project
352e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET *
452e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * Licensed under the Apache License, Version 2.0 (the "License");
552e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * you may not use this file except in compliance with the License.
652e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * You may obtain a copy of the License at
752e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET *
852e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET *      http://www.apache.org/licenses/LICENSE-2.0
952e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET *
1052e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * Unless required by applicable law or agreed to in writing, software
1152e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * distributed under the License is distributed on an "AS IS" BASIS,
1252e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1352e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * See the License for the specific language governing permissions and
1452e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * limitations under the License.
1552e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET */
162fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
174b915ae1b226889da266c480c1ce90f6dd9f86b9Bertrand SIMONNET#include "persistent_integer.h"
182fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
192fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include <fcntl.h>
202fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
212fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include <base/logging.h>
222fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato#include <base/posix/eintr_wrapper.h>
232fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
24bd3505e634cf8f6a8cb95f2b352670a0890c06f2Bertrand SIMONNET#include "constants.h"
252fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
26e5c7eb1d1399f3c6c7fb566aab0ff3de47471ce8Luigi Semenzatonamespace chromeos_metrics {
272fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
28a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNETPersistentInteger::PersistentInteger(const std::string& name,
29a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET                                     const base::FilePath& directory)
30a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET    : value_(0),
312fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      version_(kVersion),
322fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      name_(name),
33a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET      backing_file_path_(directory.Append(name_)),
34a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET      synced_(false) {}
352fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
362fd51cc42dddba7568baec97f6b3701e2a77253bLuigi SemenzatoPersistentInteger::~PersistentInteger() {}
372fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
38f05ab40ab949c1052d1d443f841416f1480924e4Ben Chanvoid PersistentInteger::Set(int64_t value) {
392fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  value_ = value;
40a5f4fe6b98ae5d214ecbe6a946d77240b9446409Luigi Semenzato  Write();
412fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
422fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
43f05ab40ab949c1052d1d443f841416f1480924e4Ben Chanint64_t PersistentInteger::Get() {
442fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  // If not synced, then read.  If the read fails, it's a good idea to write.
452fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (!synced_ && !Read())
46a5f4fe6b98ae5d214ecbe6a946d77240b9446409Luigi Semenzato    Write();
472fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  return value_;
482fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
492fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
50f05ab40ab949c1052d1d443f841416f1480924e4Ben Chanint64_t PersistentInteger::GetAndClear() {
51f05ab40ab949c1052d1d443f841416f1480924e4Ben Chan  int64_t v = Get();
522fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  Set(0);
532fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  return v;
542fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
552fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
56f05ab40ab949c1052d1d443f841416f1480924e4Ben Chanvoid PersistentInteger::Add(int64_t x) {
572fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  Set(Get() + x);
582fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
592fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
60a5f4fe6b98ae5d214ecbe6a946d77240b9446409Luigi Semenzatovoid PersistentInteger::Write() {
61a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET  int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(),
622fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato                             O_WRONLY | O_CREAT | O_TRUNC,
632fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato                             S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
64a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET  PCHECK(fd >= 0) << "cannot open " << backing_file_path_.value()
65a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET                  << " for writing";
662fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
672fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato          sizeof(version_)) &&
682fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato         (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
692fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato          sizeof(value_)))
70a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET      << "cannot write to " << backing_file_path_.value();
712fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  close(fd);
722fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  synced_ = true;
732fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
742fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
752fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzatobool PersistentInteger::Read() {
76a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET  int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(), O_RDONLY));
772fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (fd < 0) {
78a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET    PLOG(WARNING) << "cannot open " << backing_file_path_.value()
79a7bc1c14df9993fc2ae0ec6258e513b8371dd910Bertrand SIMONNET                  << " for reading";
802fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    return false;
812fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  }
82f05ab40ab949c1052d1d443f841416f1480924e4Ben Chan  int32_t version;
83f05ab40ab949c1052d1d443f841416f1480924e4Ben Chan  int64_t value;
842fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  bool read_succeeded = false;
852fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
862fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      version == version_ &&
872fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato      HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
882fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    value_ = value;
892fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    read_succeeded = true;
902fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato    synced_ = true;
912fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  }
922fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  close(fd);
932fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato  return read_succeeded;
942fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}
952fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato
962fd51cc42dddba7568baec97f6b3701e2a77253bLuigi Semenzato}  // namespace chromeos_metrics
97