blob: 44b0d25682d11a206d2a55c35633ef68ef6e6816 [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
Alex Deymo63784a52014-05-28 10:46:14 -07005#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_
6#define CHROMEOS_PLATFORM_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) {
Alex Deymoc705cc82014-02-19 11:15:00 -080024 std::string error;
Gilad Arnoldb3b05442014-05-30 14:25:05 -070025 const std::string policy_name = policy_->PolicyRequestName(policy_method);
Alex Deymoc705cc82014-02-19 11:15:00 -080026
27 // First try calling the actual policy.
Gilad Arnoldb3b05442014-05-30 14:25:05 -070028 LOG(INFO) << "Evaluating " << policy_name << " START";
Alex Deymo7b948f02014-03-10 17:01:10 -070029 EvalStatus status = (policy_.get()->*policy_method)(ec, state_.get(), &error,
Alex Deymo2de23f52014-02-26 14:30:13 -080030 result, args...);
Alex Deymoc705cc82014-02-19 11:15:00 -080031
Alex Deymoe636c3c2014-03-11 19:02:08 -070032 if (status == EvalStatus::kFailed) {
Gilad Arnold897b5e52014-05-21 09:37:18 -070033 LOG(WARNING) << "Policy request failed: " << error;
Alex Deymoc705cc82014-02-19 11:15:00 -080034 error.clear();
Alex Deymo7b948f02014-03-10 17:01:10 -070035 status = (default_policy_.*policy_method)(ec, state_.get(), &error,
Alex Deymo2de23f52014-02-26 14:30:13 -080036 result, args...);
Alex Deymoc705cc82014-02-19 11:15:00 -080037
Alex Deymoe636c3c2014-03-11 19:02:08 -070038 if (status == EvalStatus::kFailed) {
Gilad Arnold897b5e52014-05-21 09:37:18 -070039 LOG(WARNING) << "Request to default policy also failed: " << error;
Alex Deymoc705cc82014-02-19 11:15:00 -080040 }
41 }
Gilad Arnoldb3b05442014-05-30 14:25:05 -070042 LOG(INFO) << "Evaluating " << policy_name << " END";
43
Alex Deymoc705cc82014-02-19 11:15:00 -080044 // TODO(deymo): Log the actual state used from the EvaluationContext.
45 return status;
46}
47
Alex Deymoe75e0252014-04-08 14:00:11 -070048template<typename R, typename... Args>
Alex Deymo63784a52014-05-28 10:46:14 -070049void UpdateManager::OnPolicyReadyToEvaluate(
Alex Deymo7b948f02014-03-10 17:01:10 -070050 scoped_refptr<EvaluationContext> ec,
51 base::Callback<void(EvalStatus status, const R& result)> callback,
Gilad Arnold13a82432014-05-19 12:52:44 -070052 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
53 std::string*, R*,
54 Args...) const,
Alex Deymoe75e0252014-04-08 14:00:11 -070055 Args... args) {
Alex Deymo41a75a72014-04-15 15:36:22 -070056 ec->ResetEvaluation();
Alex Deymo7b948f02014-03-10 17:01:10 -070057 R result;
58 EvalStatus status = EvaluatePolicy(ec, policy_method, &result, args...);
59
60 if (status != EvalStatus::kAskMeAgainLater) {
61 // AsyncPolicyRequest finished.
62 callback.Run(status, result);
63 return;
64 }
Alex Deymo53556ec2014-03-17 10:05:57 -070065 // Re-schedule the policy request based on used variables.
Alex Deymo7b948f02014-03-10 17:01:10 -070066 base::Closure closure = base::Bind(
Alex Deymo63784a52014-05-28 10:46:14 -070067 &UpdateManager::OnPolicyReadyToEvaluate<R, Args...>,
Alex Deymo7b948f02014-03-10 17:01:10 -070068 base::Unretained(this), ec, callback, policy_method, args...);
Alex Deymo53556ec2014-03-17 10:05:57 -070069
70 if (!ec->RunOnValueChangeOrTimeout(closure)) {
71 // The policy method didn't use any non-const variable nor there's any
72 // time-based event that will change the status of evaluation. We call the
73 // callback with EvalStatus::kAskMeAgainLater.
74 LOG(ERROR) << "Policy implementation didn't use any non-const variable "
75 "but returned kAskMeAgainLater.";
76 callback.Run(EvalStatus::kAskMeAgainLater, result);
77 return;
78 }
Alex Deymo7b948f02014-03-10 17:01:10 -070079}
80
Gilad Arnold13a82432014-05-19 12:52:44 -070081template<typename R, typename... ActualArgs, typename... ExpectedArgs>
Alex Deymo63784a52014-05-28 10:46:14 -070082EvalStatus UpdateManager::PolicyRequest(
Gilad Arnold13a82432014-05-19 12:52:44 -070083 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
84 std::string*, R*,
85 ExpectedArgs...) const,
86 R* result, ActualArgs... args) {
Gilad Arnoldb2271992014-06-19 12:35:24 -070087 scoped_refptr<EvaluationContext> ec(
88 new EvaluationContext(clock_, evaluation_timeout_));
Alex Deymo7b948f02014-03-10 17:01:10 -070089 // A PolicyRequest allways consists on a single evaluation on a new
90 // EvaluationContext.
Gilad Arnold13a82432014-05-19 12:52:44 -070091 // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
92 // explicitly instantiate EvaluatePolicy with the latter in lieu of the
93 // former.
Gilad Arnold897b5e52014-05-21 09:37:18 -070094 EvalStatus ret = EvaluatePolicy<R, ExpectedArgs...>(ec, policy_method, result,
95 args...);
96 // Sync policy requests must not block, if they do then this is an error.
97 DCHECK(EvalStatus::kAskMeAgainLater != ret);
98 LOG_IF(WARNING, EvalStatus::kAskMeAgainLater == ret)
99 << "Sync request used with an async policy";
100 return ret;
Alex Deymo7b948f02014-03-10 17:01:10 -0700101}
102
Gilad Arnold13a82432014-05-19 12:52:44 -0700103template<typename R, typename... ActualArgs, typename... ExpectedArgs>
Alex Deymo63784a52014-05-28 10:46:14 -0700104void UpdateManager::AsyncPolicyRequest(
Alex Deymo7b948f02014-03-10 17:01:10 -0700105 base::Callback<void(EvalStatus, const R& result)> callback,
Gilad Arnold13a82432014-05-19 12:52:44 -0700106 EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
107 std::string*, R*,
108 ExpectedArgs...) const,
109 ActualArgs... args) {
Gilad Arnoldb2271992014-06-19 12:35:24 -0700110 scoped_refptr<EvaluationContext> ec =
111 new EvaluationContext(clock_, evaluation_timeout_);
Gilad Arnold13a82432014-05-19 12:52:44 -0700112 // IMPORTANT: To ensure that ActualArgs can be converted to ExpectedArgs, we
Alex Deymo63784a52014-05-28 10:46:14 -0700113 // explicitly instantiate UpdateManager::OnPolicyReadyToEvaluate with the
Gilad Arnold13a82432014-05-19 12:52:44 -0700114 // latter in lieu of the former.
Alex Deymo7b948f02014-03-10 17:01:10 -0700115 base::Closure closure = base::Bind(
Alex Deymo63784a52014-05-28 10:46:14 -0700116 &UpdateManager::OnPolicyReadyToEvaluate<R, ExpectedArgs...>,
Alex Deymo7b948f02014-03-10 17:01:10 -0700117 base::Unretained(this), ec, callback, policy_method, args...);
118 RunFromMainLoop(closure);
119}
120
Alex Deymo63784a52014-05-28 10:46:14 -0700121} // namespace chromeos_update_manager
Alex Deymoc705cc82014-02-19 11:15:00 -0800122
Alex Deymo63784a52014-05-28 10:46:14 -0700123#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_INL_H_