From 84fda19c835219a320e79680acef059c3ebc2621 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Thu, 24 Mar 2016 16:26:20 -0700 Subject: bootstat: Handle v1 record files which do not contain file contents. Bug: 27836969 Change-Id: I18fcdab7ca32d00af3f8827f42d47868492ed719 --- bootstat/boot_event_record_store.cpp | 7 +++-- bootstat/boot_event_record_store.h | 1 + bootstat/boot_event_record_store_test.cpp | 51 ++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 3 deletions(-) (limited to 'bootstat') diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp index 5d1fae90b..ef4f68ec0 100644 --- a/bootstat/boot_event_record_store.cpp +++ b/bootstat/boot_event_record_store.cpp @@ -55,8 +55,11 @@ bool ParseRecordEventTime(const std::string& path, int32_t* uptime) { return false; } - int32_t value = std::stoi(content); - bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime); + // Ignore existing bootstat records (which do not contain file content). + if (!content.empty()) { + int32_t value = std::stoi(content); + bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime); + } return true; } diff --git a/bootstat/boot_event_record_store.h b/bootstat/boot_event_record_store.h index 4d5deee51..a2b83184e 100644 --- a/bootstat/boot_event_record_store.h +++ b/bootstat/boot_event_record_store.h @@ -55,6 +55,7 @@ class BootEventRecordStore { FRIEND_TEST(BootEventRecordStoreTest, AddMultipleBootEvents); FRIEND_TEST(BootEventRecordStoreTest, AddBootEventWithValue); FRIEND_TEST(BootEventRecordStoreTest, GetBootEvent); + FRIEND_TEST(BootEventRecordStoreTest, GetBootEventNoFileContent); // Sets the filesystem path of the record store. void SetStorePath(const std::string& path); diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp index 343f9d00b..d4f075590 100644 --- a/bootstat/boot_event_record_store_test.cpp +++ b/bootstat/boot_event_record_store_test.cpp @@ -17,12 +17,16 @@ #include "boot_event_record_store.h" #include +#include #include #include #include #include +#include #include +#include #include +#include #include #include #include "uptime_parser.h" @@ -31,6 +35,36 @@ using testing::UnorderedElementsAreArray; namespace { +// Creates a fake boot event record file at |record_path| containing the boot +// record |value|. This method is necessary as truncating a +// BootEventRecordStore-created file would modify the mtime, which would alter +// the value of the record. +bool CreateEmptyBootEventRecord(const std::string& record_path, int32_t value) { + android::base::unique_fd record_fd(creat(record_path.c_str(), S_IRUSR | S_IWUSR)); + if (record_fd.get() == -1) { + return false; + } + + // Writing the value as content in the record file is a debug measure to + // ensure the validity of the file mtime value, i.e., to check that the record + // file mtime values are not changed once set. + // TODO(jhawkins): Remove this block. + if (!android::base::WriteStringToFd(std::to_string(value), record_fd.get())) { + return false; + } + + // Set the |mtime| of the file to store the value of the boot event while + // preserving the |atime|. + struct timespec atime = {/* tv_sec */ 0, /* tv_usec */ UTIME_OMIT}; + struct timespec mtime = {/* tv_sec */ value, /* tv_usec */ 0}; + const struct timespec times[] = {atime, mtime}; + if (futimens(record_fd.get(), times) != 0) { + return false; + } + + return true; +} + // Returns true if the time difference between |a| and |b| is no larger // than 10 seconds. This allow for a relatively large fuzz when comparing // two timestamps taken back-to-back. @@ -178,4 +212,19 @@ TEST_F(BootEventRecordStoreTest, GetBootEvent) { // Null |record|. EXPECT_DEATH(store.GetBootEvent("carboniferous", nullptr), std::string()); -} \ No newline at end of file +} + +// Tests that the BootEventRecordStore is capable of handling an older record +// protocol which does not contain file contents. +TEST_F(BootEventRecordStoreTest, GetBootEventNoFileContent) { + BootEventRecordStore store; + store.SetStorePath(GetStorePathForTesting()); + + EXPECT_TRUE(CreateEmptyBootEventRecord(store.GetBootEventPath("devonian"), 2718)); + + BootEventRecordStore::BootEventRecord record; + bool result = store.GetBootEvent("devonian", &record); + EXPECT_EQ(true, result); + EXPECT_EQ("devonian", record.first); + EXPECT_EQ(2718, record.second); +} -- cgit v1.2.3