1/* 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 */ 16 17#include "persistent_integer.h" 18 19#include <fcntl.h> 20 21#include <base/logging.h> 22#include <base/posix/eintr_wrapper.h> 23 24#include "constants.h" 25 26namespace chromeos_metrics { 27 28PersistentInteger::PersistentInteger(const std::string& name, 29 const base::FilePath& directory) 30 : value_(0), 31 version_(kVersion), 32 name_(name), 33 backing_file_path_(directory.Append(name_)), 34 synced_(false) {} 35 36PersistentInteger::~PersistentInteger() {} 37 38void PersistentInteger::Set(int64_t value) { 39 value_ = value; 40 Write(); 41} 42 43int64_t PersistentInteger::Get() { 44 // If not synced, then read. If the read fails, it's a good idea to write. 45 if (!synced_ && !Read()) 46 Write(); 47 return value_; 48} 49 50int64_t PersistentInteger::GetAndClear() { 51 int64_t v = Get(); 52 Set(0); 53 return v; 54} 55 56void PersistentInteger::Add(int64_t x) { 57 Set(Get() + x); 58} 59 60void PersistentInteger::Write() { 61 int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(), 62 O_WRONLY | O_CREAT | O_TRUNC, 63 S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)); 64 PCHECK(fd >= 0) << "cannot open " << backing_file_path_.value() 65 << " for writing"; 66 PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) == 67 sizeof(version_)) && 68 (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) == 69 sizeof(value_))) 70 << "cannot write to " << backing_file_path_.value(); 71 close(fd); 72 synced_ = true; 73} 74 75bool PersistentInteger::Read() { 76 int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(), O_RDONLY)); 77 if (fd < 0) { 78 PLOG(WARNING) << "cannot open " << backing_file_path_.value() 79 << " for reading"; 80 return false; 81 } 82 int32_t version; 83 int64_t value; 84 bool read_succeeded = false; 85 if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) && 86 version == version_ && 87 HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) { 88 value_ = value; 89 read_succeeded = true; 90 synced_ = true; 91 } 92 close(fd); 93 return read_succeeded; 94} 95 96} // namespace chromeos_metrics 97