1 //
2 // Copyright (C) 2011 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 
17 #ifndef UPDATE_ENGINE_COMMON_ACTION_PROCESSOR_H_
18 #define UPDATE_ENGINE_COMMON_ACTION_PROCESSOR_H_
19 
20 #include <deque>
21 #include <memory>
22 #include <vector>
23 
24 #include <base/macros.h>
25 #include <brillo/errors/error.h>
26 
27 #include "update_engine/common/error_code.h"
28 
29 #include <gtest/gtest_prod.h>
30 
31 // The structure of these classes (Action, ActionPipe, ActionProcessor, etc.)
32 // is based on the KSAction* classes from the Google Update Engine code at
33 // http://code.google.com/p/update-engine/ . The author of this file sends
34 // a big thanks to that team for their high quality design, implementation,
35 // and documentation.
36 
37 // See action.h for an overview of this class and other Action* classes.
38 
39 // An ActionProcessor keeps a queue of Actions and processes them in order.
40 
41 namespace chromeos_update_engine {
42 
43 class AbstractAction;
44 class ActionProcessorDelegate;
45 
46 class ActionProcessor {
47  public:
48   ActionProcessor() = default;
49 
50   virtual ~ActionProcessor();
51 
52   // Starts processing the first Action in the queue. If there's a delegate,
53   // when all processing is complete, ProcessingDone() will be called on the
54   // delegate.
55   virtual void StartProcessing();
56 
57   // Aborts processing. If an Action is running, it will have
58   // TerminateProcessing() called on it. The Action that was running and all the
59   // remaining actions will be lost and must be re-enqueued if this Processor is
60   // to use it.
61   void StopProcessing();
62 
63   // Suspend the processing. If an Action is running, it will have the
64   // SuspendProcessing() called on it, and it should suspend operations until
65   // ResumeProcessing() is called on this class to continue. While suspended,
66   // no new actions will be started. Calling SuspendProcessing while the
67   // processing is suspended or not running this method performs no action.
68   void SuspendProcessing();
69 
70   // Resume the suspended processing. If the ActionProcessor is not suspended
71   // or not running in the first place this method performs no action.
72   void ResumeProcessing();
73 
74   // Returns true iff the processing was started but not yet completed nor
75   // stopped.
76   bool IsRunning() const;
77 
78   // Adds another Action to the end of the queue.
79   virtual void EnqueueAction(std::unique_ptr<AbstractAction> action);
80 
81   // Sets/gets the current delegate. Set to null to remove a delegate.
delegate()82   ActionProcessorDelegate* delegate() const { return delegate_; }
set_delegate(ActionProcessorDelegate * delegate)83   void set_delegate(ActionProcessorDelegate* delegate) { delegate_ = delegate; }
84 
85   // Returns a pointer to the current Action that's processing.
current_action()86   AbstractAction* current_action() const { return current_action_.get(); }
87 
88   // Called by an action to notify processor that it's done. Caller passes self.
89   // But this call deletes the action if there no other object has a reference
90   // to it, so in that case, the caller should not try to access any of its
91   // member variables after this call.
92   void ActionComplete(AbstractAction* actionptr, ErrorCode code);
93 
94  private:
95   FRIEND_TEST(ActionProcessorTest, ChainActionsTest);
96 
97   // Continue processing actions (if any) after the last action terminated with
98   // the passed error code. If there are no more actions to process, the
99   // processing will terminate.
100   void StartNextActionOrFinish(ErrorCode code);
101 
102   // Actions that have not yet begun processing, in the order in which
103   // they'll be processed.
104   std::deque<std::unique_ptr<AbstractAction>> actions_;
105 
106   // A pointer to the currently processing Action, if any.
107   std::unique_ptr<AbstractAction> current_action_;
108 
109   // The ErrorCode reported by an action that was suspended but finished while
110   // being suspended. This error code is stored here to be reported back to the
111   // delegate once the processor is resumed.
112   ErrorCode suspended_error_code_{ErrorCode::kSuccess};
113 
114   // Whether the action processor is or should be suspended.
115   bool suspended_{false};
116 
117   // A pointer to the delegate, or null if none.
118   ActionProcessorDelegate* delegate_{nullptr};
119 
120   DISALLOW_COPY_AND_ASSIGN(ActionProcessor);
121 };
122 
123 // A delegate object can be used to be notified of events that happen
124 // in an ActionProcessor. An instance of this class can be passed to an
125 // ActionProcessor to register itself.
126 class ActionProcessorDelegate {
127  public:
128   virtual ~ActionProcessorDelegate() = default;
129 
130   // Called when all processing in an ActionProcessor has completed. A pointer
131   // to the ActionProcessor is passed. |code| is set to the exit code of the
132   // last completed action.
ProcessingDone(const ActionProcessor * processor,ErrorCode code)133   virtual void ProcessingDone(const ActionProcessor* processor,
134                               ErrorCode code) {}
135 
136   // Called when processing has stopped. Does not mean that all Actions have
137   // completed. If/when all Actions complete, ProcessingDone() will be called.
ProcessingStopped(const ActionProcessor * processor)138   virtual void ProcessingStopped(const ActionProcessor* processor) {}
139 
140   // Called whenever an action has finished processing, either successfully
141   // or otherwise.
ActionCompleted(ActionProcessor * processor,AbstractAction * action,ErrorCode code)142   virtual void ActionCompleted(ActionProcessor* processor,
143                                AbstractAction* action,
144                                ErrorCode code) {}
145 };
146 
147 }  // namespace chromeos_update_engine
148 
149 #endif  // UPDATE_ENGINE_COMMON_ACTION_PROCESSOR_H_
150