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