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