[REFACTOR] libsnapshot: Add InitiateMergeAndWait

Move snapshot_ctl's merge command to SnapshotManager::
InitiateMergeAndWait function so that tests can use
it too.

Test: libsnapshot_test
Bug: 143551390

Change-Id: I0936c262afaca7ba445ee18465dca4e16b9416ad
This commit is contained in:
Yifan Hong 2019-10-29 16:23:10 -07:00
parent 8578a8a8ec
commit 4913d7af12
4 changed files with 31 additions and 18 deletions

View file

@ -154,6 +154,7 @@ class SnapshotManager final {
// rebooting or after rolling back), or merge the OTA.
bool FinishedSnapshotWrites();
private:
// Initiate a merge on all snapshot devices. This should only be used after an
// update has been marked successful after booting.
bool InitiateMerge();
@ -181,6 +182,15 @@ class SnapshotManager final {
// GetUpdateState will return None, and a new update can begin.
UpdateState ProcessUpdateState();
public:
// Initiate the merge if necessary, then wait for the merge to finish.
// See InitiateMerge() and ProcessUpdateState() for details.
// Returns:
// - None if no merge to initiate
// - MergeCompleted if merge is completed
// - other states indicating an error has occurred
UpdateState InitiateMergeAndWait();
// Find the status of the current update, if any.
//
// |progress| depends on the returned status:

View file

@ -2089,5 +2089,23 @@ std::unique_ptr<AutoDevice> SnapshotManager::EnsureMetadataMounted() {
return AutoUnmountDevice::New(device_->GetMetadataDir());
}
UpdateState SnapshotManager::InitiateMergeAndWait() {
auto state = GetUpdateState();
if (state == UpdateState::None) {
LOG(INFO) << "Can't find any snapshot to merge.";
return state;
}
if (state == UpdateState::Unverified) {
if (!InitiateMerge()) {
LOG(ERROR) << "Failed to initiate merge.";
return state;
}
}
// All other states can be handled by ProcessUpdateState.
LOG(INFO) << "Waiting for any merge to complete. This can take up to 1 minute.";
return ProcessUpdateState();
}
} // namespace snapshot
} // namespace android

View file

@ -847,8 +847,7 @@ TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
}
// Initiate the merge and wait for it to be completed.
ASSERT_TRUE(init->InitiateMerge());
ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
ASSERT_EQ(UpdateState::MergeCompleted, init->InitiateMergeAndWait());
// Check that the target partitions have the same content after the merge.
for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
@ -1052,8 +1051,7 @@ TEST_F(SnapshotUpdateTest, ReclaimCow) {
// Initiate the merge and wait for it to be completed.
auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
ASSERT_TRUE(new_sm->InitiateMerge());
ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
ASSERT_EQ(UpdateState::MergeCompleted, new_sm->InitiateMergeAndWait());
// Execute the second update.
ASSERT_TRUE(new_sm->BeginUpdate());

View file

@ -60,24 +60,11 @@ bool MergeCmdHandler(int argc, char** argv) {
android::base::InitLogging(argv, &android::base::StdioLogger);
}
auto sm = SnapshotManager::New();
auto state = SnapshotManager::New()->InitiateMergeAndWait();
auto state = sm->GetUpdateState();
if (state == UpdateState::None) {
LOG(INFO) << "Can't find any snapshot to merge.";
return true;
}
if (state == UpdateState::Unverified) {
if (!sm->InitiateMerge()) {
LOG(ERROR) << "Failed to initiate merge.";
return false;
}
}
// All other states can be handled by ProcessUpdateState.
LOG(INFO) << "Waiting for any merge to complete. This can take up to 1 minute.";
state = SnapshotManager::New()->ProcessUpdateState();
if (state == UpdateState::MergeCompleted) {
auto end = std::chrono::steady_clock::now();
auto passed = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();