blob: 2618e4e7ed37a3166335731f6193bc7d352a34e7 [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>
Alex Deymo8427b4a2014-11-05 14:00:32 -080020
21#include <base/logging.h>
22
Alex Deymo39910dc2015-11-09 17:04:30 -080023#include "update_engine/common/action.h"
Alex Deymo14fd1ec2016-02-24 22:03:57 -080024#include "update_engine/common/error_code_utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000025
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080026using std::string;
27
rspangler@google.com49fdf182009-10-10 00:57:34 +000028namespace chromeos_update_engine {
29
rspangler@google.com49fdf182009-10-10 00:57:34 +000030ActionProcessor::~ActionProcessor() {
Alex Deymo2b4268c2015-12-04 13:56:25 -080031 if (IsRunning())
rspangler@google.com49fdf182009-10-10 00:57:34 +000032 StopProcessing();
Alex Deymo2b4268c2015-12-04 13:56:25 -080033 for (auto action : actions_)
34 action->SetProcessor(nullptr);
rspangler@google.com49fdf182009-10-10 00:57:34 +000035}
36
37void ActionProcessor::EnqueueAction(AbstractAction* action) {
38 actions_.push_back(action);
39 action->SetProcessor(this);
40}
41
42void ActionProcessor::StartProcessing() {
43 CHECK(!IsRunning());
44 if (!actions_.empty()) {
45 current_action_ = actions_.front();
Alex Deymo14fd1ec2016-02-24 22:03:57 -080046 LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
rspangler@google.com49fdf182009-10-10 00:57:34 +000047 actions_.pop_front();
48 current_action_->PerformAction();
49 }
50}
51
52void ActionProcessor::StopProcessing() {
53 CHECK(IsRunning());
Alex Deymo14fd1ec2016-02-24 22:03:57 -080054 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" : "");
Alex Vakulenko88b591f2014-08-28 16:48:57 -070061 current_action_ = nullptr;
Alex Deymo14fd1ec2016-02-24 22:03:57 -080062 suspended_ = false;
rspangler@google.com49fdf182009-10-10 00:57:34 +000063 if (delegate_)
64 delegate_->ProcessingStopped(this);
65}
66
Alex Deymo14fd1ec2016-02-24 22:03:57 -080067void ActionProcessor::SuspendProcessing() {
68 // No current_action_ when not suspended means that the action processor was
69 // never started or already finished.
70 if (suspended_ || !current_action_) {
71 LOG(WARNING) << "Called SuspendProcessing while not processing.";
72 return;
73 }
74 suspended_ = true;
75
76 // If there's a current action we should notify it that it should suspend, but
77 // the action can ignore that and terminate at any point.
78 LOG(INFO) << "ActionProcessor: suspending " << current_action_->Type();
79 current_action_->SuspendAction();
80}
81
82void ActionProcessor::ResumeProcessing() {
83 if (!suspended_) {
84 LOG(WARNING) << "Called ResumeProcessing while not suspended.";
85 return;
86 }
87 suspended_ = false;
88 if (current_action_) {
89 // The current_action_ did not call ActionComplete while suspended, so we
90 // should notify it of the resume operation.
91 LOG(INFO) << "ActionProcessor: resuming " << current_action_->Type();
92 current_action_->ResumeAction();
93 } else {
94 // The last action called ActionComplete while suspended, so there is
95 // already a log message with the type of the finished action. We simply
96 // state that we are resuming processing and the next function will log the
97 // start of the next action or processing completion.
98 LOG(INFO) << "ActionProcessor: resuming processing";
99 StartNextActionOrFinish(suspended_error_code_);
100 }
101}
102
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000103void ActionProcessor::ActionComplete(AbstractAction* actionptr,
David Zeuthena99981f2013-04-29 13:42:47 -0700104 ErrorCode code) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000105 CHECK_EQ(actionptr, current_action_);
106 if (delegate_)
Darin Petkovc1a8b422010-07-19 11:34:49 -0700107 delegate_->ActionCompleted(this, actionptr, code);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108 string old_type = current_action_->Type();
David Zeuthen33bae492014-02-25 16:16:18 -0800109 current_action_->ActionCompleted(code);
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700110 current_action_->SetProcessor(nullptr);
111 current_action_ = nullptr;
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800112 LOG(INFO) << "ActionProcessor: finished "
113 << (actions_.empty() ? "last action " : "") << old_type
114 << (suspended_ ? " while suspended" : "")
115 << " with code " << utils::ErrorCodeToString(code);
116 if (!actions_.empty() && code != ErrorCode::kSuccess) {
117 LOG(INFO) << "ActionProcessor: Aborting processing due to failure.";
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000118 actions_.clear();
119 }
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800120 if (suspended_) {
121 // If an action finished while suspended we don't start the next action (or
122 // terminate the processing) until the processor is resumed. This condition
123 // will be flagged by a nullptr current_action_ while suspended_ is true.
124 suspended_error_code_ = code;
125 return;
126 }
127 StartNextActionOrFinish(code);
128}
129
130void ActionProcessor::StartNextActionOrFinish(ErrorCode code) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000131 if (actions_.empty()) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000132 if (delegate_) {
Darin Petkovc1a8b422010-07-19 11:34:49 -0700133 delegate_->ProcessingDone(this, code);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000134 }
135 return;
136 }
137 current_action_ = actions_.front();
138 actions_.pop_front();
Alex Deymo14fd1ec2016-02-24 22:03:57 -0800139 LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000140 current_action_->PerformAction();
141}
142
143} // namespace chromeos_update_engine