diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp index adfee1d1c..d274ba4b6 100644 --- a/fs_mgr/libsnapshot/Android.bp +++ b/fs_mgr/libsnapshot/Android.bp @@ -72,6 +72,7 @@ filegroup { "android/snapshot/snapshot.proto", "device_info.cpp", "snapshot.cpp", + "snapshot_stats.cpp", "snapshot_metadata_updater.cpp", "partition_cow_creator.cpp", "return.cpp", diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto index a3a518d0d..2ac0c4485 100644 --- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto +++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto @@ -131,3 +131,13 @@ message SnapshotUpdateStatus { // Sectors allocated for metadata in all the snapshot devices. uint64 metadata_sectors = 4; } + +// Next: 2 +message SnapshotMergeReport { + // Status of the update after the merge attempts. + UpdateState state = 1; + + // Number of reboots that occurred after issuing and before completeing the + // merge of all the snapshot devices. + int32 resume_count = 2; +} diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index a56078a1d..0cf579d3b 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -91,6 +91,8 @@ class SnapshotManager final { using MergeStatus = android::hardware::boot::V1_1::MergeStatus; using FiemapStatus = android::fiemap::FiemapStatus; + friend class SnapshotMergeStats; + public: // Dependency injection for testing. class IDeviceInfo { diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp new file mode 100644 index 000000000..c48509e07 --- /dev/null +++ b/fs_mgr/libsnapshot/snapshot_stats.cpp @@ -0,0 +1,80 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "snapshot_stats.h" + +#include + +#include +#include +#include "utility.h" + +namespace android { +namespace snapshot { + +SnapshotMergeStats::SnapshotMergeStats(SnapshotManager& parent) : parent_(parent) { + init_time_ = std::chrono::steady_clock::now(); +} + +SnapshotMergeStats::~SnapshotMergeStats() { + std::string error; + auto file_path = parent_.GetMergeStateFilePath(); + if (!android::base::RemoveFileIfExists(file_path, &error)) { + LOG(ERROR) << "Failed to remove merge statistics file " << file_path << ": " << error; + return; + } +} + +void SnapshotMergeStats::Start() { + SnapshotMergeReport report; + report.set_resume_count(0); + report.set_state(UpdateState::None); + + std::string contents; + if (!report.SerializeToString(&contents)) { + LOG(ERROR) << "Unable to serialize SnapshotMergeStats."; + return; + } + auto file_path = parent_.GetMergeStateFilePath(); + if (!WriteStringToFileAtomic(contents, file_path)) { + PLOG(ERROR) << "Could not write to merge statistics file"; + return; + } +} + +void SnapshotMergeStats::Resume() { + std::string contents; + if (!android::base::ReadFileToString(parent_.GetMergeStateFilePath(), &contents)) { + PLOG(INFO) << "Read merge statistics file failed"; + return; + } + + if (!report_.ParseFromString(contents)) { + LOG(ERROR) << "Unable to parse merge statistics file as SnapshotMergeReport"; + return; + } + + report_.set_resume_count(report_.resume_count() + 1); +} + +void SnapshotMergeStats::set_state(android::snapshot::UpdateState state) { + report_.set_state(state); +} + +SnapshotMergeReport SnapshotMergeStats::GetReport() { + return report_; +} + +} // namespace snapshot +} // namespace android diff --git a/fs_mgr/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/snapshot_stats.h new file mode 100644 index 000000000..1ca915663 --- /dev/null +++ b/fs_mgr/libsnapshot/snapshot_stats.h @@ -0,0 +1,42 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include +#include + +namespace android { +namespace snapshot { + +class SnapshotMergeStats { + public: + SnapshotMergeStats(SnapshotManager& parent); + ~SnapshotMergeStats(); + void Start(); + void Resume(); + void set_state(android::snapshot::UpdateState state); + SnapshotMergeReport GetReport(); + + private: + const SnapshotManager& parent_; + SnapshotMergeReport report_; + std::chrono::time_point init_time_; + std::chrono::time_point end_time_; +}; + +} // namespace snapshot +} // namespace android