blob: 15f72dfad49b9f9b237e1afc5a3654c6d6b5a5db [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UPDATE_ENGINE_ACTION_H__
6#define UPDATE_ENGINE_ACTION_H__
7
8#include <stdio.h>
9#include <tr1/memory>
10#include <iostream>
11
12#include "base/basictypes.h"
seanparent@google.comd2e4ccc2009-11-05 22:56:33 +000013#include <base/logging.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000014
15#include "update_engine/action_processor.h"
16
17// The structure of these classes (Action, ActionPipe, ActionProcessor, etc.)
18// is based on the KSAction* classes from the Google Update Engine code at
19// http://code.google.com/p/update-engine/ . The author of this file sends
20// a big thanks to that team for their high quality design, implementation,
21// and documentation.
22//
23// Readers may want to consult this wiki page from the Update Engine site:
24// http://code.google.com/p/update-engine/wiki/ActionProcessor
25// Although it's referring to the Objective-C KSAction* classes, much
26// applies here as well.
27//
28// How it works:
29//
30// First off, there is only one thread and all I/O should be asynchronous.
31// A glib main loop blocks whenever there is no work to be done. This happens
32// where there is no CPU work to be done and no I/O ready to transfer in or
33// out. Two kinds of events can wake up the main loop: timer alarm or file
34// descriptors. If either of these happens, glib finds out the owner of what
35// fired and calls the appropriate code to handle it. As such, all the code
36// in the Action* classes and the code that is calls is non-blocking.
37//
38// An ActionProcessor contains a queue of Actions to perform. When
39// ActionProcessor::StartProcessing() is called, it executes the first action.
40// Each action tells the processor when it has completed, which causes the
41// Processor to execute the next action. ActionProcessor may have a delegate
42// (an object of type ActionProcessorDelegate). If it does, the delegate
43// is called to be notified of events as they happen.
44//
45// ActionPipe classes
46//
47// See action_pipe.h
48//
49// ActionTraits
50//
51// We need to use an extra class ActionTraits. ActionTraits is a simple
52// templated class that contains only two typedefs: OutputObjectType and
53// InputObjectType. Each action class also has two typedefs of the same name
54// that are of the same type. So, to get the input/output types of, e.g., the
55// DownloadAction class, we look at the type of
56// DownloadAction::InputObjectType.
57//
58// Each concrete Action class derives from Action<T>. This means that during
59// template instatiation of Action<T>, T is declared but not defined, which
60// means that T::InputObjectType (and OutputObjectType) is not defined.
61// However, the traits class is constructed in such a way that it will be
62// template instatiated first, so Action<T> *can* find the types it needs by
63// consulting ActionTraits<T>::InputObjectType (and OutputObjectType).
64// This is why the ActionTraits classes are needed.
65
66using std::tr1::shared_ptr;
67
68namespace chromeos_update_engine {
69
70// It is handy to have a non-templated base class of all Actions.
71class AbstractAction {
72 public:
73 AbstractAction() : processor_(NULL) {}
74
75 // Begin performing the action. Since this code is asynchronous, when this
76 // method returns, it means only that the action has started, not necessarily
77 // completed. However, it's acceptable for this method to perform the
78 // action synchronously; Action authors should understand the implications
79 // of synchronously performing, though, because this is a single-threaded
80 // app, the entire process will be blocked while the action performs.
81 //
82 // When the action is complete, it must call
83 // ActionProcessor::ActionComplete(this); to notify the processor that it's
84 // done.
85 virtual void PerformAction() = 0;
86
87 // Called by the ActionProcessor to tell this Action which processor
88 // it belongs to.
89 void SetProcessor(ActionProcessor* processor) {
90 if (processor)
91 CHECK(!processor_);
92 else
93 CHECK(processor_);
94 processor_ = processor;
95 }
96
97 // Returns true iff the action is the current action of its ActionProcessor.
98 bool IsRunning() const {
99 if (!processor_)
100 return false;
101 return processor_->current_action() == this;
102 }
103
104 // Called on asynchronous actions if canceled. Actions may implement if
105 // there's any cleanup to do. There is no need to call
106 // ActionProcessor::ActionComplete() because the processor knows this
107 // action is terminating.
108 // Only the ActionProcessor should call this.
109 virtual void TerminateProcessing() {};
110
111 // These methods are useful for debugging. TODO(adlr): consider using
112 // std::type_info for this?
113 // Type() returns a string of the Action type. I.e., for DownloadAction,
114 // Type() would return "DownloadAction".
115 virtual string Type() const = 0;
116
117 protected:
118 // A weak pointer to the processor that owns this Action.
119 ActionProcessor* processor_;
120};
121
122// Forward declare a couple classes we use.
123template<typename T>
124class ActionPipe;
125template<typename T>
126class ActionTraits;
127
128template<typename SubClass>
129class Action : public AbstractAction {
130 public:
131 virtual ~Action() {
132 LOG(INFO) << "Action died";
133 }
134
135 // Attaches an input pipe to this Action. This is optional; an Action
136 // doesn't need to have an input pipe. The input pipe must be of the type
137 // of object that this class expects.
138 // This is generally called by ActionPipe::Bond()
139 void set_in_pipe(
140 // this type is a fancy way of saying: a shared_ptr to an
141 // ActionPipe<InputObjectType>.
142 const shared_ptr<ActionPipe<
143 typename ActionTraits<SubClass>::InputObjectType> >&
144 in_pipe) {
145 in_pipe_ = in_pipe;
146 }
147
148 // Attaches an output pipe to this Action. This is optional; an Action
149 // doesn't need to have an output pipe. The output pipe must be of the type
150 // of object that this class expects.
151 // This is generally called by ActionPipe::Bond()
152 void set_out_pipe(
153 // this type is a fancy way of saying: a shared_ptr to an
154 // ActionPipe<OutputObjectType>.
155 const shared_ptr<ActionPipe<
156 typename ActionTraits<SubClass>::OutputObjectType> >&
157 out_pipe) {
158 out_pipe_ = out_pipe;
159 }
160 protected:
161 // Returns true iff there is an associated input pipe. If there's an input
162 // pipe, there's an input object, but it may have been constructed with the
163 // default ctor if the previous action didn't call SetOutputObject().
164 bool HasInputObject() const { return in_pipe_.get(); }
165
166 // returns a const reference to the object in the input pipe.
167 const typename ActionTraits<SubClass>::InputObjectType& GetInputObject()
168 const {
169 CHECK(HasInputObject());
170 return in_pipe_->contents();
171 }
172
173 // Returns true iff there's an output pipe.
174 bool HasOutputPipe() const {
175 return out_pipe_.get();
176 }
177
178 // Copies the object passed into the output pipe. It will be accessible to
179 // the next Action via that action's input pipe (which is the same as this
180 // Action's output pipe).
181 void SetOutputObject(
182 const typename ActionTraits<SubClass>::OutputObjectType& out_obj) {
183 CHECK(HasOutputPipe());
184 out_pipe_->set_contents(out_obj);
185 }
186
187 // We use a shared_ptr to the pipe. shared_ptr objects destroy what they
188 // point to when the last such shared_ptr object dies. We consider the
189 // Actions on either end of a pipe to "own" the pipe. When the last Action
190 // of the two dies, the ActionPipe will die, too.
191 shared_ptr<ActionPipe<typename ActionTraits<SubClass>::InputObjectType> >
192 in_pipe_;
193 shared_ptr<ActionPipe<typename ActionTraits<SubClass>::OutputObjectType> >
194 out_pipe_;
195};
196
197}; // namespace chromeos_update_engine
198
199#endif // UPDATE_ENGINE_ACTION_H__