1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2011 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
1649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#ifndef UPDATE_ENGINE_COMMON_ACTION_PROCESSOR_H_
1839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#define UPDATE_ENGINE_COMMON_ACTION_PROCESSOR_H_
1949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
2049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <deque>
2149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
2205735a1879a553153458aae0a25fa5d42e3e408fBen Chan#include <base/macros.h>
2314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo#include <brillo/errors/error.h>
2449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
2539910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/error_code.h"
26a99981fda75fe0b17e96c700e3ddc93eca1cebe5David Zeuthen
2749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// The structure of these classes (Action, ActionPipe, ActionProcessor, etc.)
2849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// is based on the KSAction* classes from the Google Update Engine code at
2949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// http://code.google.com/p/update-engine/ . The author of this file sends
3049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// a big thanks to that team for their high quality design, implementation,
3149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// and documentation.
3249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
33072359ca138504065e1e0c1189eb38c09576d324Alex Vakulenko// See action.h for an overview of this class and other Action* classes.
3449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// An ActionProcessor keeps a queue of Actions and processes them in order.
3649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comnamespace chromeos_update_engine {
3849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass AbstractAction;
4049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass ActionProcessorDelegate;
4149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
4249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass ActionProcessor {
4349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com public:
4414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  ActionProcessor() = default;
4549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
46f42cc1c604fe5b0be29847a24f9bd5acf42ba394Darin Petkov  virtual ~ActionProcessor();
4749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
4849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Starts processing the first Action in the queue. If there's a delegate,
4949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // when all processing is complete, ProcessingDone() will be called on the
5049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // delegate.
51f42cc1c604fe5b0be29847a24f9bd5acf42ba394Darin Petkov  virtual void StartProcessing();
5249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
5349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Aborts processing. If an Action is running, it will have
54f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo  // TerminateProcessing() called on it. The Action that was running and all the
55f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo  // remaining actions will be lost and must be re-enqueued if this Processor is
56f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo  // to use it.
5749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  void StopProcessing();
5849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
5914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // Suspend the processing. If an Action is running, it will have the
6014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // SuspendProcessing() called on it, and it should suspend operations until
6114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // ResumeProcessing() is called on this class to continue. While suspended,
6214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // no new actions will be started. Calling SuspendProcessing while the
6314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // processing is suspended or not running this method performs no action.
6414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  void SuspendProcessing();
6514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo
6614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // Resume the suspended processing. If the ActionProcessor is not suspended
67f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo  // or not running in the first place this method performs no action.
6814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  void ResumeProcessing();
6914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo
7014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // Returns true iff the processing was started but not yet completed nor
7114fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // stopped.
7214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  bool IsRunning() const { return current_action_ != nullptr || suspended_; }
7349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
7449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Adds another Action to the end of the queue.
75f42cc1c604fe5b0be29847a24f9bd5acf42ba394Darin Petkov  virtual void EnqueueAction(AbstractAction* action);
7649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
7788b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  // Sets/gets the current delegate. Set to null to remove a delegate.
78f42cc1c604fe5b0be29847a24f9bd5acf42ba394Darin Petkov  ActionProcessorDelegate* delegate() const { return delegate_; }
7949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  void set_delegate(ActionProcessorDelegate *delegate) {
8049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com    delegate_ = delegate;
8149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  }
8249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
8349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Returns a pointer to the current Action that's processing.
8449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  AbstractAction* current_action() const {
8549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com    return current_action_;
8649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  }
8749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
8849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Called by an action to notify processor that it's done. Caller passes self.
89a99981fda75fe0b17e96c700e3ddc93eca1cebe5David Zeuthen  void ActionComplete(AbstractAction* actionptr, ErrorCode code);
9049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
9149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com private:
9214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // Continue processing actions (if any) after the last action terminated with
9314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // the passed error code. If there are no more actions to process, the
9414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // processing will terminate.
9514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  void StartNextActionOrFinish(ErrorCode code);
9614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo
9749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Actions that have not yet begun processing, in the order in which
9849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // they'll be processed.
9949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  std::deque<AbstractAction*> actions_;
10049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
101072359ca138504065e1e0c1189eb38c09576d324Alex Vakulenko  // A pointer to the currently processing Action, if any.
10214fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  AbstractAction* current_action_{nullptr};
10314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo
10414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // The ErrorCode reported by an action that was suspended but finished while
10514fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // being suspended. This error code is stored here to be reported back to the
10614fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // delegate once the processor is resumed.
10714fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  ErrorCode suspended_error_code_{ErrorCode::kSuccess};
10814fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo
10914fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  // Whether the action processor is or should be suspended.
11014fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  bool suspended_{false};
11149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
11288b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  // A pointer to the delegate, or null if none.
11314fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo  ActionProcessorDelegate* delegate_{nullptr};
11414fd1ec41d1da4e849b724b762ca111a30c6628cAlex Deymo
11549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  DISALLOW_COPY_AND_ASSIGN(ActionProcessor);
11649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com};
11749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
11849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// A delegate object can be used to be notified of events that happen
11949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// in an ActionProcessor. An instance of this class can be passed to an
12049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// ActionProcessor to register itself.
12149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comclass ActionProcessorDelegate {
12249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com public:
123e89487039d0eca8130d822cabf75a729609509e0Alex Deymo  virtual ~ActionProcessorDelegate() = default;
124e89487039d0eca8130d822cabf75a729609509e0Alex Deymo
12549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Called when all processing in an ActionProcessor has completed. A pointer
126c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov  // to the ActionProcessor is passed. |code| is set to the exit code of the
127c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov  // last completed action.
128c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov  virtual void ProcessingDone(const ActionProcessor* processor,
129a99981fda75fe0b17e96c700e3ddc93eca1cebe5David Zeuthen                              ErrorCode code) {}
13049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
13149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Called when processing has stopped. Does not mean that all Actions have
13249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // completed. If/when all Actions complete, ProcessingDone() will be called.
13349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  virtual void ProcessingStopped(const ActionProcessor* processor) {}
13449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
13549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // Called whenever an action has finished processing, either successfully
13649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com  // or otherwise.
137c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  virtual void ActionCompleted(ActionProcessor* processor,
138c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com                               AbstractAction* action,
139a99981fda75fe0b17e96c700e3ddc93eca1cebe5David Zeuthen                               ErrorCode code) {}
14049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com};
14149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
14249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com}  // namespace chromeos_update_engine
14349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
14439910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#endif  // UPDATE_ENGINE_COMMON_ACTION_PROCESSOR_H_
145