Utility class to measure snapshot merge duration

With the Virtual A/B feature, when the device successfully boots after an OTA
update, a dm-snapshot merge operation is performed, which consolidates the
updated images to the base devices.  This merge operation depends on the OTA
size and may affect the device performance until completed.
Create the SnapshotMergeStats class that takes care of measuring the duration
of a merge operation and manages the merge state file to continue tracking the
merge in the case of an interruption due to a reboot.

Bug: 138817833
Test: m
Change-Id: I9dcf1423716c89d8f9b4a0feb4e75bb7b9d18935
Signed-off-by: Alessio Balsini <balsini@google.com>
This commit is contained in:
Alessio Balsini 2020-01-21 19:10:47 +00:00
parent 34ad19f4c4
commit cd3915d2e7
5 changed files with 135 additions and 0 deletions

View File

@ -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",

View File

@ -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;
}

View File

@ -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 {

View File

@ -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 <sstream>
#include <android-base/file.h>
#include <android-base/logging.h>
#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

View File

@ -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 <chrono>
#include <android/snapshot/snapshot.pb.h>
#include <libsnapshot/snapshot.h>
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<std::chrono::steady_clock> init_time_;
std::chrono::time_point<std::chrono::steady_clock> end_time_;
};
} // namespace snapshot
} // namespace android