blob: 7109692b14ef9b0eb2fb3bf21e2bbd7079ee94ce [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
Xiyuan Xiaed9bd922016-04-07 14:45:16 -0700117 // Reset the poll interval on a polling variable to the given one.
118 void SetPollInterval(base::TimeDelta poll_interval) {
119 DCHECK_EQ(kVariableModePoll, mode_) << "Can't set the poll_interval on a "
120 << mode_ << " variable";
121 poll_interval_ = poll_interval;
122 }
123
Alex Deymoa07a1232014-02-25 14:19:50 -0800124 // Calls ValueChanged on all the observers.
125 void NotifyValueChanged() {
Alex Deymo59d378d2014-04-17 12:53:43 -0700126 // Fire all the observer methods from the main loop as single call. In order
127 // to avoid scheduling these callbacks when it is not needed, we check
128 // first the list of observers.
129 if (!observer_list_.empty()) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700130 brillo::MessageLoop::current()->PostTask(
Alex Deymo0bb23412015-06-19 00:04:46 -0700131 FROM_HERE,
Alex Deymo509dd532015-06-10 14:11:05 -0700132 base::Bind(&BaseVariable::OnValueChangedNotification,
133 base::Unretained(this)));
Alex Deymo59d378d2014-04-17 12:53:43 -0700134 }
Alex Deymoa07a1232014-02-25 14:19:50 -0800135 }
136
Alex Deymo391ad9f2014-01-29 14:36:20 -0800137 private:
Alex Deymo63784a52014-05-28 10:46:14 -0700138 friend class UmEvaluationContextTest;
139 FRIEND_TEST(UmBaseVariableTest, RepeatedObserverTest);
140 FRIEND_TEST(UmBaseVariableTest, NotifyValueChangedTest);
141 FRIEND_TEST(UmBaseVariableTest, NotifyValueRemovesObserversTest);
Alex Deymoa07a1232014-02-25 14:19:50 -0800142
Alex Deymoa8033932014-02-25 10:33:13 -0800143 BaseVariable(const std::string& name, VariableMode mode,
144 base::TimeDelta poll_interval)
145 : name_(name), mode_(mode),
146 poll_interval_(mode == kVariableModePoll ?
147 poll_interval : base::TimeDelta()) {}
148
Alex Deymoa5856e42014-03-31 18:01:36 -0700149 void OnValueChangedNotification() {
150 // A ValueChanged() method can change the list of observers, for example
151 // removing itself and invalidating the iterator, so we create a snapshot
152 // of the observers first. Also, to support the case when *another* observer
153 // is removed, we check for them.
154 std::list<BaseVariable::ObserverInterface*> observer_list_copy(
155 observer_list_);
156
157 for (auto& observer : observer_list_copy) {
158 if (std::find(observer_list_.begin(), observer_list_.end(), observer) !=
159 observer_list_.end()) {
160 observer->ValueChanged(this);
161 }
162 }
163 }
164
Alex Deymoa8033932014-02-25 10:33:13 -0800165 // The default PollInterval in minutes.
166 static constexpr int kDefaultPollMinutes = 5;
167
Alex Deymo391ad9f2014-01-29 14:36:20 -0800168 // The variable's name as a string.
169 const std::string name_;
Alex Deymo0e433692014-02-20 07:23:03 -0800170
171 // The variable's mode.
172 const VariableMode mode_;
Alex Deymoa8033932014-02-25 10:33:13 -0800173
174 // The variable's polling interval for VariableModePoll variable and 0 for
175 // other modes.
Xiyuan Xiaed9bd922016-04-07 14:45:16 -0700176 base::TimeDelta poll_interval_;
Alex Deymoa07a1232014-02-25 14:19:50 -0800177
178 // The list of value changes observers.
Alex Deymo53556ec2014-03-17 10:05:57 -0700179 std::list<BaseVariable::ObserverInterface*> observer_list_;
Alex Deymo231a8512014-03-21 12:56:10 -0700180
181 DISALLOW_COPY_AND_ASSIGN(BaseVariable);
Alex Deymo391ad9f2014-01-29 14:36:20 -0800182};
183
Alex Deymo63784a52014-05-28 10:46:14 -0700184// Interface to an Update Manager variable of a given type. Implementation
Alex Deymo391ad9f2014-01-29 14:36:20 -0800185// internals are hidden as protected members, since policies should not be
186// using them directly.
187template<typename T>
188class Variable : public BaseVariable {
189 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800190 ~Variable() override {}
Alex Deymo8c499142014-01-02 19:33:34 -0800191
192 protected:
Alex Deymo23949d42014-02-05 15:20:59 -0800193 // Only allow to get values through the EvaluationContext class and not
194 // directly from the variable.
195 friend class EvaluationContext;
196
Gilad Arnold67ed78d2014-04-23 13:17:46 -0700197 // Needed to be able to verify variable contents during unit testing.
Alex Deymo63784a52014-05-28 10:46:14 -0700198 friend class UmTestUtils;
199 FRIEND_TEST(UmRealRandomProviderTest, GetRandomValues);
Alex Deymoca0aaa62014-01-06 10:39:58 -0800200
Alex Deymo0e433692014-02-20 07:23:03 -0800201 Variable(const std::string& name, VariableMode mode)
202 : BaseVariable(name, mode) {}
203
Gilad Arnoldb6a039f2014-03-26 12:12:39 -0700204 Variable(const std::string& name, const base::TimeDelta poll_interval)
Alex Deymoa8033932014-02-25 10:33:13 -0800205 : BaseVariable(name, poll_interval) {}
206
Alex Deymo8c499142014-01-02 19:33:34 -0800207 // Gets the current value of the variable. The current value is copied to a
208 // new object and returned. The caller of this method owns the object and
209 // should delete it.
210 //
211 // In case of and error getting the current value or the |timeout| timeout is
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700212 // exceeded, a null value is returned and the |errmsg| is set.
Alex Deymo8c499142014-01-02 19:33:34 -0800213 //
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700214 // The caller can pass a null value for |errmsg|, in which case the error
Alex Deymo8c499142014-01-02 19:33:34 -0800215 // message won't be set.
216 virtual const T* GetValue(base::TimeDelta timeout, std::string* errmsg) = 0;
Alex Deymo231a8512014-03-21 12:56:10 -0700217
218 private:
219 DISALLOW_COPY_AND_ASSIGN(Variable);
Alex Deymo8c499142014-01-02 19:33:34 -0800220};
221
Alex Deymo63784a52014-05-28 10:46:14 -0700222} // namespace chromeos_update_manager
Alex Deymo8c499142014-01-02 19:33:34 -0800223
Gilad Arnold48415f12014-06-27 07:10:58 -0700224#endif // UPDATE_ENGINE_UPDATE_MANAGER_VARIABLE_H_