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