xref: /aosp_15_r20/system/update_engine/common/action.h (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2009 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #ifndef UPDATE_ENGINE_COMMON_ACTION_H_
18*5a923131SAndroid Build Coastguard Worker #define UPDATE_ENGINE_COMMON_ACTION_H_
19*5a923131SAndroid Build Coastguard Worker 
20*5a923131SAndroid Build Coastguard Worker #include <stdio.h>
21*5a923131SAndroid Build Coastguard Worker 
22*5a923131SAndroid Build Coastguard Worker #include <memory>
23*5a923131SAndroid Build Coastguard Worker #include <string>
24*5a923131SAndroid Build Coastguard Worker 
25*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
26*5a923131SAndroid Build Coastguard Worker #include <android-base/macros.h>
27*5a923131SAndroid Build Coastguard Worker 
28*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/action_pipe.h"
29*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/action_processor.h"
30*5a923131SAndroid Build Coastguard Worker 
31*5a923131SAndroid Build Coastguard Worker // The structure of these classes (Action, ActionPipe, ActionProcessor, etc.)
32*5a923131SAndroid Build Coastguard Worker // is based on the KSAction* classes from the Google Update Engine code at
33*5a923131SAndroid Build Coastguard Worker // http://code.google.com/p/update-engine/ . The author of this file sends
34*5a923131SAndroid Build Coastguard Worker // a big thanks to that team for their high quality design, implementation,
35*5a923131SAndroid Build Coastguard Worker // and documentation.
36*5a923131SAndroid Build Coastguard Worker //
37*5a923131SAndroid Build Coastguard Worker // Readers may want to consult this wiki page from the Update Engine site:
38*5a923131SAndroid Build Coastguard Worker // http://code.google.com/p/update-engine/wiki/ActionProcessor
39*5a923131SAndroid Build Coastguard Worker // Although it's referring to the Objective-C KSAction* classes, much
40*5a923131SAndroid Build Coastguard Worker // applies here as well.
41*5a923131SAndroid Build Coastguard Worker //
42*5a923131SAndroid Build Coastguard Worker // How it works:
43*5a923131SAndroid Build Coastguard Worker //
44*5a923131SAndroid Build Coastguard Worker // First off, there is only one thread and all I/O should be asynchronous.
45*5a923131SAndroid Build Coastguard Worker // A message loop blocks whenever there is no work to be done. This happens
46*5a923131SAndroid Build Coastguard Worker // where there is no CPU work to be done and no I/O ready to transfer in or
47*5a923131SAndroid Build Coastguard Worker // out. Two kinds of events can wake up the message loop: timer alarm or file
48*5a923131SAndroid Build Coastguard Worker // descriptors. If either of these happens, the message loop finds out the owner
49*5a923131SAndroid Build Coastguard Worker // of what fired and calls the appropriate code to handle it. As such, all the
50*5a923131SAndroid Build Coastguard Worker // code in the Action* classes and the code that is calls is non-blocking.
51*5a923131SAndroid Build Coastguard Worker //
52*5a923131SAndroid Build Coastguard Worker // An ActionProcessor contains a queue of Actions to perform. When
53*5a923131SAndroid Build Coastguard Worker // ActionProcessor::StartProcessing() is called, it executes the first action.
54*5a923131SAndroid Build Coastguard Worker // Each action tells the processor when it has completed, which causes the
55*5a923131SAndroid Build Coastguard Worker // Processor to execute the next action. ActionProcessor may have a delegate
56*5a923131SAndroid Build Coastguard Worker // (an object of type ActionProcessorDelegate). If it does, the delegate
57*5a923131SAndroid Build Coastguard Worker // is called to be notified of events as they happen.
58*5a923131SAndroid Build Coastguard Worker //
59*5a923131SAndroid Build Coastguard Worker // ActionPipe classes
60*5a923131SAndroid Build Coastguard Worker //
61*5a923131SAndroid Build Coastguard Worker // See action_pipe.h
62*5a923131SAndroid Build Coastguard Worker //
63*5a923131SAndroid Build Coastguard Worker // ActionTraits
64*5a923131SAndroid Build Coastguard Worker //
65*5a923131SAndroid Build Coastguard Worker // We need to use an extra class ActionTraits. ActionTraits is a simple
66*5a923131SAndroid Build Coastguard Worker // templated class that contains only two typedefs: OutputObjectType and
67*5a923131SAndroid Build Coastguard Worker // InputObjectType. Each action class also has two typedefs of the same name
68*5a923131SAndroid Build Coastguard Worker // that are of the same type. So, to get the input/output types of, e.g., the
69*5a923131SAndroid Build Coastguard Worker // DownloadAction class, we look at the type of
70*5a923131SAndroid Build Coastguard Worker // DownloadAction::InputObjectType.
71*5a923131SAndroid Build Coastguard Worker //
72*5a923131SAndroid Build Coastguard Worker // Each concrete Action class derives from Action<T>. This means that during
73*5a923131SAndroid Build Coastguard Worker // template instantiation of Action<T>, T is declared but not defined, which
74*5a923131SAndroid Build Coastguard Worker // means that T::InputObjectType (and OutputObjectType) is not defined.
75*5a923131SAndroid Build Coastguard Worker // However, the traits class is constructed in such a way that it will be
76*5a923131SAndroid Build Coastguard Worker // template instantiated first, so Action<T> *can* find the types it needs by
77*5a923131SAndroid Build Coastguard Worker // consulting ActionTraits<T>::InputObjectType (and OutputObjectType).
78*5a923131SAndroid Build Coastguard Worker // This is why the ActionTraits classes are needed.
79*5a923131SAndroid Build Coastguard Worker 
80*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
81*5a923131SAndroid Build Coastguard Worker 
82*5a923131SAndroid Build Coastguard Worker // It is handy to have a non-templated base class of all Actions.
83*5a923131SAndroid Build Coastguard Worker class AbstractAction {
84*5a923131SAndroid Build Coastguard Worker  public:
AbstractAction()85*5a923131SAndroid Build Coastguard Worker   AbstractAction() : processor_(nullptr) {}
86*5a923131SAndroid Build Coastguard Worker   virtual ~AbstractAction() = default;
87*5a923131SAndroid Build Coastguard Worker 
88*5a923131SAndroid Build Coastguard Worker   // Begin performing the action. Since this code is asynchronous, when this
89*5a923131SAndroid Build Coastguard Worker   // method returns, it means only that the action has started, not necessarily
90*5a923131SAndroid Build Coastguard Worker   // completed. However, it's acceptable for this method to perform the
91*5a923131SAndroid Build Coastguard Worker   // action synchronously; Action authors should understand the implications
92*5a923131SAndroid Build Coastguard Worker   // of synchronously performing, though, because this is a single-threaded
93*5a923131SAndroid Build Coastguard Worker   // app, the entire process will be blocked while the action performs.
94*5a923131SAndroid Build Coastguard Worker   //
95*5a923131SAndroid Build Coastguard Worker   // When the action is complete, it must call
96*5a923131SAndroid Build Coastguard Worker   // ActionProcessor::ActionComplete(this); to notify the processor that it's
97*5a923131SAndroid Build Coastguard Worker   // done.
98*5a923131SAndroid Build Coastguard Worker   virtual void PerformAction() = 0;
99*5a923131SAndroid Build Coastguard Worker 
100*5a923131SAndroid Build Coastguard Worker   // Called on ActionProcess::ActionComplete() by ActionProcessor.
ActionCompleted(ErrorCode code)101*5a923131SAndroid Build Coastguard Worker   virtual void ActionCompleted([[maybe_unused]] ErrorCode code) {}
102*5a923131SAndroid Build Coastguard Worker 
103*5a923131SAndroid Build Coastguard Worker   // Called by the ActionProcessor to tell this Action which processor
104*5a923131SAndroid Build Coastguard Worker   // it belongs to.
SetProcessor(ActionProcessor * processor)105*5a923131SAndroid Build Coastguard Worker   void SetProcessor(ActionProcessor* processor) {
106*5a923131SAndroid Build Coastguard Worker     if (processor)
107*5a923131SAndroid Build Coastguard Worker       CHECK(!processor_);
108*5a923131SAndroid Build Coastguard Worker     else
109*5a923131SAndroid Build Coastguard Worker       CHECK(processor_);
110*5a923131SAndroid Build Coastguard Worker     processor_ = processor;
111*5a923131SAndroid Build Coastguard Worker   }
112*5a923131SAndroid Build Coastguard Worker 
113*5a923131SAndroid Build Coastguard Worker   // Returns true iff the action is the current action of its ActionProcessor.
IsRunning()114*5a923131SAndroid Build Coastguard Worker   bool IsRunning() const {
115*5a923131SAndroid Build Coastguard Worker     if (!processor_)
116*5a923131SAndroid Build Coastguard Worker       return false;
117*5a923131SAndroid Build Coastguard Worker     return processor_->current_action() == this;
118*5a923131SAndroid Build Coastguard Worker   }
119*5a923131SAndroid Build Coastguard Worker 
120*5a923131SAndroid Build Coastguard Worker   // Called on asynchronous actions if canceled. Actions may implement if
121*5a923131SAndroid Build Coastguard Worker   // there's any cleanup to do. There is no need to call
122*5a923131SAndroid Build Coastguard Worker   // ActionProcessor::ActionComplete() because the processor knows this
123*5a923131SAndroid Build Coastguard Worker   // action is terminating.
124*5a923131SAndroid Build Coastguard Worker   // Only the ActionProcessor should call this.
TerminateProcessing()125*5a923131SAndroid Build Coastguard Worker   virtual void TerminateProcessing() {}
126*5a923131SAndroid Build Coastguard Worker 
127*5a923131SAndroid Build Coastguard Worker   // Called on asynchronous actions if the processing is suspended and resumed,
128*5a923131SAndroid Build Coastguard Worker   // respectively. These methods are called by the ActionProcessor and should
129*5a923131SAndroid Build Coastguard Worker   // not be explicitly called.
130*5a923131SAndroid Build Coastguard Worker   // The action may still call ActionCompleted() once the action is completed
131*5a923131SAndroid Build Coastguard Worker   // while the processing is suspended, for example if suspend/resume is not
132*5a923131SAndroid Build Coastguard Worker   // implemented for the given action.
SuspendAction()133*5a923131SAndroid Build Coastguard Worker   virtual void SuspendAction() {}
ResumeAction()134*5a923131SAndroid Build Coastguard Worker   virtual void ResumeAction() {}
135*5a923131SAndroid Build Coastguard Worker 
136*5a923131SAndroid Build Coastguard Worker   // These methods are useful for debugging. TODO(adlr): consider using
137*5a923131SAndroid Build Coastguard Worker   // std::type_info for this?
138*5a923131SAndroid Build Coastguard Worker   // Type() returns a string of the Action type. I.e., for DownloadAction,
139*5a923131SAndroid Build Coastguard Worker   // Type() would return "DownloadAction".
140*5a923131SAndroid Build Coastguard Worker   virtual std::string Type() const = 0;
141*5a923131SAndroid Build Coastguard Worker 
142*5a923131SAndroid Build Coastguard Worker  protected:
143*5a923131SAndroid Build Coastguard Worker   // A weak pointer to the processor that owns this Action.
144*5a923131SAndroid Build Coastguard Worker   ActionProcessor* processor_;
145*5a923131SAndroid Build Coastguard Worker };
146*5a923131SAndroid Build Coastguard Worker 
147*5a923131SAndroid Build Coastguard Worker // Forward declare a couple classes we use.
148*5a923131SAndroid Build Coastguard Worker template <typename T>
149*5a923131SAndroid Build Coastguard Worker class ActionPipe;
150*5a923131SAndroid Build Coastguard Worker template <typename T>
151*5a923131SAndroid Build Coastguard Worker class ActionTraits;
152*5a923131SAndroid Build Coastguard Worker 
153*5a923131SAndroid Build Coastguard Worker template <typename SubClass>
154*5a923131SAndroid Build Coastguard Worker class Action : public AbstractAction {
155*5a923131SAndroid Build Coastguard Worker  public:
~Action()156*5a923131SAndroid Build Coastguard Worker   ~Action() override {}
157*5a923131SAndroid Build Coastguard Worker 
158*5a923131SAndroid Build Coastguard Worker   // Attaches an input pipe to this Action. This is optional; an Action
159*5a923131SAndroid Build Coastguard Worker   // doesn't need to have an input pipe. The input pipe must be of the type
160*5a923131SAndroid Build Coastguard Worker   // of object that this class expects.
161*5a923131SAndroid Build Coastguard Worker   // This is generally called by ActionPipe::Bond()
set_in_pipe(const std::shared_ptr<ActionPipe<typename ActionTraits<SubClass>::InputObjectType>> & in_pipe)162*5a923131SAndroid Build Coastguard Worker   void set_in_pipe(
163*5a923131SAndroid Build Coastguard Worker       // this type is a fancy way of saying: a shared_ptr to an
164*5a923131SAndroid Build Coastguard Worker       // ActionPipe<InputObjectType>.
165*5a923131SAndroid Build Coastguard Worker       const std::shared_ptr<
166*5a923131SAndroid Build Coastguard Worker           ActionPipe<typename ActionTraits<SubClass>::InputObjectType>>&
167*5a923131SAndroid Build Coastguard Worker           in_pipe) {
168*5a923131SAndroid Build Coastguard Worker     in_pipe_ = in_pipe;
169*5a923131SAndroid Build Coastguard Worker   }
170*5a923131SAndroid Build Coastguard Worker 
171*5a923131SAndroid Build Coastguard Worker   // Attaches an output pipe to this Action. This is optional; an Action
172*5a923131SAndroid Build Coastguard Worker   // doesn't need to have an output pipe. The output pipe must be of the type
173*5a923131SAndroid Build Coastguard Worker   // of object that this class expects.
174*5a923131SAndroid Build Coastguard Worker   // This is generally called by ActionPipe::Bond()
set_out_pipe(const std::shared_ptr<ActionPipe<typename ActionTraits<SubClass>::OutputObjectType>> & out_pipe)175*5a923131SAndroid Build Coastguard Worker   void set_out_pipe(
176*5a923131SAndroid Build Coastguard Worker       // this type is a fancy way of saying: a shared_ptr to an
177*5a923131SAndroid Build Coastguard Worker       // ActionPipe<OutputObjectType>.
178*5a923131SAndroid Build Coastguard Worker       const std::shared_ptr<
179*5a923131SAndroid Build Coastguard Worker           ActionPipe<typename ActionTraits<SubClass>::OutputObjectType>>&
180*5a923131SAndroid Build Coastguard Worker           out_pipe) {
181*5a923131SAndroid Build Coastguard Worker     out_pipe_ = out_pipe;
182*5a923131SAndroid Build Coastguard Worker   }
183*5a923131SAndroid Build Coastguard Worker 
184*5a923131SAndroid Build Coastguard Worker   // Returns true iff there is an associated input pipe. If there's an input
185*5a923131SAndroid Build Coastguard Worker   // pipe, there's an input object, but it may have been constructed with the
186*5a923131SAndroid Build Coastguard Worker   // default ctor if the previous action didn't call SetOutputObject().
HasInputObject()187*5a923131SAndroid Build Coastguard Worker   bool HasInputObject() const { return in_pipe_.get(); }
188*5a923131SAndroid Build Coastguard Worker 
189*5a923131SAndroid Build Coastguard Worker   // returns a const reference to the object in the input pipe.
GetInputObject()190*5a923131SAndroid Build Coastguard Worker   const typename ActionTraits<SubClass>::InputObjectType& GetInputObject()
191*5a923131SAndroid Build Coastguard Worker       const {
192*5a923131SAndroid Build Coastguard Worker     CHECK(HasInputObject());
193*5a923131SAndroid Build Coastguard Worker     return in_pipe_->contents();
194*5a923131SAndroid Build Coastguard Worker   }
195*5a923131SAndroid Build Coastguard Worker 
196*5a923131SAndroid Build Coastguard Worker   // Returns true iff there's an output pipe.
HasOutputPipe()197*5a923131SAndroid Build Coastguard Worker   bool HasOutputPipe() const { return out_pipe_.get(); }
198*5a923131SAndroid Build Coastguard Worker 
199*5a923131SAndroid Build Coastguard Worker   // Copies the object passed into the output pipe. It will be accessible to
200*5a923131SAndroid Build Coastguard Worker   // the next Action via that action's input pipe (which is the same as this
201*5a923131SAndroid Build Coastguard Worker   // Action's output pipe).
SetOutputObject(const typename ActionTraits<SubClass>::OutputObjectType & out_obj)202*5a923131SAndroid Build Coastguard Worker   void SetOutputObject(
203*5a923131SAndroid Build Coastguard Worker       const typename ActionTraits<SubClass>::OutputObjectType& out_obj) {
204*5a923131SAndroid Build Coastguard Worker     CHECK(HasOutputPipe());
205*5a923131SAndroid Build Coastguard Worker     out_pipe_->set_contents(out_obj);
206*5a923131SAndroid Build Coastguard Worker   }
207*5a923131SAndroid Build Coastguard Worker 
208*5a923131SAndroid Build Coastguard Worker   // Returns a reference to the object sitting in the output pipe.
GetOutputObject()209*5a923131SAndroid Build Coastguard Worker   const typename ActionTraits<SubClass>::OutputObjectType& GetOutputObject() {
210*5a923131SAndroid Build Coastguard Worker     CHECK(HasOutputPipe());
211*5a923131SAndroid Build Coastguard Worker     return out_pipe_->contents();
212*5a923131SAndroid Build Coastguard Worker   }
213*5a923131SAndroid Build Coastguard Worker 
214*5a923131SAndroid Build Coastguard Worker  protected:
215*5a923131SAndroid Build Coastguard Worker   // We use a shared_ptr to the pipe. shared_ptr objects destroy what they
216*5a923131SAndroid Build Coastguard Worker   // point to when the last such shared_ptr object dies. We consider the
217*5a923131SAndroid Build Coastguard Worker   // Actions on either end of a pipe to "own" the pipe. When the last Action
218*5a923131SAndroid Build Coastguard Worker   // of the two dies, the ActionPipe will die, too.
219*5a923131SAndroid Build Coastguard Worker   std::shared_ptr<ActionPipe<typename ActionTraits<SubClass>::InputObjectType>>
220*5a923131SAndroid Build Coastguard Worker       in_pipe_;
221*5a923131SAndroid Build Coastguard Worker   std::shared_ptr<ActionPipe<typename ActionTraits<SubClass>::OutputObjectType>>
222*5a923131SAndroid Build Coastguard Worker       out_pipe_;
223*5a923131SAndroid Build Coastguard Worker };
224*5a923131SAndroid Build Coastguard Worker 
225*5a923131SAndroid Build Coastguard Worker // An action that does nothing and completes with kSuccess immediately.
226*5a923131SAndroid Build Coastguard Worker class NoOpAction : public AbstractAction {
227*5a923131SAndroid Build Coastguard Worker  public:
~NoOpAction()228*5a923131SAndroid Build Coastguard Worker   ~NoOpAction() override {}
PerformAction()229*5a923131SAndroid Build Coastguard Worker   void PerformAction() override {
230*5a923131SAndroid Build Coastguard Worker     processor_->ActionComplete(this, ErrorCode::kSuccess);
231*5a923131SAndroid Build Coastguard Worker   }
StaticType()232*5a923131SAndroid Build Coastguard Worker   static std::string StaticType() { return "NoOpAction"; }
Type()233*5a923131SAndroid Build Coastguard Worker   std::string Type() const override { return StaticType(); }
234*5a923131SAndroid Build Coastguard Worker };
235*5a923131SAndroid Build Coastguard Worker 
236*5a923131SAndroid Build Coastguard Worker };  // namespace chromeos_update_engine
237*5a923131SAndroid Build Coastguard Worker 
238*5a923131SAndroid Build Coastguard Worker #endif  // UPDATE_ENGINE_COMMON_ACTION_H_
239