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