evaluation_context.h revision a65fced5f4c2b551616b26ee90a800b44090735f
1// Copyright (c) 2014 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_UPDATE_MANAGER_EVALUATION_CONTEXT_H_ 6#define UPDATE_ENGINE_UPDATE_MANAGER_EVALUATION_CONTEXT_H_ 7 8#include <map> 9#include <string> 10 11#include <base/callback.h> 12#include <base/memory/ref_counted.h> 13#include <base/memory/scoped_ptr.h> 14#include <base/memory/weak_ptr.h> 15#include <base/time/time.h> 16 17#include "update_engine/clock_interface.h" 18#include "update_engine/update_manager/boxed_value.h" 19#include "update_engine/update_manager/event_loop.h" 20#include "update_engine/update_manager/variable.h" 21 22namespace chromeos_update_manager { 23 24// The EvaluationContext class is the interface between a policy implementation 25// and the state. The EvaluationContext tracks the variables used by a policy 26// request and caches the returned values, owning those cached values. 27// The same EvaluationContext should be re-used for all the evaluations of the 28// same policy request (an AsyncPolicyRequest might involve several 29// re-evaluations). Each evaluation of the EvaluationContext is run at a given 30// point in time, which is used as a reference for the evaluation timeout and 31// the time based queries of the policy, such as 32// Is{Wallclock,Monotonic}TimeGreaterThan(). 33// 34// Example: 35// 36// scoped_refptr<EvaluationContext> ec = new EvaluationContext(...); 37// 38// ... 39// // The following call to ResetEvaluation() is optional. Use it to reset the 40// // evaluation time if the EvaluationContext isn't used right after its 41// // construction. 42// ec->ResetEvaluation(); 43// EvalStatus status = policy->SomeMethod(ec, state, &result, args...); 44// 45// ... 46// // Run a closure when any of the used async variables changes its value or 47// // the timeout for re-query the values happens again. 48// ec->RunOnValueChangeOrTimeout(closure); 49// // If the provided |closure| wants to re-evaluate the policy, it should 50// // call ec->ResetEvaluation() to start a new evaluation. 51// 52class EvaluationContext : public base::RefCounted<EvaluationContext>, 53 private BaseVariable::ObserverInterface { 54 public: 55 EvaluationContext(chromeos_update_engine::ClockInterface* clock, 56 base::TimeDelta evaluation_timeout, 57 base::TimeDelta expiration_timeout); 58 EvaluationContext(chromeos_update_engine::ClockInterface* clock, 59 base::TimeDelta evaluation_timeout) 60 : EvaluationContext(clock, evaluation_timeout, base::TimeDelta::Max()) {} 61 ~EvaluationContext(); 62 63 // Returns a pointer to the value returned by the passed variable |var|. The 64 // EvaluationContext instance keeps the ownership of the returned object. The 65 // returned object is valid during the life of the evaluation, even if the 66 // passed Variable changes it. 67 // 68 // In case of error, a NULL value is returned. 69 template<typename T> 70 const T* GetValue(Variable<T>* var); 71 72 // Returns whether the evaluation time has surpassed |timestamp|, on either 73 // the ClockInterface::GetWallclockTime() or 74 // ClockInterface::GetMonotonicTime() scales, respectively. 75 bool IsWallclockTimeGreaterThan(base::Time timestamp); 76 bool IsMonotonicTimeGreaterThan(base::Time timestamp); 77 78 // Returns whether the evaluation context has expired. 79 bool is_expired() const { return is_expired_; } 80 81 // TODO(deymo): Move the following methods to an interface only visible by the 82 // UpdateManager class and not the policy implementations. 83 84 // Resets the EvaluationContext to its initial state removing all the 85 // non-const cached variables and re-setting the evaluation time. This should 86 // be called right before any new evaluation starts. 87 void ResetEvaluation(); 88 89 // Schedules the passed |callback| closure to be called when a cached 90 // variable changes its value, a polling interval passes, or the context 91 // expiration occurs. If none of these events can happen, for example if 92 // there's no cached variable, this method returns false. 93 // 94 // Right before the passed closure is called the EvaluationContext is 95 // reseted, removing all the non-const cached values. 96 bool RunOnValueChangeOrTimeout(base::Closure callback); 97 98 // Returns a textual representation of the evaluation context, 99 // including the variables and their values. This is intended only 100 // to help with debugging and the format may change in the future. 101 std::string DumpContext() const; 102 103 private: 104 friend class UmEvaluationContextTest; 105 106 // Removes all the Observers and timeout callbacks scheduled by 107 // RunOnValueChangeOrTimeout(). This method is idempotent. 108 void RemoveObserversAndTimeout(); 109 110 // BaseVariable::ObserverInterface override. 111 void ValueChanged(BaseVariable* var); 112 113 // Called from the main loop when a scheduled timeout has passed. 114 void OnTimeout(); 115 116 // Removes the observers from the used Variables and cancels the timeout, 117 // then executes the scheduled callback. 118 void OnValueChangedOrTimeout(); 119 120 // If |monotonic_deadline| is not Time::Max(), returns the remaining time 121 // until it is reached, or zero if it has passed. Otherwise, returns 122 // TimeDelta::Max(). 123 base::TimeDelta RemainingTime(base::Time monotonic_deadline) const; 124 125 // Returns a monotonic clock timestamp at which |timeout| will have elapsed 126 // since the current time. 127 base::Time MonotonicDeadline(base::TimeDelta timeout); 128 129 // A map to hold the cached values for every variable. 130 typedef std::map<BaseVariable*, BoxedValue> ValueCacheMap; 131 132 // The cached values of the called Variables. 133 ValueCacheMap value_cache_; 134 135 // A callback used for triggering re-evaluation upon a value change or poll 136 // timeout, or notifying about the evaluation context expiration. It is up to 137 // the caller to determine whether or not expiration occurred via 138 // is_expired(). 139 scoped_ptr<base::Closure> callback_; 140 141 // The EventId returned by the event loop identifying the timeout callback. 142 // Used for canceling the timeout callback. 143 EventId timeout_event_ = kEventIdNull; 144 145 // Whether a timeout event firing marks the expiration of the evaluation 146 // context. 147 bool timeout_marks_expiration_; 148 149 // Whether the evaluation context has indeed expired. 150 bool is_expired_ = false; 151 152 // Pointer to the mockable clock interface; 153 chromeos_update_engine::ClockInterface* const clock_; 154 155 // The timestamps when the evaluation of this EvaluationContext started, 156 // corresponding to ClockInterface::GetWallclockTime() and 157 // ClockInterface::GetMonotonicTime(), respectively. These values are reset 158 // every time ResetEvaluation() is called. 159 base::Time evaluation_start_wallclock_; 160 base::Time evaluation_start_monotonic_; 161 162 // The timestamps when a reevaluation should be triggered due to various 163 // expected value changes, corresponding to ClockInterface::GetWallclockTime() 164 // and ClockInterface::GetMonotonicTIme(), respectively. These timestamps are 165 // greater or equal to corresponding |evaluation_start_{wallclock,monotonic}_| 166 // counterparts since they are in the future; however, they may be smaller 167 // than the current corresponding times during the course of evaluation. 168 base::Time reevaluation_time_wallclock_; 169 base::Time reevaluation_time_monotonic_; 170 171 // The timeout of an evaluation. 172 const base::TimeDelta evaluation_timeout_; 173 174 // The timestamp in the ClockInterface::GetMonotonicTime() scale at which the 175 // current evaluation should finish. 176 base::Time evaluation_monotonic_deadline_; 177 178 // The monotonic clock deadline at which expiration occurs. This is set once 179 // during construction. 180 const base::Time expiration_monotonic_deadline_; 181 182 base::WeakPtrFactory<EvaluationContext> weak_ptr_factory_; 183 184 DISALLOW_COPY_AND_ASSIGN(EvaluationContext); 185}; 186 187} // namespace chromeos_update_manager 188 189// Include the implementation of the template methods. 190#include "update_engine/update_manager/evaluation_context-inl.h" 191 192#endif // UPDATE_ENGINE_UPDATE_MANAGER_EVALUATION_CONTEXT_H_ 193