1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2009 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 1649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/action_processor.h" 188427b4a6d0e6e02beedbb53798272f8ddc39386fAlex Deymo 194fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes#include <string> 208427b4a6d0e6e02beedbb53798272f8ddc39386fAlex Deymo 218427b4a6d0e6e02beedbb53798272f8ddc39386fAlex Deymo#include <base/logging.h> 228427b4a6d0e6e02beedbb53798272f8ddc39386fAlex Deymo 2339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/action.h" 2414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo#include "update_engine/common/error_code_utils.h" 2549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 264fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyesusing std::string; 274fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes 2849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comnamespace chromeos_update_engine { 2949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 3049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comActionProcessor::~ActionProcessor() { 312b4268c8f89d115b0895b3f0172f42c11d9b1d7cAlex Deymo if (IsRunning()) 3249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com StopProcessing(); 332b4268c8f89d115b0895b3f0172f42c11d9b1d7cAlex Deymo for (auto action : actions_) 342b4268c8f89d115b0895b3f0172f42c11d9b1d7cAlex Deymo action->SetProcessor(nullptr); 3549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} 3649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 3749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comvoid ActionProcessor::EnqueueAction(AbstractAction* action) { 3849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com actions_.push_back(action); 3949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com action->SetProcessor(this); 4049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} 4149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 4249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comvoid ActionProcessor::StartProcessing() { 4349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com CHECK(!IsRunning()); 4449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com if (!actions_.empty()) { 4549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com current_action_ = actions_.front(); 4614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: starting " << current_action_->Type(); 4749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com actions_.pop_front(); 4849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com current_action_->PerformAction(); 4949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com } 5049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} 5149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 5249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comvoid ActionProcessor::StopProcessing() { 5349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com CHECK(IsRunning()); 5414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo if (current_action_) { 5514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo current_action_->TerminateProcessing(); 5614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo current_action_->SetProcessor(nullptr); 5714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo } 5814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: aborted " 5914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo << (current_action_ ? current_action_->Type() : "") 6014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo << (suspended_ ? " while suspended" : ""); 6188b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko current_action_ = nullptr; 6214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo suspended_ = false; 63f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo // Delete all the actions before calling the delegate. 64f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo for (auto action : actions_) 65f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo action->SetProcessor(nullptr); 66f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo actions_.clear(); 6749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com if (delegate_) 6849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com delegate_->ProcessingStopped(this); 6949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} 7049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 7114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymovoid ActionProcessor::SuspendProcessing() { 7214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // No current_action_ when not suspended means that the action processor was 7314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // never started or already finished. 7414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo if (suspended_ || !current_action_) { 7514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(WARNING) << "Called SuspendProcessing while not processing."; 7614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo return; 7714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo } 7814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo suspended_ = true; 7914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo 8014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // If there's a current action we should notify it that it should suspend, but 8114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // the action can ignore that and terminate at any point. 8214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: suspending " << current_action_->Type(); 8314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo current_action_->SuspendAction(); 8414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo} 8514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo 8614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymovoid ActionProcessor::ResumeProcessing() { 8714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo if (!suspended_) { 8814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(WARNING) << "Called ResumeProcessing while not suspended."; 8914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo return; 9014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo } 9114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo suspended_ = false; 9214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo if (current_action_) { 9314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // The current_action_ did not call ActionComplete while suspended, so we 9414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // should notify it of the resume operation. 9514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: resuming " << current_action_->Type(); 9614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo current_action_->ResumeAction(); 9714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo } else { 9814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // The last action called ActionComplete while suspended, so there is 9914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // already a log message with the type of the finished action. We simply 10014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // state that we are resuming processing and the next function will log the 10114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // start of the next action or processing completion. 10214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: resuming processing"; 10314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo StartNextActionOrFinish(suspended_error_code_); 10414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo } 10514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo} 10614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo 107c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.comvoid ActionProcessor::ActionComplete(AbstractAction* actionptr, 108a99981fda75fe0b17e96c700e3ddc93eca1cebe5David Zeuthen ErrorCode code) { 10949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com CHECK_EQ(actionptr, current_action_); 11049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com if (delegate_) 111c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov delegate_->ActionCompleted(this, actionptr, code); 11249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com string old_type = current_action_->Type(); 11333bae491eded4ef4f1eb4f4ef0f01ef0e5463f3aDavid Zeuthen current_action_->ActionCompleted(code); 11488b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko current_action_->SetProcessor(nullptr); 11588b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko current_action_ = nullptr; 11614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: finished " 11714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo << (actions_.empty() ? "last action " : "") << old_type 11814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo << (suspended_ ? " while suspended" : "") 11914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo << " with code " << utils::ErrorCodeToString(code); 12014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo if (!actions_.empty() && code != ErrorCode::kSuccess) { 12114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: Aborting processing due to failure."; 122c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com actions_.clear(); 123c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com } 12414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo if (suspended_) { 12514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // If an action finished while suspended we don't start the next action (or 12614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // terminate the processing) until the processor is resumed. This condition 12714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo // will be flagged by a nullptr current_action_ while suspended_ is true. 12814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo suspended_error_code_ = code; 12914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo return; 13014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo } 13114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo StartNextActionOrFinish(code); 13214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo} 13314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo 13414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymovoid ActionProcessor::StartNextActionOrFinish(ErrorCode code) { 135c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com if (actions_.empty()) { 13649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com if (delegate_) { 137c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov delegate_->ProcessingDone(this, code); 13849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com } 13949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com return; 14049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com } 14149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com current_action_ = actions_.front(); 14249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com actions_.pop_front(); 14314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo LOG(INFO) << "ActionProcessor: starting " << current_action_->Type(); 14449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com current_action_->PerformAction(); 14549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} 14649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 14749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} // namespace chromeos_update_engine 148