blob: 98774ef5531dc0620c67524222959f5a61b0f280 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2014 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//
Alex Deymo8c499142014-01-02 19:33:34 -080016
Gilad Arnold48415f12014-06-27 07:10:58 -070017#ifndef UPDATE_ENGINE_UPDATE_MANAGER_VARIABLE_H_
18#define UPDATE_ENGINE_UPDATE_MANAGER_VARIABLE_H_
Alex Deymo8c499142014-01-02 19:33:34 -080019
Alex Deymoa07a1232014-02-25 14:19:50 -080020#include <algorithm>
21#include <list>
Alex Deymo8c499142014-01-02 19:33:34 -080022#include <string>
23
Alex Deymo53556ec2014-03-17 10:05:57 -070024#include <base/bind.h>
Alex Deymo0bb23412015-06-19 00:04:46 -070025#include <base/location.h>
Alex Deymo53556ec2014-03-17 10:05:57 -070026#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070027#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070028#include <brillo/message_loops/message_loop.h>
Alex Deymoca0aaa62014-01-06 10:39:58 -080029#include <gtest/gtest_prod.h> // for FRIEND_TEST
Alex Deymo8c499142014-01-02 19:33:34 -080030
Alex Deymo63784a52014-05-28 10:46:14 -070031namespace chromeos_update_manager {
Alex Deymo8c499142014-01-02 19:33:34 -080032
Alex Deymo0e433692014-02-20 07:23:03 -080033// The VariableMode specifies important behavior of the variable in terms of
34// whether, how and when the value of the variable changes.
35enum VariableMode {
36 // Const variables never changes during the life of a policy request, so the
37 // EvaluationContext caches the value even between different evaluations of
38 // the same policy request.
39 kVariableModeConst,
40
41 // Poll variables, or synchronous variables, represent a variable with a value
42 // that can be queried at any time, but it is not known when the value
43 // changes on the source of information. In order to detect if the value of
44 // the variable changes, it has to be queried again.
45 kVariableModePoll,
46
47 // Async variables are able to produce a signal or callback whenever the
48 // value changes. This means that it's not required to poll the value to
49 // detect when it changes, instead, you should register an observer to get
50 // a notification when that happens.
51 kVariableModeAsync,
52};
53
Alex Deymo391ad9f2014-01-29 14:36:20 -080054// This class is a base class with the common functionality that doesn't
Alex Vakulenko072359c2014-07-18 11:41:07 -070055// depend on the variable's type, implemented by all the variables.
Alex Deymo391ad9f2014-01-29 14:36:20 -080056class BaseVariable {
Alex Deymo8c499142014-01-02 19:33:34 -080057 public:
Alex Deymoa07a1232014-02-25 14:19:50 -080058 // Interface for observing changes on variable value.
Alex Deymo53556ec2014-03-17 10:05:57 -070059 class ObserverInterface {
Alex Deymoa07a1232014-02-25 14:19:50 -080060 public:
Alex Deymo53556ec2014-03-17 10:05:57 -070061 virtual ~ObserverInterface() {}
Alex Deymoa07a1232014-02-25 14:19:50 -080062
63 // Called when the value on the variable changes.
64 virtual void ValueChanged(BaseVariable* variable) = 0;
65 };
66
Alex Deymo53556ec2014-03-17 10:05:57 -070067 virtual ~BaseVariable() {
68 if (!observer_list_.empty()) {
69 LOG(WARNING) << "Variable " << name_ << " deleted with "
70 << observer_list_.size() << " observers.";
71 }
Alex Deymoc83baf62014-04-02 17:43:35 -070072 DCHECK(observer_list_.empty()) << "Don't destroy the variable without "
73 "removing the observers.";
Alex Deymo53556ec2014-03-17 10:05:57 -070074 }
Alex Deymo391ad9f2014-01-29 14:36:20 -080075
76 // Returns the variable name as a string.
Alex Deymo0e433692014-02-20 07:23:03 -080077 const std::string& GetName() const {
Alex Deymo391ad9f2014-01-29 14:36:20 -080078 return name_;
79 }
80
Alex Deymo0e433692014-02-20 07:23:03 -080081 // Returns the variable mode.
82 VariableMode GetMode() const {
83 return mode_;
84 }
85
Alex Deymoa8033932014-02-25 10:33:13 -080086 // For VariableModePoll variables, it returns the polling interval of this
87 // variable. In other case, it returns 0.
88 base::TimeDelta GetPollInterval() const {
89 return poll_interval_;
90 }
91
Alex Deymoa07a1232014-02-25 14:19:50 -080092 // Adds and removes observers for value changes on the variable. This only
93 // works for kVariableAsync variables since the other modes don't track value
94 // changes. Adding the same observer twice has no effect.
Alex Deymo53556ec2014-03-17 10:05:57 -070095 virtual void AddObserver(BaseVariable::ObserverInterface* observer) {
Alex Deymoa07a1232014-02-25 14:19:50 -080096 if (std::find(observer_list_.begin(), observer_list_.end(), observer) ==
97 observer_list_.end()) {
98 observer_list_.push_back(observer);
99 }
100 }
101
Alex Deymo53556ec2014-03-17 10:05:57 -0700102 virtual void RemoveObserver(BaseVariable::ObserverInterface* observer) {
Alex Deymoa07a1232014-02-25 14:19:50 -0800103 observer_list_.remove(observer);
104 }
105
Alex Deymo0e433692014-02-20 07:23:03 -0800106 protected:
Alex Deymoa8033932014-02-25 10:33:13 -0800107 // Creates a BaseVariable using the default polling interval (5 minutes).
Alex Deymo0e433692014-02-20 07:23:03 -0800108 BaseVariable(const std::string& name, VariableMode mode)
Alex Deymoa8033932014-02-25 10:33:13 -0800109 : BaseVariable(name, mode,
110 base::TimeDelta::FromMinutes(kDefaultPollMinutes)) {}
111
112 // Creates a BaseVariable with mode kVariableModePoll and the provided
113 // polling interval.
114 BaseVariable(const std::string& name, base::TimeDelta poll_interval)
115 : BaseVariable(name, kVariableModePoll, poll_interval) {}
Alex Deymo0e433692014-02-20 07:23:03 -0800116
Alex Deymoa07a1232014-02-25 14:19:50 -0800117 // Calls ValueChanged on all the observers.
118 void NotifyValueChanged() {
Alex Deymo59d378d2014-04-17 12:53:43 -0700119 // Fire all the observer methods from the main loop as single call. In order
120 // to avoid scheduling these callbacks when it is not needed, we check
121 // first the list of observers.
122 if (!observer_list_.empty()) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700123 brillo::MessageLoop::current()->PostTask(
Alex Deymo0bb23412015-06-19 00:04:46 -0700124 FROM_HERE,
Alex Deymo509dd532015-06-10 14:11:05 -0700125 base::Bind(&BaseVariable::OnValueChangedNotification,
126 base::Unretained(this)));
Alex Deymo59d378d2014-04-17 12:53:43 -0700127 }
Alex Deymoa07a1232014-02-25 14:19:50 -0800128 }
129
Alex Deymo391ad9f2014-01-29 14:36:20 -0800130 private:
Alex Deymo63784a52014-05-28 10:46:14 -0700131 friend class UmEvaluationContextTest;
132 FRIEND_TEST(UmBaseVariableTest, RepeatedObserverTest);
133 FRIEND_TEST(UmBaseVariableTest, NotifyValueChangedTest);
134 FRIEND_TEST(UmBaseVariableTest, NotifyValueRemovesObserversTest);
Alex Deymoa07a1232014-02-25 14:19:50 -0800135
Alex Deymoa8033932014-02-25 10:33:13 -0800136 BaseVariable(const std::string& name, VariableMode mode,
137 base::TimeDelta poll_interval)
138 : name_(name), mode_(mode),
139 poll_interval_(mode == kVariableModePoll ?
140 poll_interval : base::TimeDelta()) {}
141
Alex Deymoa5856e42014-03-31 18:01:36 -0700142 void OnValueChangedNotification() {
143 // A ValueChanged() method can change the list of observers, for example
144 // removing itself and invalidating the iterator, so we create a snapshot
145 // of the observers first. Also, to support the case when *another* observer
146 // is removed, we check for them.
147 std::list<BaseVariable::ObserverInterface*> observer_list_copy(
148 observer_list_);
149
150 for (auto& observer : observer_list_copy) {
151 if (std::find(observer_list_.begin(), observer_list_.end(), observer) !=
152 observer_list_.end()) {
153 observer->ValueChanged(this);
154 }
155 }
156 }
157
Alex Deymoa8033932014-02-25 10:33:13 -0800158 // The default PollInterval in minutes.
159 static constexpr int kDefaultPollMinutes = 5;
160
Alex Deymo391ad9f2014-01-29 14:36:20 -0800161 // The variable's name as a string.
162 const std::string name_;
Alex Deymo0e433692014-02-20 07:23:03 -0800163
164 // The variable's mode.
165 const VariableMode mode_;
Alex Deymoa8033932014-02-25 10:33:13 -0800166
167 // The variable's polling interval for VariableModePoll variable and 0 for
168 // other modes.
169 const base::TimeDelta poll_interval_;
Alex Deymoa07a1232014-02-25 14:19:50 -0800170
171 // The list of value changes observers.
Alex Deymo53556ec2014-03-17 10:05:57 -0700172 std::list<BaseVariable::ObserverInterface*> observer_list_;
Alex Deymo231a8512014-03-21 12:56:10 -0700173
174 DISALLOW_COPY_AND_ASSIGN(BaseVariable);
Alex Deymo391ad9f2014-01-29 14:36:20 -0800175};
176
Alex Deymo63784a52014-05-28 10:46:14 -0700177// Interface to an Update Manager variable of a given type. Implementation
Alex Deymo391ad9f2014-01-29 14:36:20 -0800178// internals are hidden as protected members, since policies should not be
179// using them directly.
180template<typename T>
181class Variable : public BaseVariable {
182 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800183 ~Variable() override {}
Alex Deymo8c499142014-01-02 19:33:34 -0800184
185 protected:
Alex Deymo23949d42014-02-05 15:20:59 -0800186 // Only allow to get values through the EvaluationContext class and not
187 // directly from the variable.
188 friend class EvaluationContext;
189
Gilad Arnold67ed78d2014-04-23 13:17:46 -0700190 // Needed to be able to verify variable contents during unit testing.
Alex Deymo63784a52014-05-28 10:46:14 -0700191 friend class UmTestUtils;
192 FRIEND_TEST(UmRealRandomProviderTest, GetRandomValues);
Alex Deymoca0aaa62014-01-06 10:39:58 -0800193
Alex Deymo0e433692014-02-20 07:23:03 -0800194 Variable(const std::string& name, VariableMode mode)
195 : BaseVariable(name, mode) {}
196
Gilad Arnoldb6a039f2014-03-26 12:12:39 -0700197 Variable(const std::string& name, const base::TimeDelta poll_interval)
Alex Deymoa8033932014-02-25 10:33:13 -0800198 : BaseVariable(name, poll_interval) {}
199
Alex Deymo8c499142014-01-02 19:33:34 -0800200 // Gets the current value of the variable. The current value is copied to a
201 // new object and returned. The caller of this method owns the object and
202 // should delete it.
203 //
204 // In case of and error getting the current value or the |timeout| timeout is
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700205 // exceeded, a null value is returned and the |errmsg| is set.
Alex Deymo8c499142014-01-02 19:33:34 -0800206 //
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700207 // The caller can pass a null value for |errmsg|, in which case the error
Alex Deymo8c499142014-01-02 19:33:34 -0800208 // message won't be set.
209 virtual const T* GetValue(base::TimeDelta timeout, std::string* errmsg) = 0;
Alex Deymo231a8512014-03-21 12:56:10 -0700210
211 private:
212 DISALLOW_COPY_AND_ASSIGN(Variable);
Alex Deymo8c499142014-01-02 19:33:34 -0800213};
214
Alex Deymo63784a52014-05-28 10:46:14 -0700215} // namespace chromeos_update_manager
Alex Deymo8c499142014-01-02 19:33:34 -0800216
Gilad Arnold48415f12014-06-27 07:10:58 -0700217#endif // UPDATE_ENGINE_UPDATE_MANAGER_VARIABLE_H_