blob: 6e555ddb9b4f987037420c15418e309e5878e901 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/common/action_processor.h"
Alex Deymo8427b4a2014-11-05 14:00:32 -080018
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080019#include <string>
Amin Hassanid3f4bea2018-04-30 14:52:40 -070020#include <utility>
Alex Deymo8427b4a2014-11-05 14:00:32 -080021
22#include <base/logging.h>
23
Alex Deymo39910dc2015-11-09 17:04:30 -080024#include "update_engine/common/action.h"
Alex Deymo14fd1ec2016-02-24 22:03:57 -080025#include "update_engine/common/error_code_utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000026
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080027using std::string;
Amin Hassanid3f4bea2018-04-30 14:52:40 -070028using std::unique_ptr;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080029
rspangler@google.com49fdf182009-10-10 00:57:34 +000030namespace chromeos_update_engine {
31
rspangler@google.com49fdf182009-10-10 00:57:34 +000032ActionProcessor::~ActionProcessor() {
Alex Deymo2b4268c2015-12-04 13:56:25 -080033 if (IsRunning())
rspangler@google.com49fdf182009-10-10 00:57:34 +000034 StopProcessing();
rspangler@google.com49fdf182009-10-10 00:57:34 +000035}
36
Amin Hassanid3f4bea2018-04-30 14:52:40 -070037void ActionProcessor::EnqueueAction(unique_ptr<AbstractAction> action) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000038 action->SetProcessor(this);
Amin Hassanid3f4bea2018-04-30 14:52:40 -070039 actions_.push_back(std::move(action));
40}
41
42bool ActionProcessor::IsRunning() const {
43 return current_action_ != nullptr || suspended_;
rspangler@google.com49fdf182009-10-10 00:57:34 +000044}
45
46void ActionProcessor::StartProcessing() {
47 CHECK(!IsRunning());
48 if (!actions_.empty()) {
Amin Hassanid3f4bea2018-04-30 14:52:40 -070049 current_action_ = std::move(actions_.front());
rspangler@google.com49fdf182009-10-10 00:57:34 +000050 actions_.pop_front();
Amin Hassanid3f4bea2018-04-30 14:52:40 -070051 LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
rspangler@google.com49fdf182009-10-10 00:57:34 +000052 current_action_->PerformAction();
53 }
54}
55
56void ActionProcessor::StopProcessing() {
57 CHECK(IsRunning());
Alex Deymo14fd1ec2016-02-24 22:03:57 -080058 if (current_action_) {
59 current_action_->TerminateProcessing();
Alex Deymo14fd1ec2016-02-24 22:03:57 -080060 }
61 LOG(INFO) << "ActionProcessor: aborted "
62 << (current_action_ ? current_action_->Type() : "")
63 << (suspended_ ? " while suspended" : "");
Amin Hassanid3f4bea2018-04-30 14:52:40 -070064 current_action_.reset();
Alex Deymo14fd1ec2016-02-24 22:03:57 -080065 suspended_ = false;
Alex Deymof2858572016-02-25 11:20:13 -080066 // Delete all the actions before calling the delegate.
Alex Deymof2858572016-02-25 11:20:13 -080067 actions_.clear();
rspangler@google.com49fdf182009-10-10 00:57:34 +000068 if (delegate_)
69 delegate_->ProcessingStopped(this);
70}
71
Alex Deymo14fd1ec2016-02-24 22:03:57 -080072void ActionProcessor::SuspendProcessing() {
73 // No current_action_ when not suspended means that the action processor was
74 // never started or already finished.
75 if (suspended_ || !current_action_) {
76 LOG(WARNING) << "Called SuspendProcessing while not processing.";
77 return;
78 }
79 suspended_ = true;
80
81 // If there's a current action we should notify it that it should suspend, but
82 // the action can ignore that and terminate at any point.
83 LOG(INFO) << "ActionProcessor: suspending " << current_action_->Type();
84 current_action_->SuspendAction();
85}
86
87void ActionProcessor::ResumeProcessing() {
88 if (!suspended_) {
89 LOG(WARNING) << "Called ResumeProcessing while not suspended.";
90 return;
91 }
92 suspended_ = false;
93 if (current_action_) {
94 // The current_action_ did not call ActionComplete while suspended, so we
95 // should notify it of the resume operation.
96 LOG(INFO) << "ActionProcessor: resuming " << current_action_->Type();
97 current_action_->ResumeAction();
98 } else {
99 // The last action called ActionComplete while suspended, so there is
100 // already a log message with the type of the finished action. We simply
101 // state that we are resuming processing and the next function will log the
102 // start of the next action or processing completion.
103 LOG(INFO) << "ActionProcessor: resuming processing";
104 StartNextActionOrFinish(suspended_error_code_);
105 }
106}
107
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000108void ActionProcessor::ActionComplete(AbstractAction* actionptr,
David Zeuthena99981f2013-04-29 13:42:47 -0700109 ErrorCode code) {
Amin Hassanid3f4bea2018-04-30 14:52:40 -0700110 CHECK_EQ(actionptr, current_action_.get());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000111 if (delegate_)
Darin Petkovc1a8b422010-07-19 11:34:49 -0700112 delegate_->ActionCompleted(this, actionptr, code);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000113 string old_type = current_action_->Type();
David Zeuthen33bae492014-02-25 16:16:18 -0800114 current_action_->ActionCompleted(code);
Amin Hassanid3f4bea2018-04-30 14:52:40 -0700115 current_action_.reset();
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800116 LOG(INFO) << "ActionProcessor: finished "
117 << (actions_.empty() ? "last action " : "") << old_type
Amin Hassanib2689592019-01-13 17:04:28 -0800118 << (suspended_ ? " while suspended" : "") << " with code "
119 << utils::ErrorCodeToString(code);
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800120 if (!actions_.empty() && code != ErrorCode::kSuccess) {
121 LOG(INFO) << "ActionProcessor: Aborting processing due to failure.";
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000122 actions_.clear();
123 }
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800124 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
134void ActionProcessor::StartNextActionOrFinish(ErrorCode code) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000135 if (actions_.empty()) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000136 if (delegate_) {
Darin Petkovc1a8b422010-07-19 11:34:49 -0700137 delegate_->ProcessingDone(this, code);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000138 }
139 return;
140 }
Amin Hassanid3f4bea2018-04-30 14:52:40 -0700141 current_action_ = std::move(actions_.front());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000142 actions_.pop_front();
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800143 LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000144 current_action_->PerformAction();
145}
146
147} // namespace chromeos_update_engine