ronnie
2022-10-23 5a83b14855e763445ac36672c35ddb68300e4b42
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
 
#ifndef UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_
#define UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_
 
#include <memory>
#include <set>
#include <string>
 
#include <base/callback.h>
#include <base/memory/ref_counted.h>
#include <base/time/time.h>
 
#include "update_engine/common/clock_interface.h"
#include "update_engine/update_manager/default_policy.h"
#include "update_engine/update_manager/evaluation_context.h"
#include "update_engine/update_manager/policy.h"
#include "update_engine/update_manager/state.h"
 
namespace chromeos_update_manager {
 
// Comparator for scoped_refptr objects.
template <typename T>
struct ScopedRefPtrLess {
  bool operator()(const scoped_refptr<T>& first,
                  const scoped_refptr<T>& second) const {
    return first.get() < second.get();
  }
};
 
// The main Update Manager singleton class.
class UpdateManager {
 public:
  // Creates the UpdateManager instance, assuming ownership on the provided
  // |state|.
  UpdateManager(chromeos_update_engine::ClockInterface* clock,
                base::TimeDelta evaluation_timeout,
                base::TimeDelta expiration_timeout,
                State* state);
 
  virtual ~UpdateManager();
 
  // PolicyRequest() evaluates the given policy with the provided arguments and
  // returns the result. The |policy_method| is the pointer-to-method of the
  // Policy class for the policy request to call. The UpdateManager will call
  // this method on the right policy. The pointer |result| must not be null
  // and the remaining |args| depend on the arguments required by the passed
  // |policy_method|.
  //
  // When the policy request succeeds, the |result| is set and the method
  // returns EvalStatus::kSucceeded, otherwise, the |result| may not be set.  A
  // policy called with this method should not block (i.e. return
  // EvalStatus::kAskMeAgainLater), which is considered a programming error. On
  // failure, EvalStatus::kFailed is returned.
  //
  // An example call to this method is:
  //   um.PolicyRequest(&Policy::SomePolicyMethod, &bool_result, arg1, arg2);
  template <typename R, typename... ActualArgs, typename... ExpectedArgs>
  EvalStatus PolicyRequest(
      EvalStatus (Policy::*policy_method)(
          EvaluationContext*, State*, std::string*, R*, ExpectedArgs...) const,
      R* result,
      ActualArgs...);
 
  // Evaluates the given |policy_method| policy with the provided |args|
  // arguments and calls the |callback| callback with the result when done.
  //
  // If the policy implementation should block, returning a
  // EvalStatus::kAskMeAgainLater status the Update Manager will re-evaluate the
  // policy until another status is returned. If the policy implementation based
  // its return value solely on const variables, the callback will be called
  // with the EvalStatus::kAskMeAgainLater status (which indicates an error).
  template <typename R, typename... ActualArgs, typename... ExpectedArgs>
  void AsyncPolicyRequest(
      base::Callback<void(EvalStatus, const R& result)> callback,
      EvalStatus (Policy::*policy_method)(
          EvaluationContext*, State*, std::string*, R*, ExpectedArgs...) const,
      ActualArgs... args);
 
 protected:
  // The UpdateManager receives ownership of the passed Policy instance.
  void set_policy(const Policy* policy) { policy_.reset(policy); }
 
  // State getter used for testing.
  State* state() { return state_.get(); }
 
 private:
  FRIEND_TEST(UmUpdateManagerTest, PolicyRequestCallsPolicy);
  FRIEND_TEST(UmUpdateManagerTest, PolicyRequestCallsDefaultOnError);
  FRIEND_TEST(UmUpdateManagerTest, PolicyRequestDoesntBlockDeathTest);
  FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestDelaysEvaluation);
  FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestTimeoutDoesNotFire);
  FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestTimesOut);
 
  // EvaluatePolicy() evaluates the passed |policy_method| method on the current
  // policy with the given |args| arguments. If the method fails, the default
  // policy is used instead.
  template <typename R, typename... Args>
  EvalStatus EvaluatePolicy(
      EvaluationContext* ec,
      EvalStatus (Policy::*policy_method)(
          EvaluationContext*, State*, std::string*, R*, Args...) const,
      R* result,
      Args... args);
 
  // OnPolicyReadyToEvaluate() is called by the main loop when the evaluation
  // of the given |policy_method| should be executed. If the evaluation finishes
  // the |callback| callback is called passing the |result| and the |status|
  // returned by the policy. If the evaluation returns an
  // EvalStatus::kAskMeAgainLater state, the |callback| will NOT be called and
  // the evaluation will be re-scheduled to be called later.
  template <typename R, typename... Args>
  void OnPolicyReadyToEvaluate(
      scoped_refptr<EvaluationContext> ec,
      base::Callback<void(EvalStatus status, const R& result)> callback,
      EvalStatus (Policy::*policy_method)(
          EvaluationContext*, State*, std::string*, R*, Args...) const,
      Args... args);
 
  // Unregisters (removes from repo) a previously created EvaluationContext.
  void UnregisterEvalContext(EvaluationContext* ec);
 
  // The policy used by the UpdateManager. Note that since it is a const Policy,
  // policy implementations are not allowed to persist state on this class.
  std::unique_ptr<const Policy> policy_;
 
  // A safe default value to the current policy. This policy is used whenever
  // a policy implementation fails with EvalStatus::kFailed.
  const DefaultPolicy default_policy_;
 
  // State Providers.
  std::unique_ptr<State> state_;
 
  // Pointer to the mockable clock interface;
  chromeos_update_engine::ClockInterface* clock_;
 
  // Timeout for a policy evaluation.
  const base::TimeDelta evaluation_timeout_;
 
  // Timeout for expiration of the evaluation context, used for async requests.
  const base::TimeDelta expiration_timeout_;
 
  // Repository of previously created EvaluationContext objects. These are being
  // unregistered (and the reference released) when the context is being
  // destructed; alternatively, when the UpdateManager instance is destroyed, it
  // will remove all pending events associated with all outstanding contexts
  // (which should, in turn, trigger their destruction).
  std::set<scoped_refptr<EvaluationContext>,
           ScopedRefPtrLess<EvaluationContext>>
      ec_repo_;
 
  base::WeakPtrFactory<UpdateManager> weak_ptr_factory_;
 
  DISALLOW_COPY_AND_ASSIGN(UpdateManager);
};
 
}  // namespace chromeos_update_manager
 
// Include the implementation of the template methods.
#include "update_engine/update_manager/update_manager-inl.h"
 
#endif  // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_