Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(440)

Side by Side Diff: components/offline_pages/background/request_picker.cc

Issue 2113383002: More detailed implementation of the RequestPicker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Try a different way of checking policy to separate policy from checking. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/offline_pages/background/request_picker.h" 5 #include "components/offline_pages/background/request_picker.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "components/offline_pages/background/save_page_request.h" 9 #include "components/offline_pages/background/save_page_request.h"
10 10
11 namespace {
12 template <typename T>
13 int signum(T t) {
14 return (T(0) < t) - (t < T(0));
15 }
16
17 #define CALL_MEMBER_FUNCTION(object,ptrToMember) ((object)->*(ptrToMember))
18 } // namespace
19
11 namespace offline_pages { 20 namespace offline_pages {
12 21
13 RequestPicker::RequestPicker( 22 RequestPicker::RequestPicker(
14 RequestQueue* requestQueue) 23 RequestQueue* requestQueue, OfflinerPolicy* policy)
15 : queue_(requestQueue), 24 : queue_(requestQueue),
25 policy_(policy),
26 fewer_retries_better_(false),
27 earlier_requests_better_(false),
16 weak_ptr_factory_(this) {} 28 weak_ptr_factory_(this) {}
17 29
18 RequestPicker::~RequestPicker() {} 30 RequestPicker::~RequestPicker() {}
19 31
32 // Entry point for the async operation to choose the next request.
20 void RequestPicker::ChooseNextRequest( 33 void RequestPicker::ChooseNextRequest(
21 RequestCoordinator::RequestPickedCallback picked_callback, 34 RequestCoordinator::RequestPickedCallback picked_callback,
22 RequestCoordinator::RequestQueueEmptyCallback empty_callback) { 35 RequestCoordinator::RequestQueueEmptyCallback empty_callback,
36 DeviceConditions* device_conditions) {
23 picked_callback_ = picked_callback; 37 picked_callback_ = picked_callback;
24 empty_callback_ = empty_callback; 38 empty_callback_ = empty_callback;
39 fewer_retries_better_ = policy_->ShouldPreferUntriedRequests();
40 earlier_requests_better_ = policy_->ShouldPreferEarlierRequests();
41 current_conditions_.reset(new DeviceConditions(*device_conditions));
25 // Get all requests from queue (there is no filtering mechanism). 42 // Get all requests from queue (there is no filtering mechanism).
26 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback, 43 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback,
27 weak_ptr_factory_.GetWeakPtr())); 44 weak_ptr_factory_.GetWeakPtr()));
28 } 45 }
29 46
47 // When we get contents from the queue, use them to pick the next
48 // request to operate on (if any).
30 void RequestPicker::GetRequestResultCallback( 49 void RequestPicker::GetRequestResultCallback(
31 RequestQueue::GetRequestsResult, 50 RequestQueue::GetRequestsResult,
32 const std::vector<SavePageRequest>& requests) { 51 const std::vector<SavePageRequest>& requests) {
33 // If there is nothing to do, return right away. 52 // If there is nothing to do, return right away.
34 if (requests.size() == 0) { 53 if (requests.size() == 0) {
35 empty_callback_.Run(); 54 empty_callback_.Run();
36 return; 55 return;
37 } 56 }
38 57
39 // Pick the most deserving request for our conditions. 58 // Pick the most deserving request for our conditions.
40 const SavePageRequest& picked_request = requests[0]; 59 const SavePageRequest* picked_request = nullptr;
41 60
42 // When we have a best request to try next, get the request coodinator to 61 RequestCompareFunction comparator = nullptr;
43 // start it. 62
44 picked_callback_.Run(picked_request); 63 // Choose which comparison function to use based on policy.
64 if (policy_->RetryCountIsMoreImportantThanRecency()) {
65 comparator = &RequestPicker::RetryCountFirstCompareFunction;
66 }
fgorski 2016/07/21 17:01:20 I don't think you need either pair of {}
Pete Williamson 2016/07/21 19:48:45 Done. I misinterpreted our guidelines as anything
67 else {
68 comparator = &RequestPicker::RecencyFirstCompareFunction;
69 }
70
71 // Iterate once through the requests, keeping track of best candidate.
72 for (unsigned i = 0; i < requests.size(); ++i) {
73 if (!RequestConditionsSatisfied(requests[i]))
74 continue;
75 if (IsNewRequestBetter(picked_request, &(requests[i]), comparator))
76 picked_request = &(requests[i]);
77 }
78
79 // If we have a best request to try next, get the request coodinator to
80 // start it. Otherwise return that we have no candidates.
81 if (picked_request != nullptr) {
82 picked_callback_.Run(*picked_request);
83 } else {
84 empty_callback_.Run();
85 }
86 }
87
88 // Filter out requests that don't meet the current conditions. For instance, if
89 // this is a predictive request, and we are not on WiFi, it should be ignored
90 // this round.
91 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) {
92 // If the user did not request the page directly, make sure we are connected
93 // to power and have WiFi and sufficient battery remaining before we take this
94 // reqeust.
95 // TODO(petewil): We may later want to configure whether to allow 2G for non
96 // user_requested items, add that to policy.
97 if (!request.user_requested()) {
98 if (!current_conditions_->IsPowerConnected())
99 return false;
100
101 if (current_conditions_->GetNetConnectionType() !=
102 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) {
103 return false;
104 }
105
106 if (current_conditions_->GetBatteryPercentage() <
107 policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) {
108 return false;
109 }
110 }
111
112 // If we have already tried this page the max number of times, it is not
113 // eligible to try again.
114 // TODO(petewil): Instead, we should have code to remove the page from the
115 // queue after the last retry.
116 if (request.attempt_count() >= policy_->GetMaxRetries())
117 return false;
118
119 // If this request is not active yet, return false.
120 // TODO(petewil): If the only reason we return nothing to do is that we have
121 // inactive requests, we still want to try again later after their activation
122 // time elapses, we shouldn't take ourselves completely off the scheduler.
123 if (request.activation_time() > base::Time::Now())
124 return false;
125
126 return true;
127 }
128
129 // Look at policies to decide which requests to prefer.
130 bool RequestPicker::IsNewRequestBetter(const SavePageRequest* oldRequest,
131 const SavePageRequest* newRequest,
132 RequestCompareFunction comparator) {
133
134 // If there is no old request, the new one is better.
135 if (oldRequest == nullptr)
136 return true;
137
138 // User requested pages get priority.
139 if (newRequest->user_requested() && !oldRequest->user_requested())
140 return true;
141
142 // Otherwise, use the comparison function for the current policy, which
143 // returns true if hte older request is better.
fgorski 2016/07/21 17:01:20 s/hte/the/
Pete Williamson 2016/07/21 19:48:45 Done.
144 return !(CALL_MEMBER_FUNCTION(this, comparator)(oldRequest, newRequest));
145 }
146
147 // Compare the results, checking request count before recency. Returns true if
148 // left hand side is better, false otherwise.
149 bool RequestPicker::RetryCountFirstCompareFunction(
150 const SavePageRequest* left, const SavePageRequest* right) {
151 // Check the attempt count.
fgorski 2016/07/21 17:01:20 Consider extracting the block from here to the fir
Pete Williamson 2016/07/21 19:48:45 After I thought about it, I prefer leaving the cod
fgorski 2016/07/22 16:02:11 I was thinking of 2 functions that are specific to
Pete Williamson 2016/07/22 16:25:53 Oh, that's different than what I thought you were
152 int result = signum(left->attempt_count() - right->attempt_count());
153
154 // Flip the direction of comparison if policy prefers fewer retries.
155 if (fewer_retries_better_)
156 result *= -1;
157
158 if (result != 0)
159 return (result > 0);
160
161 // If we get here, the attempt counts were the same, so check recency.
162 base::TimeDelta difference = left->creation_time() - right->creation_time();
fgorski 2016/07/21 17:01:20 Same for this section. (Extract) And both extract
163 result = signum(difference.InMilliseconds());
164
165 // Flip the direction of the check if policy prefers later requests.
166 if (earlier_requests_better_)
167 result *= -1;
168
169 if (result == 1)
fgorski 2016/07/21 17:01:20 this whole block to the end is equivalent to: ret
Pete Williamson 2016/07/21 19:48:45 Done.
170 return true;
171
172 return false;
173 }
174
175 // Compare the results, checking recency before request count. Returns true if
176 // left hand side is better, false otherwise.
177 bool RequestPicker::RecencyFirstCompareFunction(
178 const SavePageRequest* left, const SavePageRequest* right) {
179 // Check the recency.
180 base::TimeDelta difference = left->creation_time() - right->creation_time();
fgorski 2016/07/21 17:01:20 nit: indentation
Pete Williamson 2016/07/21 19:48:45 Done.
181 int result = signum(difference.InMilliseconds());
182
183 // Flip the direction of comparison if policy prefers fewer retries.
184 if (earlier_requests_better_)
185 result *= -1;
186
187 if (result != 0)
188 return (result > 0);
189
190 // If we get here, the recency was the same, so check the attempt count.
191 result = signum(left->attempt_count() - right->attempt_count());
192
193 // Flip the direction of the check if policy prefers later requests.
194 if (fewer_retries_better_)
195 result *= -1;
196
197 if (result == 1)
fgorski 2016/07/21 17:01:20 same here: return result > 0
Pete Williamson 2016/07/21 19:48:45 Done.
198 return true;
199
200 return false;
45 } 201 }
46 202
47 } // namespace offline_pages 203 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698