blob: 90855adcf98b861a420800d5a43355c4a743e1fc [file] [log] [blame]
Alex Deymo23949d42014-02-05 15:20:59 -08001// 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#include "update_engine/policy_manager/evaluation_context.h"
6
Alex Deymo53556ec2014-03-17 10:05:57 -07007#include <base/bind.h>
8
9using base::Closure;
Alex Deymo23949d42014-02-05 15:20:59 -080010using base::TimeDelta;
11
12namespace chromeos_policy_manager {
13
Alex Deymo53556ec2014-03-17 10:05:57 -070014EvaluationContext::~EvaluationContext() {
15 RemoveObserversAndTimeout();
16}
17
18void EvaluationContext::RemoveObserversAndTimeout() {
19 for (auto& it : value_cache_) {
20 if (it.first->GetMode() == kVariableModeAsync)
21 it.first->RemoveObserver(this);
22 }
23 CancelMainLoopEvent(poll_timeout_event_);
24 poll_timeout_event_ = kEventIdNull;
25}
26
Alex Deymo23949d42014-02-05 15:20:59 -080027TimeDelta EvaluationContext::RemainingTime() const {
28 // TODO(deymo): Return a timeout based on the elapsed time on the current
29 // policy request evaluation.
30 return TimeDelta::FromSeconds(1.);
31}
32
Alex Deymo53556ec2014-03-17 10:05:57 -070033void EvaluationContext::ValueChanged(BaseVariable* var) {
34 DLOG(INFO) << "ValueChanged for variable " << var->GetName();
35 OnValueChangedOrPollTimeout();
36}
37
38void EvaluationContext::OnPollTimeout() {
39 DLOG(INFO) << "OnPollTimeout() called.";
40 poll_timeout_event_ = kEventIdNull;
41 OnValueChangedOrPollTimeout();
42}
43
44void EvaluationContext::OnValueChangedOrPollTimeout() {
45 RemoveObserversAndTimeout();
46 // Remove the cached values of non-const variables
47 for (auto it = value_cache_.begin(); it != value_cache_.end(); ) {
48 if (it->first->GetMode() == kVariableModeConst) {
49 ++it;
50 } else {
51 it = value_cache_.erase(it);
52 }
53 }
54
55 if (value_changed_callback_.get() != NULL) {
56 value_changed_callback_->Run();
57 value_changed_callback_.reset();
58 }
59}
60
61bool EvaluationContext::RunOnValueChangeOrTimeout(Closure callback) {
62 TimeDelta reeval_timeout;
63 bool reeval_timeout_set = false;
64 bool waiting_for_value_change = false;
65
66 if (value_changed_callback_.get() != NULL) {
67 LOG(ERROR) << "RunOnValueChangeOrTimeout called more than once.";
68 return false;
69 }
70
71 for (auto& it : value_cache_) {
72 switch (it.first->GetMode()) {
73 case kVariableModeAsync:
74 waiting_for_value_change = true;
75 DLOG(INFO) << "Waiting for value on " << it.first->GetName();
76 it.first->AddObserver(this);
77 break;
78 case kVariableModePoll:
79 if (!reeval_timeout_set || reeval_timeout > it.first->GetPollInterval())
80 reeval_timeout = it.first->GetPollInterval();
81 reeval_timeout_set = true;
82 break;
83 case kVariableModeConst:
84 // Ignored.
85 break;
86 }
87 }
88 // Check if the re-evaluation is actually being scheduled. If there are no
89 // events waited for, this function should return false.
90 if (!waiting_for_value_change && !reeval_timeout_set)
91 return false;
92 if (reeval_timeout_set) {
93 poll_timeout_event_ = RunFromMainLoopAfterTimeout(
Alex Deymodb799532014-03-21 13:00:00 -070094 base::Bind(&EvaluationContext::OnPollTimeout,
95 weak_ptr_factory_.GetWeakPtr()),
Alex Deymo53556ec2014-03-17 10:05:57 -070096 reeval_timeout);
97 }
98
99 value_changed_callback_.reset(new Closure(callback));
100 return true;
101}
102
Alex Deymo23949d42014-02-05 15:20:59 -0800103} // namespace chromeos_policy_manager