action_processor.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. #include "update_engine/common/action_processor.h"
  17. #include <string>
  18. #include <utility>
  19. #include <base/logging.h>
  20. #include "update_engine/common/action.h"
  21. #include "update_engine/common/error_code_utils.h"
  22. using std::string;
  23. using std::unique_ptr;
  24. namespace chromeos_update_engine {
  25. ActionProcessor::~ActionProcessor() {
  26. if (IsRunning())
  27. StopProcessing();
  28. }
  29. void ActionProcessor::EnqueueAction(unique_ptr<AbstractAction> action) {
  30. action->SetProcessor(this);
  31. actions_.push_back(std::move(action));
  32. }
  33. bool ActionProcessor::IsRunning() const {
  34. return current_action_ != nullptr || suspended_;
  35. }
  36. void ActionProcessor::StartProcessing() {
  37. CHECK(!IsRunning());
  38. if (!actions_.empty()) {
  39. current_action_ = std::move(actions_.front());
  40. actions_.pop_front();
  41. LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
  42. current_action_->PerformAction();
  43. }
  44. }
  45. void ActionProcessor::StopProcessing() {
  46. CHECK(IsRunning());
  47. if (current_action_) {
  48. current_action_->TerminateProcessing();
  49. }
  50. LOG(INFO) << "ActionProcessor: aborted "
  51. << (current_action_ ? current_action_->Type() : "")
  52. << (suspended_ ? " while suspended" : "");
  53. current_action_.reset();
  54. suspended_ = false;
  55. // Delete all the actions before calling the delegate.
  56. actions_.clear();
  57. if (delegate_)
  58. delegate_->ProcessingStopped(this);
  59. }
  60. void ActionProcessor::SuspendProcessing() {
  61. // No current_action_ when not suspended means that the action processor was
  62. // never started or already finished.
  63. if (suspended_ || !current_action_) {
  64. LOG(WARNING) << "Called SuspendProcessing while not processing.";
  65. return;
  66. }
  67. suspended_ = true;
  68. // If there's a current action we should notify it that it should suspend, but
  69. // the action can ignore that and terminate at any point.
  70. LOG(INFO) << "ActionProcessor: suspending " << current_action_->Type();
  71. current_action_->SuspendAction();
  72. }
  73. void ActionProcessor::ResumeProcessing() {
  74. if (!suspended_) {
  75. LOG(WARNING) << "Called ResumeProcessing while not suspended.";
  76. return;
  77. }
  78. suspended_ = false;
  79. if (current_action_) {
  80. // The current_action_ did not call ActionComplete while suspended, so we
  81. // should notify it of the resume operation.
  82. LOG(INFO) << "ActionProcessor: resuming " << current_action_->Type();
  83. current_action_->ResumeAction();
  84. } else {
  85. // The last action called ActionComplete while suspended, so there is
  86. // already a log message with the type of the finished action. We simply
  87. // state that we are resuming processing and the next function will log the
  88. // start of the next action or processing completion.
  89. LOG(INFO) << "ActionProcessor: resuming processing";
  90. StartNextActionOrFinish(suspended_error_code_);
  91. }
  92. }
  93. void ActionProcessor::ActionComplete(AbstractAction* actionptr,
  94. ErrorCode code) {
  95. CHECK_EQ(actionptr, current_action_.get());
  96. if (delegate_)
  97. delegate_->ActionCompleted(this, actionptr, code);
  98. string old_type = current_action_->Type();
  99. current_action_->ActionCompleted(code);
  100. current_action_.reset();
  101. LOG(INFO) << "ActionProcessor: finished "
  102. << (actions_.empty() ? "last action " : "") << old_type
  103. << (suspended_ ? " while suspended" : "") << " with code "
  104. << utils::ErrorCodeToString(code);
  105. if (!actions_.empty() && code != ErrorCode::kSuccess) {
  106. LOG(INFO) << "ActionProcessor: Aborting processing due to failure.";
  107. actions_.clear();
  108. }
  109. if (suspended_) {
  110. // If an action finished while suspended we don't start the next action (or
  111. // terminate the processing) until the processor is resumed. This condition
  112. // will be flagged by a nullptr current_action_ while suspended_ is true.
  113. suspended_error_code_ = code;
  114. return;
  115. }
  116. StartNextActionOrFinish(code);
  117. }
  118. void ActionProcessor::StartNextActionOrFinish(ErrorCode code) {
  119. if (actions_.empty()) {
  120. if (delegate_) {
  121. delegate_->ProcessingDone(this, code);
  122. }
  123. return;
  124. }
  125. current_action_ = std::move(actions_.front());
  126. actions_.pop_front();
  127. LOG(INFO) << "ActionProcessor: starting " << current_action_->Type();
  128. current_action_->PerformAction();
  129. }
  130. } // namespace chromeos_update_engine