blob: 982ec930ae2af98cdfe8dbf014cb9c7f61f25b86 [file] [log] [blame]
Alex Deymoc705cc82014-02-19 11:15:00 -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
Gilad Arnold48415f12014-06-27 07:10:58 -07005#ifndef UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_
6#define UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_
Alex Deymoc705cc82014-02-19 11:15:00 -08007
Alex Deymo53556ec2014-03-17 10:05:57 -07008#include <string>
9
Alex Deymo7b948f02014-03-10 17:01:10 -070010#include <base/bind.h>
11
Alex Deymo63784a52014-05-28 10:46:14 -070012#include "update_engine/update_manager/evaluation_context.h"
13#include "update_engine/update_manager/event_loop.h"
Alex Deymoc705cc82014-02-19 11:15:00 -080014
Alex Deymo63784a52014-05-28 10:46:14 -070015namespace chromeos_update_manager {
Alex Deymoc705cc82014-02-19 11:15:00 -080016
Alex Deymoe75e0252014-04-08 14:00:11 -070017template<typename R, typename... Args>
Alex Deymo63784a52014-05-28 10:46:14 -070018EvalStatus UpdateManager::EvaluatePolicy(
Alex Deymoe75e0252014-04-08 14:00:11 -070019 EvaluationContext* ec,
Gilad Arnold13a82432014-05-19 12:52:44 -070020 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
21 std::string*, R*,
22 Args...) const,
Alex Deymoe75e0252014-04-08 14:00:11 -070023 R* result, Args... args) {
Gilad Arnoldb3b05442014-05-30 14:25:05 -070024 const std::string policy_name = policy_->PolicyRequestName(policy_method);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070025 const bool timed_out = ec->is_expired();
Alex Deymoc705cc82014-02-19 11:15:00 -080026
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070027 // Reset the evaluation context.
28 ec->ResetEvaluation();
29
Gilad Arnoldb3b05442014-05-30 14:25:05 -070030 LOG(INFO) << "Evaluating " << policy_name << " START";
Alex Deymoc705cc82014-02-19 11:15:00 -080031
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070032 // First try calling the actual policy, if the request did not time out.
33 EvalStatus status = EvalStatus::kFailed;
34 if (timed_out) {
35 LOG(WARNING) << "Skipping reevaluation because the request timed out.";
36 } else {
37 std::string error;
38 status = (policy_.get()->*policy_method)(ec, state_.get(), &error, result,
39 args...);
40 LOG_IF(WARNING, status == EvalStatus::kFailed)
Gilad Arnold6e5ab5c2014-06-23 15:13:56 -070041 << "Evaluating policy failed: " << error
42 << "\nEvaluation context: " << ec->DumpContext();
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070043 }
44
45 // If evaluating the main policy failed, defer to the default policy.
Alex Deymoe636c3c2014-03-11 19:02:08 -070046 if (status == EvalStatus::kFailed) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070047 std::string error;
48 status = (default_policy_.*policy_method)(ec, state_.get(), &error, result,
49 args...);
50 LOG_IF(WARNING, status == EvalStatus::kFailed)
51 << "Evaluating default policy failed: " << error;
Alex Deymoc705cc82014-02-19 11:15:00 -080052
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070053 if (timed_out && status == EvalStatus::kAskMeAgainLater) {
54 LOG(WARNING) << "Default policy would block but request timed out, "
55 << "forcing failure.";
56 status = EvalStatus::kFailed;
Alex Deymoc705cc82014-02-19 11:15:00 -080057 }
58 }
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070059
Gilad Arnoldb3b05442014-05-30 14:25:05 -070060 LOG(INFO) << "Evaluating " << policy_name << " END";
61
Alex Deymoc705cc82014-02-19 11:15:00 -080062 return status;
63}
64
Alex Deymoe75e0252014-04-08 14:00:11 -070065template<typename R, typename... Args>
Alex Deymo63784a52014-05-28 10:46:14 -070066void UpdateManager::OnPolicyReadyToEvaluate(
Alex Deymo7b948f02014-03-10 17:01:10 -070067 scoped_refptr<EvaluationContext> ec,
68 base::Callback<void(EvalStatus status, const R& result)> callback,
Gilad Arnold13a82432014-05-19 12:52:44 -070069 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
70 std::string*, R*,
71 Args...) const,
Alex Deymoe75e0252014-04-08 14:00:11 -070072 Args... args) {
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070073 // Evaluate the policy.
Alex Deymo7b948f02014-03-10 17:01:10 -070074 R result;
75 EvalStatus status = EvaluatePolicy(ec, policy_method, &result, args...);
76
77 if (status != EvalStatus::kAskMeAgainLater) {
78 // AsyncPolicyRequest finished.
79 callback.Run(status, result);
80 return;
81 }
Alex Deymo53556ec2014-03-17 10:05:57 -070082
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070083 // Re-schedule the policy request based on used variables.
84 base::Closure reeval_callback = base::Bind(
85 &UpdateManager::OnPolicyReadyToEvaluate<R, Args...>,
86 base::Unretained(this), ec, callback,
87 policy_method, args...);
88 if (ec->RunOnValueChangeOrTimeout(reeval_callback))
89 return; // Reevaluation scheduled successfully.
90
91 // Scheduling a reevaluation can fail because policy method didn't use any
92 // non-const variable nor there's any time-based event that will change the
93 // status of evaluation. Alternatively, this may indicate an error in the use
94 // of the scheduling interface.
95 LOG(ERROR) << "Failed to schedule a reevaluation of policy "
96 << policy_->PolicyRequestName(policy_method) << "; this is a bug.";
97 callback.Run(status, result);
Alex Deymo7b948f02014-03-10 17:01:10 -070098}
99
Gilad Arnold13a82432014-05-19 12:52:44 -0700100template<typename R, typename... ActualArgs, typename... ExpectedArgs>
Alex Deymo63784a52014-05-28 10:46:14 -0700101EvalStatus UpdateManager::PolicyRequest(
Gilad Arnold13a82432014-05-19 12:52:44 -0700102 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
103 std::string*, R*,
104 ExpectedArgs...) const,
105 R* result, ActualArgs... args) {
Gilad Arnoldb2271992014-06-19 12:35:24 -0700106 scoped_refptr<EvaluationContext> ec(
107 new EvaluationContext(clock_, evaluation_timeout_));
Alex Vakulenko072359c2014-07-18 11:41:07 -0700108 // A PolicyRequest always consists on a single evaluation on a new
Alex Deymo7b948f02014-03-10 17:01:10 -0700109 // EvaluationContext.
Gilad Arnold13a82432014-05-19 12:52:44 -0700110 // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
111 // explicitly instantiate EvaluatePolicy with the latter in lieu of the
112 // former.
Gilad Arnold897b5e52014-05-21 09:37:18 -0700113 EvalStatus ret = EvaluatePolicy<R, ExpectedArgs...>(ec, policy_method, result,
114 args...);
115 // Sync policy requests must not block, if they do then this is an error.
116 DCHECK(EvalStatus::kAskMeAgainLater != ret);
117 LOG_IF(WARNING, EvalStatus::kAskMeAgainLater == ret)
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700118 << "Sync request used with an async policy; this is a bug";
Gilad Arnold897b5e52014-05-21 09:37:18 -0700119 return ret;
Alex Deymo7b948f02014-03-10 17:01:10 -0700120}
121
Gilad Arnold13a82432014-05-19 12:52:44 -0700122template<typename R, typename... ActualArgs, typename... ExpectedArgs>
Alex Deymo63784a52014-05-28 10:46:14 -0700123void UpdateManager::AsyncPolicyRequest(
Alex Deymo7b948f02014-03-10 17:01:10 -0700124 base::Callback<void(EvalStatus, const R& result)> callback,
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700125 base::TimeDelta request_timeout,
Gilad Arnold13a82432014-05-19 12:52:44 -0700126 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
127 std::string*, R*,
128 ExpectedArgs...) const,
129 ActualArgs... args) {
Gilad Arnoldb2271992014-06-19 12:35:24 -0700130 scoped_refptr<EvaluationContext> ec =
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700131 new EvaluationContext(clock_, evaluation_timeout_, request_timeout);
Gilad Arnold13a82432014-05-19 12:52:44 -0700132 // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
Alex Deymo63784a52014-05-28 10:46:14 -0700133 // explicitly instantiate UpdateManager::OnPolicyReadyToEvaluate with the
Gilad Arnold13a82432014-05-19 12:52:44 -0700134 // latter in lieu of the former.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700135 base::Closure eval_callback = base::Bind(
Alex Deymo63784a52014-05-28 10:46:14 -0700136 &UpdateManager::OnPolicyReadyToEvaluate<R, ExpectedArgs...>,
Alex Deymo7b948f02014-03-10 17:01:10 -0700137 base::Unretained(this), ec, callback, policy_method, args...);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700138 RunFromMainLoop(eval_callback);
Alex Deymo7b948f02014-03-10 17:01:10 -0700139}
140
Alex Deymo63784a52014-05-28 10:46:14 -0700141} // namespace chromeos_update_manager
Alex Deymoc705cc82014-02-19 11:15:00 -0800142
Gilad Arnold48415f12014-06-27 07:10:58 -0700143#endif // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_