evaluation_context.cc revision 39910dcd1d68987ccee7c3031dc269233a8490bb
1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2014 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
1623949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
1763784a578dd26880454d70797519358a2326291bAlex Deymo#include "update_engine/update_manager/evaluation_context.h"
1823949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
19f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold#include <algorithm>
2002f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan#include <memory>
21c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen#include <string>
22c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
2353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo#include <base/bind.h>
24c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen#include <base/json/json_writer.h>
250bb234147ea8f0247b733375fcf1685eaf329aacAlex Deymo#include <base/location.h>
266e5ab5c011a214aa345ecbba3d910c2ffaec3c83Gilad Arnold#include <base/strings/string_util.h>
27c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen#include <base/values.h>
28c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
2939910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
3053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
3183ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnoldusing base::Callback;
3253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymousing base::Closure;
3341a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymousing base::Time;
3423949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymousing base::TimeDelta;
353f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkousing brillo::MessageLoop;
3641a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymousing chromeos_update_engine::ClockInterface;
37c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthenusing std::string;
3802f7c1dee242f490143791dbb73fa23fa3007cfaBen Chanusing std::unique_ptr;
3923949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
40a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnoldnamespace {
41a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
42a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// Returns whether |curr_time| surpassed |ref_time|; if not, also checks whether
43a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// |ref_time| is sooner than the current value of |*reeval_time|, in which case
44a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// the latter is updated to the former.
45f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool IsTimeGreaterThanHelper(Time ref_time, Time curr_time,
46f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                             Time* reeval_time) {
47a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  if (curr_time > ref_time)
48a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold    return true;
49a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // Remember the nearest reference we've checked against in this evaluation.
50a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  if (*reeval_time > ref_time)
51a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold    *reeval_time = ref_time;
52a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return false;
53a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}
54a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
55a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// If |expires| never happens (maximal value), returns the maximal interval;
56a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// otherwise, returns the difference between |expires| and |curr|.
57f329b933db41d26644a97afef928eb1b319d6d99Alex DeymoTimeDelta GetTimeout(Time curr, Time expires) {
58a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  if (expires.is_max())
59a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold    return TimeDelta::Max();
60a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return expires - curr;
61a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}
62a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
63a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}  // namespace
64a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
6563784a578dd26880454d70797519358a2326291bAlex Deymonamespace chromeos_update_manager {
6623949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
6783ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad ArnoldEvaluationContext::EvaluationContext(
6883ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    ClockInterface* clock,
6983ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    TimeDelta evaluation_timeout,
7083ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    TimeDelta expiration_timeout,
7102f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan    unique_ptr<Callback<void(EvaluationContext*)>> unregister_cb)
7241a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo    : clock_(clock),
73b227199133f2d694414293697c67599a761f23beGilad Arnold      evaluation_timeout_(evaluation_timeout),
74fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold      expiration_timeout_(expiration_timeout),
7502f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan      unregister_cb_(std::move(unregister_cb)),
7641a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo      weak_ptr_factory_(this) {
7741a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo  ResetEvaluation();
78fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold  ResetExpiration();
7941a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo}
8041a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
8153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex DeymoEvaluationContext::~EvaluationContext() {
8253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  RemoveObserversAndTimeout();
8383ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold  if (unregister_cb_.get())
8483ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    unregister_cb_->Run(this);
8553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
8653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
8702f7c1dee242f490143791dbb73fa23fa3007cfaBen Chanunique_ptr<Closure> EvaluationContext::RemoveObserversAndTimeout() {
8853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  for (auto& it : value_cache_) {
8953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    if (it.first->GetMode() == kVariableModeAsync)
9053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      it.first->RemoveObserver(this);
9153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
92509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  MessageLoop::current()->CancelTask(timeout_event_);
93509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  timeout_event_ = MessageLoop::kTaskIdNull;
9483ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold
9502f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan  return unique_ptr<Closure>(callback_.release());
9653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
9753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
98f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad ArnoldTimeDelta EvaluationContext::RemainingTime(Time monotonic_deadline) const {
99f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (monotonic_deadline.is_max())
100f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    return TimeDelta::Max();
101f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  TimeDelta remaining = monotonic_deadline - clock_->GetMonotonicTime();
102f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  return std::max(remaining, TimeDelta());
103f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold}
104f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
105f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad ArnoldTime EvaluationContext::MonotonicDeadline(TimeDelta timeout) {
106f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  return (timeout.is_max() ? Time::Max() :
107f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold          clock_->GetMonotonicTime() + timeout);
10823949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo}
10923949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
11053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymovoid EvaluationContext::ValueChanged(BaseVariable* var) {
111f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  DLOG(INFO) << "ValueChanged() called for variable " << var->GetName();
112f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  OnValueChangedOrTimeout();
11353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
11453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
115f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnoldvoid EvaluationContext::OnTimeout() {
116f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  DLOG(INFO) << "OnTimeout() called due to "
117f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold             << (timeout_marks_expiration_ ? "expiration" : "poll interval");
118509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  timeout_event_ = MessageLoop::kTaskIdNull;
119f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  is_expired_ = timeout_marks_expiration_;
120f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  OnValueChangedOrTimeout();
12153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
12253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
123f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnoldvoid EvaluationContext::OnValueChangedOrTimeout() {
124f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Copy the callback handle locally, allowing it to be reassigned.
12502f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan  unique_ptr<Closure> callback = RemoveObserversAndTimeout();
126f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
127f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (callback.get())
128fb794f4b7274576e10b0df291655ad6c88a97df4Gilad Arnold    callback->Run();
12941a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo}
13041a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
131f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool EvaluationContext::IsWallclockTimeGreaterThan(Time timestamp) {
132a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return IsTimeGreaterThanHelper(timestamp, evaluation_start_wallclock_,
133a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold                                 &reevaluation_time_wallclock_);
134a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}
135a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
136f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool EvaluationContext::IsMonotonicTimeGreaterThan(Time timestamp) {
137a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return IsTimeGreaterThanHelper(timestamp, evaluation_start_monotonic_,
138a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold                                 &reevaluation_time_monotonic_);
13941a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo}
14041a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
14141a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymovoid EvaluationContext::ResetEvaluation() {
142a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  evaluation_start_wallclock_ = clock_->GetWallclockTime();
143a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  evaluation_start_monotonic_ = clock_->GetMonotonicTime();
144a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  reevaluation_time_wallclock_ = Time::Max();
145a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  reevaluation_time_monotonic_ = Time::Max();
146f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  evaluation_monotonic_deadline_ = MonotonicDeadline(evaluation_timeout_);
14741a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
14853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  // Remove the cached values of non-const variables
14953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  for (auto it = value_cache_.begin(); it != value_cache_.end(); ) {
15053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    if (it->first->GetMode() == kVariableModeConst) {
15153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      ++it;
15253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    } else {
15353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      it = value_cache_.erase(it);
15453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    }
15553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
15653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
15753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
158fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnoldvoid EvaluationContext::ResetExpiration() {
159fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold  expiration_monotonic_deadline_ = MonotonicDeadline(expiration_timeout_);
160fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold  is_expired_ = false;
161fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold}
162fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold
16353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymobool EvaluationContext::RunOnValueChangeOrTimeout(Closure callback) {
164f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Check that the method was not called more than once.
16588b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  if (callback_.get()) {
166f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    LOG(ERROR) << "RunOnValueChangeOrTimeout called more than once.";
167f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    return false;
16841a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo  }
16941a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
170f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Check that the context did not yet expire.
171f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (is_expired()) {
172f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    LOG(ERROR) << "RunOnValueChangeOrTimeout called on an expired context.";
17353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    return false;
17453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
17553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
176a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // Handle reevaluation due to a Is{Wallclock,Monotonic}TimeGreaterThan(). We
177a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // choose the smaller of the differences between evaluation start time and
178a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // reevaluation time among the wallclock and monotonic scales.
179a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  TimeDelta timeout = std::min(
180a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      GetTimeout(evaluation_start_wallclock_, reevaluation_time_wallclock_),
181a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      GetTimeout(evaluation_start_monotonic_, reevaluation_time_monotonic_));
182f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
183f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Handle reevaluation due to async or poll variables.
184a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  bool waiting_for_value_change = false;
18553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  for (auto& it : value_cache_) {
18653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    switch (it.first->GetMode()) {
18753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      case kVariableModeAsync:
18853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        DLOG(INFO) << "Waiting for value on " << it.first->GetName();
18953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        it.first->AddObserver(this);
190f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        waiting_for_value_change = true;
19153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        break;
19253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      case kVariableModePoll:
193f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        timeout = std::min(timeout, it.first->GetPollInterval());
19453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        break;
19553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      case kVariableModeConst:
19653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        // Ignored.
19753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        break;
19853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    }
19953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
200f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
20153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  // Check if the re-evaluation is actually being scheduled. If there are no
20253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  // events waited for, this function should return false.
203f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (!waiting_for_value_change && timeout.is_max())
20453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    return false;
205f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
206f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Ensure that we take into account the expiration timeout.
207f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  TimeDelta expiration = RemainingTime(expiration_monotonic_deadline_);
208f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  timeout_marks_expiration_ = expiration < timeout;
209f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (timeout_marks_expiration_)
210f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    timeout = expiration;
211f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
212f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Store the reevaluation callback.
213f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  callback_.reset(new Closure(callback));
214f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
215f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Schedule a timeout event, if one is set.
216f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (!timeout.is_max()) {
217f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    DLOG(INFO) << "Waiting for timeout in "
218f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold               << chromeos_update_engine::utils::FormatTimeDelta(timeout);
219509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo    timeout_event_ = MessageLoop::current()->PostDelayedTask(
2200bb234147ea8f0247b733375fcf1685eaf329aacAlex Deymo        FROM_HERE,
221f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        base::Bind(&EvaluationContext::OnTimeout,
222db799534a8f6ae061ed6d6a46ed800f55d50325bAlex Deymo                   weak_ptr_factory_.GetWeakPtr()),
223f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        timeout);
22453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
22553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
22653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  return true;
22753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
22853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
229c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthenstring EvaluationContext::DumpContext() const {
230c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  base::DictionaryValue* variables = new base::DictionaryValue();
231c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  for (auto& it : value_cache_) {
232c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen    variables->SetString(it.first->GetName(), it.second.ToString());
233c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  }
234c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
235c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  base::DictionaryValue value;
236c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  value.Set("variables", variables);  // Adopts |variables|.
237a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  value.SetString(
238a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      "evaluation_start_wallclock",
239a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      chromeos_update_engine::utils::ToString(evaluation_start_wallclock_));
240a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  value.SetString(
241a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      "evaluation_start_monotonic",
242a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      chromeos_update_engine::utils::ToString(evaluation_start_monotonic_));
243c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
244c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  string json_str;
2456a9d3497bcf57b8b9f5765a2909a51c9f8119cd1Alex Vakulenko  base::JSONWriter::WriteWithOptions(
2466a9d3497bcf57b8b9f5765a2909a51c9f8119cd1Alex Vakulenko      value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_str);
2476e5ab5c011a214aa345ecbba3d910c2ffaec3c83Gilad Arnold  base::TrimWhitespaceASCII(json_str, base::TRIM_TRAILING, &json_str);
248c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
249c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  return json_str;
250c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen}
251c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
25263784a578dd26880454d70797519358a2326291bAlex Deymo}  // namespace chromeos_update_manager
253