Home | History | Annotate | Download | only in common
      1 //
      2 // Copyright (C) 2009 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "update_engine/common/action_processor.h"
     18 
     19 #include <string>
     20 
     21 #include <base/logging.h>
     22 
     23 #include "update_engine/common/action.h"
     24 #include "update_engine/common/error_code_utils.h"
     25 
     26 using std::string;
     27 
     28 namespace chromeos_update_engine {
     29 
     30 ActionProcessor::~ActionProcessor() {
     31   if (IsRunning())
     32     StopProcessing();
     33   for (auto action : actions_)
     34     action->SetProcessor(nullptr);
     35 }
     36 
     37 void ActionProcessor::EnqueueAction(AbstractAction* action) {
     38   actions_.push_back(action);
     39   action->SetProcessor(this);
     40 }
     41 
     42 void ActionProcessor::StartProcessing() {
     43   CHECK(!IsRunning());
     44   if (!actions_.empty()) {
     45     current_action_ = actions_.front();
     46     LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
     47     actions_.pop_front();
     48     current_action_->PerformAction();
     49   }
     50 }
     51 
     52 void ActionProcessor::StopProcessing() {
     53   CHECK(IsRunning());
     54   if (current_action_) {
     55     current_action_->TerminateProcessing();
     56     current_action_->SetProcessor(nullptr);
     57   }
     58   LOG(INFO) << "ActionProcessor: aborted "
     59             << (current_action_ ? current_action_->Type() : "")
     60             << (suspended_ ? " while suspended" : "");
     61   current_action_ = nullptr;
     62   suspended_ = false;
     63   // Delete all the actions before calling the delegate.
     64   for (auto action : actions_)
     65     action->SetProcessor(nullptr);
     66   actions_.clear();
     67   if (delegate_)
     68     delegate_->ProcessingStopped(this);
     69 }
     70 
     71 void ActionProcessor::SuspendProcessing() {
     72   // No current_action_ when not suspended means that the action processor was
     73   // never started or already finished.
     74   if (suspended_ || !current_action_) {
     75     LOG(WARNING) << "Called SuspendProcessing while not processing.";
     76     return;
     77   }
     78   suspended_ = true;
     79 
     80   // If there's a current action we should notify it that it should suspend, but
     81   // the action can ignore that and terminate at any point.
     82   LOG(INFO) << "ActionProcessor: suspending " << current_action_->Type();
     83   current_action_->SuspendAction();
     84 }
     85 
     86 void ActionProcessor::ResumeProcessing() {
     87   if (!suspended_) {
     88     LOG(WARNING) << "Called ResumeProcessing while not suspended.";
     89     return;
     90   }
     91   suspended_ = false;
     92   if (current_action_) {
     93     // The current_action_ did not call ActionComplete while suspended, so we
     94     // should notify it of the resume operation.
     95     LOG(INFO) << "ActionProcessor: resuming " << current_action_->Type();
     96     current_action_->ResumeAction();
     97   } else {
     98     // The last action called ActionComplete while suspended, so there is
     99     // already a log message with the type of the finished action. We simply
    100     // state that we are resuming processing and the next function will log the
    101     // start of the next action or processing completion.
    102     LOG(INFO) << "ActionProcessor: resuming processing";
    103     StartNextActionOrFinish(suspended_error_code_);
    104   }
    105 }
    106 
    107 void ActionProcessor::ActionComplete(AbstractAction* actionptr,
    108                                      ErrorCode code) {
    109   CHECK_EQ(actionptr, current_action_);
    110   if (delegate_)
    111     delegate_->ActionCompleted(this, actionptr, code);
    112   string old_type = current_action_->Type();
    113   current_action_->ActionCompleted(code);
    114   current_action_->SetProcessor(nullptr);
    115   current_action_ = nullptr;
    116   LOG(INFO) << "ActionProcessor: finished "
    117             << (actions_.empty() ? "last action " : "") << old_type
    118             << (suspended_ ? " while suspended" : "")
    119             << " with code " << utils::ErrorCodeToString(code);
    120   if (!actions_.empty() && code != ErrorCode::kSuccess) {
    121     LOG(INFO) << "ActionProcessor: Aborting processing due to failure.";
    122     actions_.clear();
    123   }
    124   if (suspended_) {
    125     // If an action finished while suspended we don't start the next action (or
    126     // terminate the processing) until the processor is resumed. This condition
    127     // will be flagged by a nullptr current_action_ while suspended_ is true.
    128     suspended_error_code_ = code;
    129     return;
    130   }
    131   StartNextActionOrFinish(code);
    132 }
    133 
    134 void ActionProcessor::StartNextActionOrFinish(ErrorCode code) {
    135   if (actions_.empty()) {
    136     if (delegate_) {
    137       delegate_->ProcessingDone(this, code);
    138     }
    139     return;
    140   }
    141   current_action_ = actions_.front();
    142   actions_.pop_front();
    143   LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
    144   current_action_->PerformAction();
    145 }
    146 
    147 }  // namespace chromeos_update_engine
    148