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