blob: d8049ac0c4fe0b420bf2f9abdc5ce2f98732602a [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#ifndef UPDATE_ENGINE_COMMON_ACTION_H_
18#define UPDATE_ENGINE_COMMON_ACTION_H_
rspangler@google.com49fdf182009-10-10 00:57:34 +000019
20#include <stdio.h>
Alex Deymobc91a272014-05-20 16:45:33 -070021
Alex Deymobc91a272014-05-20 16:45:33 -070022#include <memory>
Alex Vakulenkod2779df2014-06-16 13:19:00 -070023#include <string>
Alex Deymobc91a272014-05-20 16:45:33 -070024
Alex Deymobc91a272014-05-20 16:45:33 -070025#include <base/logging.h>
Ben Chan05735a12014-09-03 07:48:22 -070026#include <base/macros.h>
Alex Deymobc91a272014-05-20 16:45:33 -070027
Alex Deymo39910dc2015-11-09 17:04:30 -080028#include "update_engine/common/action_pipe.h"
29#include "update_engine/common/action_processor.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000030
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.
Alex Deymo0b3db6b2015-08-10 15:19:37 -070045// A message loop blocks whenever there is no work to be done. This happens
rspangler@google.com49fdf182009-10-10 00:57:34 +000046// where there is no CPU work to be done and no I/O ready to transfer in or
Alex Deymo0b3db6b2015-08-10 15:19:37 -070047// 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.
rspangler@google.com49fdf182009-10-10 00:57:34 +000051//
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
Alex Vakulenkod2779df2014-06-16 13:19:00 -070073// template instantiation of Action<T>, T is declared but not defined, which
rspangler@google.com49fdf182009-10-10 00:57:34 +000074// means that T::InputObjectType (and OutputObjectType) is not defined.
75// However, the traits class is constructed in such a way that it will be
Alex Vakulenkod2779df2014-06-16 13:19:00 -070076// template instantiated first, so Action<T> *can* find the types it needs by
rspangler@google.com49fdf182009-10-10 00:57:34 +000077// consulting ActionTraits<T>::InputObjectType (and OutputObjectType).
78// This is why the ActionTraits classes are needed.
79
rspangler@google.com49fdf182009-10-10 00:57:34 +000080namespace chromeos_update_engine {
81
82// It is handy to have a non-templated base class of all Actions.
83class AbstractAction {
84 public:
Alex Vakulenko88b591f2014-08-28 16:48:57 -070085 AbstractAction() : processor_(nullptr) {}
Alex Deymoe8948702014-11-11 21:44:45 -080086 virtual ~AbstractAction() = default;
rspangler@google.com49fdf182009-10-10 00:57:34 +000087
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
David Zeuthen33bae492014-02-25 16:16:18 -0800100 // Called on ActionProcess::ActionComplete() by ActionProcessor.
101 virtual void ActionCompleted(ErrorCode code) {}
102
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103 // 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.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700125 virtual void TerminateProcessing() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000126
127 // These methods are useful for debugging. TODO(adlr): consider using
128 // std::type_info for this?
129 // Type() returns a string of the Action type. I.e., for DownloadAction,
130 // Type() would return "DownloadAction".
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800131 virtual std::string Type() const = 0;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000132
133 protected:
134 // A weak pointer to the processor that owns this Action.
135 ActionProcessor* processor_;
136};
137
138// Forward declare a couple classes we use.
139template<typename T>
140class ActionPipe;
141template<typename T>
142class ActionTraits;
143
144template<typename SubClass>
145class Action : public AbstractAction {
146 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800147 ~Action() override {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000148
149 // Attaches an input pipe to this Action. This is optional; an Action
150 // doesn't need to have an input pipe. The input pipe must be of the type
151 // of object that this class expects.
152 // This is generally called by ActionPipe::Bond()
153 void set_in_pipe(
154 // this type is a fancy way of saying: a shared_ptr to an
155 // ActionPipe<InputObjectType>.
Alex Deymobc91a272014-05-20 16:45:33 -0700156 const std::shared_ptr<ActionPipe<
Ben Chanf9cb98c2014-09-21 18:31:30 -0700157 typename ActionTraits<SubClass>::InputObjectType>>& in_pipe) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000158 in_pipe_ = in_pipe;
159 }
160
161 // Attaches an output pipe to this Action. This is optional; an Action
162 // doesn't need to have an output pipe. The output pipe must be of the type
163 // of object that this class expects.
164 // This is generally called by ActionPipe::Bond()
165 void set_out_pipe(
166 // this type is a fancy way of saying: a shared_ptr to an
167 // ActionPipe<OutputObjectType>.
Alex Deymobc91a272014-05-20 16:45:33 -0700168 const std::shared_ptr<ActionPipe<
Ben Chanf9cb98c2014-09-21 18:31:30 -0700169 typename ActionTraits<SubClass>::OutputObjectType>>& out_pipe) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000170 out_pipe_ = out_pipe;
171 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000172
rspangler@google.com49fdf182009-10-10 00:57:34 +0000173 // Returns true iff there is an associated input pipe. If there's an input
174 // pipe, there's an input object, but it may have been constructed with the
175 // default ctor if the previous action didn't call SetOutputObject().
176 bool HasInputObject() const { return in_pipe_.get(); }
177
178 // returns a const reference to the object in the input pipe.
179 const typename ActionTraits<SubClass>::InputObjectType& GetInputObject()
180 const {
181 CHECK(HasInputObject());
182 return in_pipe_->contents();
183 }
184
185 // Returns true iff there's an output pipe.
186 bool HasOutputPipe() const {
187 return out_pipe_.get();
188 }
189
190 // Copies the object passed into the output pipe. It will be accessible to
191 // the next Action via that action's input pipe (which is the same as this
192 // Action's output pipe).
193 void SetOutputObject(
194 const typename ActionTraits<SubClass>::OutputObjectType& out_obj) {
195 CHECK(HasOutputPipe());
196 out_pipe_->set_contents(out_obj);
197 }
198
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199 // Returns a reference to the object sitting in the output pipe.
200 const typename ActionTraits<SubClass>::OutputObjectType& GetOutputObject() {
201 CHECK(HasOutputPipe());
202 return out_pipe_->contents();
203 }
204
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700205 protected:
rspangler@google.com49fdf182009-10-10 00:57:34 +0000206 // We use a shared_ptr to the pipe. shared_ptr objects destroy what they
207 // point to when the last such shared_ptr object dies. We consider the
208 // Actions on either end of a pipe to "own" the pipe. When the last Action
209 // of the two dies, the ActionPipe will die, too.
Ben Chanf9cb98c2014-09-21 18:31:30 -0700210 std::shared_ptr<ActionPipe<typename ActionTraits<SubClass>::InputObjectType>>
rspangler@google.com49fdf182009-10-10 00:57:34 +0000211 in_pipe_;
Ben Chanf9cb98c2014-09-21 18:31:30 -0700212 std::shared_ptr<ActionPipe<typename ActionTraits<SubClass>::OutputObjectType>>
rspangler@google.com49fdf182009-10-10 00:57:34 +0000213 out_pipe_;
214};
215
216}; // namespace chromeos_update_engine
217
Alex Deymo39910dc2015-11-09 17:04:30 -0800218#endif // UPDATE_ENGINE_COMMON_ACTION_H_