1 // 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 // 16 17 // Generic and provider-independent Variable subclasses. These variables can be 18 // used by any state provider to implement simple variables to avoid repeat the 19 // same common code on different state providers. 20 21 #ifndef UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ 22 #define UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ 23 24 #include <string> 25 26 #include <base/callback.h> 27 28 #include "update_engine/update_manager/variable.h" 29 30 namespace chromeos_update_manager { 31 32 // Variable class returning a copy of a given object using the copy constructor. 33 // This template class can be used to define variables that expose as a variable 34 // any fixed object, such as the a provider's private member. The variable will 35 // create copies of the provided object using the copy constructor of that 36 // class. 37 // 38 // For example, a state provider exposing a private member as a variable can 39 // implement this as follows: 40 // 41 // class SomethingProvider { 42 // public: 43 // SomethingProvider(...) { 44 // var_something_foo = new PollCopyVariable<MyType>(foo_); 45 // } 46 // ... 47 // private: 48 // MyType foo_; 49 // }; 50 template<typename T> 51 class PollCopyVariable : public Variable<T> { 52 public: 53 // Creates the variable returning copies of the passed |ref|. The reference to 54 // this object is kept and it should be available whenever the GetValue() 55 // method is called. If |is_set_p| is not null, then this flag will be 56 // consulted prior to returning the value, and an |errmsg| will be returned if 57 // it is not set. PollCopyVariable(const std::string & name,const T & ref,const bool * is_set_p,const std::string & errmsg)58 PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p, 59 const std::string& errmsg) 60 : Variable<T>(name, kVariableModePoll), ref_(ref), is_set_p_(is_set_p), 61 errmsg_(errmsg) {} PollCopyVariable(const std::string & name,const T & ref,const bool * is_set_p)62 PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p) 63 : PollCopyVariable(name, ref, is_set_p, std::string()) {} PollCopyVariable(const std::string & name,const T & ref)64 PollCopyVariable(const std::string& name, const T& ref) 65 : PollCopyVariable(name, ref, nullptr) {} 66 PollCopyVariable(const std::string & name,const base::TimeDelta poll_interval,const T & ref,const bool * is_set_p,const std::string & errmsg)67 PollCopyVariable(const std::string& name, const base::TimeDelta poll_interval, 68 const T& ref, const bool* is_set_p, 69 const std::string& errmsg) 70 : Variable<T>(name, poll_interval), ref_(ref), is_set_p_(is_set_p), 71 errmsg_(errmsg) {} PollCopyVariable(const std::string & name,const base::TimeDelta poll_interval,const T & ref,const bool * is_set_p)72 PollCopyVariable(const std::string& name, const base::TimeDelta poll_interval, 73 const T& ref, const bool* is_set_p) 74 : PollCopyVariable(name, poll_interval, ref, is_set_p, std::string()) {} PollCopyVariable(const std::string & name,const base::TimeDelta poll_interval,const T & ref)75 PollCopyVariable(const std::string& name, const base::TimeDelta poll_interval, 76 const T& ref) 77 : PollCopyVariable(name, poll_interval, ref, nullptr) {} 78 79 protected: 80 FRIEND_TEST(UmPollCopyVariableTest, SimpleTest); 81 FRIEND_TEST(UmPollCopyVariableTest, UseCopyConstructorTest); 82 83 // Variable override. GetValue(base::TimeDelta,std::string * errmsg)84 inline const T* GetValue(base::TimeDelta /* timeout */, 85 std::string* errmsg) override { 86 if (is_set_p_ && !(*is_set_p_)) { 87 if (errmsg) { 88 if (errmsg_.empty()) 89 *errmsg = "No value set for " + this->GetName(); 90 else 91 *errmsg = errmsg_; 92 } 93 return nullptr; 94 } 95 return new T(ref_); 96 } 97 98 private: 99 // Reference to the object to be copied by GetValue(). 100 const T& ref_; 101 102 // A pointer to a flag indicating whether the value is set. If null, then the 103 // value is assumed to be set. 104 const bool* const is_set_p_; 105 106 // An error message to be returned when attempting to get an unset value. 107 const std::string errmsg_; 108 }; 109 110 // Variable class returning a constant value that is cached on the variable when 111 // it is created. 112 template<typename T> 113 class ConstCopyVariable : public Variable<T> { 114 public: 115 // Creates the variable returning copies of the passed |obj|. The value passed 116 // is copied in this variable, and new copies of it will be returned by 117 // GetValue(). ConstCopyVariable(const std::string & name,const T & obj)118 ConstCopyVariable(const std::string& name, const T& obj) 119 : Variable<T>(name, kVariableModeConst), obj_(obj) {} 120 121 protected: 122 // Variable override. GetValue(base::TimeDelta,std::string *)123 const T* GetValue(base::TimeDelta /* timeout */, 124 std::string* /* errmsg */) override { 125 return new T(obj_); 126 } 127 128 private: 129 // Value to be copied by GetValue(). 130 const T obj_; 131 }; 132 133 // Variable class returning a copy of a value returned by a given function. The 134 // function is called every time the variable is being polled. 135 template<typename T> 136 class CallCopyVariable : public Variable<T> { 137 public: CallCopyVariable(const std::string & name,base::Callback<T (void)> func)138 CallCopyVariable(const std::string& name, base::Callback<T(void)> func) 139 : Variable<T>(name, kVariableModePoll), func_(func) {} CallCopyVariable(const std::string & name,const base::TimeDelta poll_interval,base::Callback<T (void)> func)140 CallCopyVariable(const std::string& name, 141 const base::TimeDelta poll_interval, 142 base::Callback<T(void)> func) 143 : Variable<T>(name, poll_interval), func_(func) {} 144 145 protected: 146 // Variable override. GetValue(base::TimeDelta,std::string *)147 const T* GetValue(base::TimeDelta /* timeout */, 148 std::string* /* errmsg */) override { 149 if (func_.is_null()) 150 return nullptr; 151 return new T(func_.Run()); 152 } 153 154 private: 155 FRIEND_TEST(UmCallCopyVariableTest, SimpleTest); 156 157 // The function to be called, stored as a base::Callback. 158 base::Callback<T(void)> func_; 159 160 DISALLOW_COPY_AND_ASSIGN(CallCopyVariable); 161 }; 162 163 164 // A Variable class to implement simple Async variables. It provides two methods 165 // SetValue and UnsetValue to modify the current value of the variable and 166 // notify the registered observers whenever the value changed. 167 // 168 // The type T needs to be copy-constructible, default-constructible and have an 169 // operator== (to determine if the value changed), which makes this class 170 // suitable for basic types. 171 template<typename T> 172 class AsyncCopyVariable : public Variable<T> { 173 public: AsyncCopyVariable(const std::string & name)174 explicit AsyncCopyVariable(const std::string& name) 175 : Variable<T>(name, kVariableModeAsync), has_value_(false) {} 176 AsyncCopyVariable(const std::string & name,const T value)177 AsyncCopyVariable(const std::string& name, const T value) 178 : Variable<T>(name, kVariableModeAsync), 179 has_value_(true), value_(value) {} 180 SetValue(const T & new_value)181 void SetValue(const T& new_value) { 182 bool should_notify = !(has_value_ && new_value == value_); 183 value_ = new_value; 184 has_value_ = true; 185 if (should_notify) 186 this->NotifyValueChanged(); 187 } 188 UnsetValue()189 void UnsetValue() { 190 if (has_value_) { 191 has_value_ = false; 192 this->NotifyValueChanged(); 193 } 194 } 195 196 protected: 197 // Variable override. GetValue(base::TimeDelta,std::string * errmsg)198 const T* GetValue(base::TimeDelta /* timeout */, 199 std::string* errmsg) override { 200 if (!has_value_) { 201 if (errmsg) 202 *errmsg = "No value set for " + this->GetName(); 203 return nullptr; 204 } 205 return new T(value_); 206 } 207 208 private: 209 // Whether the variable has a value set. 210 bool has_value_; 211 212 // Copy of the object to be returned by GetValue(). 213 T value_; 214 }; 215 216 } // namespace chromeos_update_manager 217 218 #endif // UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ 219