blob: 649dcff08b1e230533d8034582b64ae249efc226 [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 Arnoldfd45a732014-08-07 15:53:46 -070024 // If expiration timeout fired, dump the context and reset expiration.
25 // IMPORTANT: We must still proceed with evaluation of the policy in this
26 // case, so that the evaluation time (and corresponding reevaluation timeouts)
27 // are readjusted.
28 if (ec->is_expired()) {
29 LOG(WARNING) << "Request timed out, evaluation context: "
30 << ec->DumpContext();
31 ec->ResetExpiration();
32 }
Alex Deymoc705cc82014-02-19 11:15:00 -080033
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070034 // Reset the evaluation context.
35 ec->ResetEvaluation();
36
Gilad Arnoldfd45a732014-08-07 15:53:46 -070037 const std::string policy_name = policy_->PolicyRequestName(policy_method);
38 LOG(INFO) << policy_name << ": START";
Alex Deymoc705cc82014-02-19 11:15:00 -080039
Gilad Arnoldfd45a732014-08-07 15:53:46 -070040 // First try calling the actual policy.
41 std::string error;
42 EvalStatus status = (policy_.get()->*policy_method)(ec, state_.get(), &error,
43 result, args...);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070044 // If evaluating the main policy failed, defer to the default policy.
Alex Deymoe636c3c2014-03-11 19:02:08 -070045 if (status == EvalStatus::kFailed) {
Gilad Arnoldfd45a732014-08-07 15:53:46 -070046 LOG(WARNING) << "Evaluating policy failed: " << error
47 << "\nEvaluation context: " << ec->DumpContext();
48 error.clear();
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070049 status = (default_policy_.*policy_method)(ec, state_.get(), &error, result,
50 args...);
Gilad Arnoldfd45a732014-08-07 15:53:46 -070051 if (status == EvalStatus::kFailed) {
52 LOG(WARNING) << "Evaluating default policy failed: " << error;
53 } else if (status == EvalStatus::kAskMeAgainLater) {
54 LOG(ERROR)
55 << "Default policy would block; this is a bug, forcing failure.";
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070056 status = EvalStatus::kFailed;
Alex Deymoc705cc82014-02-19 11:15:00 -080057 }
58 }
Gilad Arnoldf9f85d62014-06-19 18:07:01 -070059
Gilad Arnoldfd45a732014-08-07 15:53:46 -070060 LOG(INFO) << policy_name << ": END";
Gilad Arnoldb3b05442014-05-30 14:25:05 -070061
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 Arnold13a82432014-05-19 12:52:44 -0700125 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
126 std::string*, R*,
127 ExpectedArgs...) const,
128 ActualArgs... args) {
Gilad Arnoldb2271992014-06-19 12:35:24 -0700129 scoped_refptr<EvaluationContext> ec =
Gilad Arnoldfd45a732014-08-07 15:53:46 -0700130 new EvaluationContext(clock_, evaluation_timeout_, expiration_timeout_);
Gilad Arnold13a82432014-05-19 12:52:44 -0700131 // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
Alex Deymo63784a52014-05-28 10:46:14 -0700132 // explicitly instantiate UpdateManager::OnPolicyReadyToEvaluate with the
Gilad Arnold13a82432014-05-19 12:52:44 -0700133 // latter in lieu of the former.
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700134 base::Closure eval_callback = base::Bind(
Alex Deymo63784a52014-05-28 10:46:14 -0700135 &UpdateManager::OnPolicyReadyToEvaluate<R, ExpectedArgs...>,
Alex Deymo7b948f02014-03-10 17:01:10 -0700136 base::Unretained(this), ec, callback, policy_method, args...);
Gilad Arnoldf9f85d62014-06-19 18:07:01 -0700137 RunFromMainLoop(eval_callback);
Alex Deymo7b948f02014-03-10 17:01:10 -0700138}
139
Alex Deymo63784a52014-05-28 10:46:14 -0700140} // namespace chromeos_update_manager
Alex Deymoc705cc82014-02-19 11:15:00 -0800141
Gilad Arnold48415f12014-06-27 07:10:58 -0700142#endif // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_