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

Side by Side Diff: chrome/browser/policy/cloud/cloud_policy_invalidator.cc

Issue 226093005: Reduce unneeded policy fetches by detecting expired invalidations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 8 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/policy/cloud/cloud_policy_invalidator.h" 5 #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/hash.h" 9 #include "base/hash.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 12 matching lines...) Expand all
23 #include "policy/policy_constants.h" 23 #include "policy/policy_constants.h"
24 #include "sync/notifier/object_id_invalidation_map.h" 24 #include "sync/notifier/object_id_invalidation_map.h"
25 25
26 namespace policy { 26 namespace policy {
27 27
28 const int CloudPolicyInvalidator::kMissingPayloadDelay = 5; 28 const int CloudPolicyInvalidator::kMissingPayloadDelay = 5;
29 const int CloudPolicyInvalidator::kMaxFetchDelayDefault = 120000; 29 const int CloudPolicyInvalidator::kMaxFetchDelayDefault = 120000;
30 const int CloudPolicyInvalidator::kMaxFetchDelayMin = 1000; 30 const int CloudPolicyInvalidator::kMaxFetchDelayMin = 1000;
31 const int CloudPolicyInvalidator::kMaxFetchDelayMax = 300000; 31 const int CloudPolicyInvalidator::kMaxFetchDelayMax = 300000;
32 const int CloudPolicyInvalidator::kInvalidationGracePeriod = 10; 32 const int CloudPolicyInvalidator::kInvalidationGracePeriod = 10;
33 const int CloudPolicyInvalidator::kUnknownVersionIgnorePeriod = 30;
34 const int CloudPolicyInvalidator::kMaxInvalidationTimeDelta = 300;
33 35
34 CloudPolicyInvalidator::CloudPolicyInvalidator( 36 CloudPolicyInvalidator::CloudPolicyInvalidator(
35 CloudPolicyCore* core, 37 CloudPolicyCore* core,
36 const scoped_refptr<base::SequencedTaskRunner>& task_runner, 38 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
37 scoped_ptr<base::Clock> clock) 39 scoped_ptr<base::Clock> clock)
38 : state_(UNINITIALIZED), 40 : state_(UNINITIALIZED),
39 core_(core), 41 core_(core),
40 task_runner_(task_runner), 42 task_runner_(task_runner),
41 clock_(clock.Pass()), 43 clock_(clock.Pass()),
42 invalidation_service_(NULL), 44 invalidation_service_(NULL),
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 !invalidation.is_unknown_version() && 169 !invalidation.is_unknown_version() &&
168 invalidation.version() <= invalidation_version_) { 170 invalidation.version() <= invalidation_version_) {
169 return; 171 return;
170 } 172 }
171 173
172 // If there is still a pending invalidation, acknowledge it, since we only 174 // If there is still a pending invalidation, acknowledge it, since we only
173 // care about the latest invalidation. 175 // care about the latest invalidation.
174 if (invalid_) 176 if (invalid_)
175 AcknowledgeInvalidation(); 177 AcknowledgeInvalidation();
176 178
179 // Get the version and payload from the invalidation.
180 // When an invalidation with unknown version is received, use negative
181 // numbers based on the number of such invalidations received. This
182 // ensures that the version numbers do not collide with "real" versions
183 // (which are positive) or previous invalidations with unknown version.
184 int64 version;
185 std::string payload;
186 if (invalidation.is_unknown_version()) {
187 version = -(++unknown_version_invalidation_count_);
188 } else {
189 version = invalidation.version();
190 payload = invalidation.payload();
191 }
192
193 // Ignore the invalidation if it is expired.
194 bool is_expired = IsInvalidationExpired(version);
195 UMA_HISTOGRAM_ENUMERATION(
196 kMetricPolicyInvalidations,
197 GetInvalidationMetric(payload.empty(), is_expired),
198 POLICY_INVALIDATION_TYPE_SIZE);
199 if (is_expired) {
200 invalidation.Acknowledge();
201 return;
202 }
203
177 // Update invalidation state. 204 // Update invalidation state.
178 invalid_ = true; 205 invalid_ = true;
179 invalidation_.reset(new syncer::Invalidation(invalidation)); 206 invalidation_.reset(new syncer::Invalidation(invalidation));
180 207 invalidation_version_ = version;
181 // When an invalidation with unknown version is received, use negative
182 // numbers based on the number of such invalidations received. This
183 // ensures that the version numbers do not collide with "real" versions
184 // (which are positive) or previous invalidations with unknown version.
185 if (invalidation.is_unknown_version()) {
186 invalidation_version_ = -(++unknown_version_invalidation_count_);
187 } else {
188 invalidation_version_ = invalidation.version();
189 }
190 208
191 // In order to prevent the cloud policy server from becoming overwhelmed when 209 // In order to prevent the cloud policy server from becoming overwhelmed when
192 // a policy with many users is modified, delay for a random period of time 210 // a policy with many users is modified, delay for a random period of time
193 // before fetching the policy. Delay for at least 20ms so that if multiple 211 // before fetching the policy. Delay for at least 20ms so that if multiple
194 // invalidations are received in quick succession, only one fetch will be 212 // invalidations are received in quick succession, only one fetch will be
195 // performed. 213 // performed.
196 base::TimeDelta delay = base::TimeDelta::FromMilliseconds( 214 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
197 base::RandInt(20, max_fetch_delay_)); 215 base::RandInt(20, max_fetch_delay_));
198 216
199 std::string payload;
200 if (!invalidation.is_unknown_version())
201 payload = invalidation.payload();
202
203 // If there is a payload, the policy can be refreshed at any time, so set 217 // If there is a payload, the policy can be refreshed at any time, so set
204 // the version and payload on the client immediately. Otherwise, the refresh 218 // the version and payload on the client immediately. Otherwise, the refresh
205 // must only run after at least kMissingPayloadDelay minutes. 219 // must only run after at least kMissingPayloadDelay minutes.
206 if (!payload.empty()) 220 if (!payload.empty())
207 core_->client()->SetInvalidationInfo(invalidation_version_, payload); 221 core_->client()->SetInvalidationInfo(version, payload);
208 else 222 else
209 delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay); 223 delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay);
210 224
211 // Schedule the policy to be refreshed. 225 // Schedule the policy to be refreshed.
212 task_runner_->PostDelayedTask( 226 task_runner_->PostDelayedTask(
213 FROM_HERE, 227 FROM_HERE,
214 base::Bind( 228 base::Bind(
215 &CloudPolicyInvalidator::RefreshPolicy, 229 &CloudPolicyInvalidator::RefreshPolicy,
216 weak_factory_.GetWeakPtr(), 230 weak_factory_.GetWeakPtr(),
217 payload.empty() /* is_missing_payload */), 231 payload.empty() /* is_missing_payload */),
218 delay); 232 delay);
219
220 // Update the kMetricPolicyInvalidations histogram.
221 UMA_HISTOGRAM_BOOLEAN(kMetricPolicyInvalidations, !payload.empty());
222 } 233 }
223 234
224 void CloudPolicyInvalidator::UpdateRegistration( 235 void CloudPolicyInvalidator::UpdateRegistration(
225 const enterprise_management::PolicyData* policy) { 236 const enterprise_management::PolicyData* policy) {
226 // Create the ObjectId based on the policy data. 237 // Create the ObjectId based on the policy data.
227 // If the policy does not specify an the ObjectId, then unregister. 238 // If the policy does not specify an the ObjectId, then unregister.
228 if (!policy || 239 if (!policy ||
229 !policy->has_invalidation_source() || 240 !policy->has_invalidation_source() ||
230 !policy->has_invalidation_name()) { 241 !policy->has_invalidation_name()) {
231 Unregister(); 242 Unregister();
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 // Determine if the policy changed by comparing its hash value to the 352 // Determine if the policy changed by comparing its hash value to the
342 // previous policy's hash value. 353 // previous policy's hash value.
343 uint32 new_hash_value = 0; 354 uint32 new_hash_value = 0;
344 if (policy && policy->has_policy_value()) 355 if (policy && policy->has_policy_value())
345 new_hash_value = base::Hash(policy->policy_value()); 356 new_hash_value = base::Hash(policy->policy_value());
346 bool changed = new_hash_value != policy_hash_value_; 357 bool changed = new_hash_value != policy_hash_value_;
347 policy_hash_value_ = new_hash_value; 358 policy_hash_value_ = new_hash_value;
348 return changed; 359 return changed;
349 } 360 }
350 361
362 bool CloudPolicyInvalidator::IsInvalidationExpired(int64 version) {
363 base::Time last_fetch_time = base::Time::UnixEpoch() +
364 base::TimeDelta::FromMilliseconds(core_->store()->policy()->timestamp());
365
366 // If the version is unknown, consider the invalidation invalid if the
367 // policy was fetched very recently.
368 if (version < 0) {
369 base::TimeDelta elapsed = clock_->Now() - last_fetch_time;
370 return elapsed.InSeconds() < kUnknownVersionIgnorePeriod;
371 }
372
373 // The invalidation version is the timestamp in microseconds. If the
374 // invalidation occurred before the last policy fetch, then the invalidation
375 // is expired. Time is added to the invalidation to err on the side of not
376 // expired.
377 base::Time invalidation_time = base::Time::UnixEpoch() +
378 base::TimeDelta::FromMicroseconds(version) +
379 base::TimeDelta::FromSeconds(kMaxInvalidationTimeDelta);
380 return invalidation_time < last_fetch_time;
381 }
382
351 int CloudPolicyInvalidator::GetPolicyRefreshMetric(bool policy_changed) { 383 int CloudPolicyInvalidator::GetPolicyRefreshMetric(bool policy_changed) {
352 if (policy_changed) { 384 if (policy_changed) {
353 if (invalid_) 385 if (invalid_)
354 return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED; 386 return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED;
355 if (GetInvalidationsEnabled()) 387 if (GetInvalidationsEnabled())
356 return METRIC_POLICY_REFRESH_CHANGED; 388 return METRIC_POLICY_REFRESH_CHANGED;
357 return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS; 389 return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS;
358 } 390 }
359 if (invalid_) 391 if (invalid_)
360 return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED; 392 return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED;
361 return METRIC_POLICY_REFRESH_UNCHANGED; 393 return METRIC_POLICY_REFRESH_UNCHANGED;
362 } 394 }
363 395
396 int CloudPolicyInvalidator::GetInvalidationMetric(bool is_missing_payload,
397 bool is_expired) {
398 if (is_expired) {
399 if (is_missing_payload)
400 return POLICY_INVALIDATION_TYPE_NO_PAYLOAD_EXPIRED;
401 return POLICY_INVALIDATION_TYPE_EXPIRED;
402 }
403 if (is_missing_payload)
404 return POLICY_INVALIDATION_TYPE_NO_PAYLOAD;
405 return POLICY_INVALIDATION_TYPE_NORMAL;
406 }
407
364 bool CloudPolicyInvalidator::GetInvalidationsEnabled() { 408 bool CloudPolicyInvalidator::GetInvalidationsEnabled() {
365 if (!invalidations_enabled_) 409 if (!invalidations_enabled_)
366 return false; 410 return false;
367 // If invalidations have been enabled for less than the grace period, then 411 // If invalidations have been enabled for less than the grace period, then
368 // consider invalidations to be disabled for metrics reporting. 412 // consider invalidations to be disabled for metrics reporting.
369 base::TimeDelta elapsed = clock_->Now() - invalidations_enabled_time_; 413 base::TimeDelta elapsed = clock_->Now() - invalidations_enabled_time_;
370 return elapsed.InSeconds() >= kInvalidationGracePeriod; 414 return elapsed.InSeconds() >= kInvalidationGracePeriod;
371 } 415 }
372 416
373 } // namespace policy 417 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698