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

Side by Side Diff: components/precache/core/precache_fetcher.cc

Issue 1961153003: Add pause/resume functionality to precache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 "components/precache/core/precache_fetcher.h" 5 #include "components/precache/core/precache_fetcher.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
14 #include "base/callback.h" 15 #include "base/callback.h"
15 #include "base/command_line.h" 16 #include "base/command_line.h"
16 #include "base/compiler_specific.h" 17 #include "base/compiler_specific.h"
17 #include "base/containers/hash_tables.h" 18 #include "base/containers/hash_tables.h"
19 #include "base/location.h"
18 #include "base/logging.h" 20 #include "base/logging.h"
19 #include "base/memory/ptr_util.h" 21 #include "base/memory/ptr_util.h"
22 #include "base/memory/ref_counted.h"
20 #include "base/metrics/histogram_macros.h" 23 #include "base/metrics/histogram_macros.h"
24 #include "components/precache/core/precache_database.h"
21 #include "components/precache/core/precache_switches.h" 25 #include "components/precache/core/precache_switches.h"
22 #include "components/precache/core/proto/precache.pb.h" 26 #include "components/precache/core/proto/precache.pb.h"
23 #include "net/base/completion_callback.h" 27 #include "net/base/completion_callback.h"
24 #include "net/base/escape.h" 28 #include "net/base/escape.h"
25 #include "net/base/io_buffer.h" 29 #include "net/base/io_buffer.h"
26 #include "net/base/load_flags.h" 30 #include "net/base/load_flags.h"
27 #include "net/base/net_errors.h" 31 #include "net/base/net_errors.h"
28 #include "net/http/http_response_headers.h" 32 #include "net/http/http_response_headers.h"
29 #include "net/url_request/url_fetcher_response_writer.h" 33 #include "net/url_request/url_fetcher_response_writer.h"
30 #include "net/url_request/url_request_context_getter.h" 34 #include "net/url_request/url_request_context_getter.h"
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 response_bytes_ = source->GetReceivedResponseContentLength(); 258 response_bytes_ = source->GetReceivedResponseContentLength();
255 network_response_bytes_ = source->GetTotalReceivedBytes(); 259 network_response_bytes_ = source->GetTotalReceivedBytes();
256 callback_.Run(*this); 260 callback_.Run(*this);
257 } 261 }
258 262
259 PrecacheFetcher::PrecacheFetcher( 263 PrecacheFetcher::PrecacheFetcher(
260 const std::vector<std::string>& starting_hosts, 264 const std::vector<std::string>& starting_hosts,
261 net::URLRequestContextGetter* request_context, 265 net::URLRequestContextGetter* request_context,
262 const GURL& config_url, 266 const GURL& config_url,
263 const std::string& manifest_url_prefix, 267 const std::string& manifest_url_prefix,
264 PrecacheFetcher::PrecacheDelegate* precache_delegate) 268 PrecacheFetcher::PrecacheDelegate* precache_delegate,
269 base::WeakPtr<PrecacheDatabase> precache_database,
270 scoped_refptr<base::SingleThreadTaskRunner> database_task_runner)
265 : starting_hosts_(starting_hosts), 271 : starting_hosts_(starting_hosts),
266 request_context_(request_context), 272 request_context_(request_context),
267 config_url_(config_url), 273 config_url_(config_url),
268 manifest_url_prefix_(manifest_url_prefix), 274 manifest_url_prefix_(manifest_url_prefix),
269 precache_delegate_(precache_delegate), 275 precache_delegate_(precache_delegate),
270 config_(new PrecacheConfigurationSettings), 276 config_(new PrecacheConfigurationSettings),
277 precache_database_(precache_database),
278 database_task_runner_(database_task_runner),
271 total_response_bytes_(0), 279 total_response_bytes_(0),
272 network_response_bytes_(0), 280 network_response_bytes_(0),
273 num_manifest_urls_to_fetch_(0), 281 num_manifest_urls_to_fetch_(0),
274 pool_(kMaxParallelFetches) { 282 pool_(kMaxParallelFetches) {
275 DCHECK(request_context_.get()); // Request context must be non-NULL. 283 DCHECK(request_context_.get()); // Request context must be non-NULL.
276 DCHECK(precache_delegate_); // Precache delegate must be non-NULL. 284 DCHECK(precache_delegate_); // Precache delegate must be non-NULL.
277 285
278 DCHECK_NE(GURL(), GetDefaultConfigURL()) 286 DCHECK_NE(GURL(), GetDefaultConfigURL())
279 << "Could not determine the precache config settings URL."; 287 << "Could not determine the precache config settings URL.";
280 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix()) 288 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix())
(...skipping 22 matching lines...) Expand all
303 num_manifest_urls_to_fetch_ * 100); 311 num_manifest_urls_to_fetch_ * 100);
304 UMA_HISTOGRAM_PERCENTAGE("Precache.Fetch.PercentCompleted", 312 UMA_HISTOGRAM_PERCENTAGE("Precache.Fetch.PercentCompleted",
305 percent_completed); 313 percent_completed);
306 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Total", 314 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Total",
307 total_response_bytes_, 1, kMaxResponseBytes, 100); 315 total_response_bytes_, 1, kMaxResponseBytes, 100);
308 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Network", 316 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Network",
309 network_response_bytes_, 1, kMaxResponseBytes, 317 network_response_bytes_, 1, kMaxResponseBytes,
310 100); 318 100);
311 } 319 }
312 320
321
322
323
324 void PrecacheFetcher::Init(
325 const base::TimeDelta& max_age) {
326 // Fetch unfinished work that is no older than |max_age|.
327 scoped_refptr<UnfinishedWork> unfinished_work =
328 new UnfinishedWork(base::TimeTicks::Now() - max_age);
329 database_task_runner_->PostTaskAndReply(
sclittle 2016/05/10 00:01:26 I'm not sure that UnfinishedWork needs to be refco
bengr 2016/05/19 01:25:44 Done.
330 FROM_HERE,
331 base::Bind(&PrecacheDatabase::GetUnfinishedWork, precache_database_,
332 unfinished_work),
333 base::Bind(&PrecacheFetcher::OnInitDone, AsWeakPtr(),
334 unfinished_work));
335 }
336
337 void PrecacheFetcher::OnInitDone(
338 scoped_refptr<UnfinishedWork> unfinished_work) {
339 if (unfinished_work->manifests.empty() &&
340 unfinished_work->resources.empty()) {
341 if (unfinished_work->total_bytes > 0) {
342 //TODO(rajendrant): report expired unfinished job.
sclittle 2016/05/10 00:01:26 nit: add space between "//" and "TODO", and capita
bengr 2016/05/19 01:25:44 Done.
343 }
344 } else {
345 // Starting hosts are cleared because this is a continuation.
346 manifest_urls_to_fetch_ = unfinished_work->manifests;
sclittle 2016/05/10 00:01:26 Use std::move on the lists here to avoid copying t
bengr 2016/05/19 01:25:44 Done.
347 resource_urls_to_fetch_ = unfinished_work->resources;
348 total_response_bytes_ = unfinished_work->total_bytes;
349 network_response_bytes_ = unfinished_work->network_bytes;
350 num_manifest_urls_to_fetch_ = unfinished_work->num_manifest_urls;
351 start_time_ = unfinished_work->start_time;
352 }
353 precache_delegate_->OnInitDone();
354 }
355
356 void PrecacheFetcher::Shutdown() {
357 scoped_refptr<UnfinishedWork> unfinished_work = new UnfinishedWork(
358 manifest_urls_to_fetch_, resource_urls_to_fetch_,
359 total_response_bytes_, network_response_bytes_,
360 num_manifest_urls_to_fetch_, start_time_);
361 database_task_runner_->PostTaskAndReply(
362 FROM_HERE,
363 base::Bind(&PrecacheDatabase::SaveUnfinishedWork, precache_database_,
364 unfinished_work),
365 base::Bind(&PrecacheFetcher::OnShutdownDone, AsWeakPtr()));
366 }
367
368 void PrecacheFetcher::OnShutdownDone() {
369 precache_delegate_->OnShutdownDone();
370 }
371
313 void PrecacheFetcher::Start() { 372 void PrecacheFetcher::Start() {
314 GURL config_url = 373 GURL config_url =
315 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_; 374 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_;
316 375
317 DCHECK(config_url.is_valid()) << "Config URL not valid: " 376 DCHECK(config_url.is_valid()) << "Config URL not valid: "
318 << config_url.possibly_invalid_spec(); 377 << config_url.possibly_invalid_spec();
319 378
320 start_time_ = base::TimeTicks::Now(); 379 if (start_time_.is_null())
380 start_time_ = base::TimeTicks::Now();
321 381
322 // Fetch the precache configuration settings from the server. 382 // Fetch the precache configuration settings from the server.
323 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available"; 383 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available";
324 VLOG(3) << "Fetching " << config_url; 384 VLOG(3) << "Fetching " << config_url;
325 pool_.Add(base::WrapUnique(new Fetcher( 385 pool_.Add(base::WrapUnique(new Fetcher(
326 request_context_.get(), config_url, 386 request_context_.get(), config_url,
327 base::Bind(&PrecacheFetcher::OnConfigFetchComplete, 387 base::Bind(&PrecacheFetcher::OnConfigFetchComplete,
328 base::Unretained(this)), 388 base::Unretained(this)),
329 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); 389 false /* is_resource_request */, std::numeric_limits<int32_t>::max())));
330 } 390 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 : manifest_url_prefix_; 456 : manifest_url_prefix_;
397 DCHECK_NE(std::string(), prefix) 457 DCHECK_NE(std::string(), prefix)
398 << "Could not determine the precache manifest URL prefix."; 458 << "Could not determine the precache manifest URL prefix.";
399 459
400 // Keep track of manifest URLs that are being fetched, in order to elide 460 // Keep track of manifest URLs that are being fetched, in order to elide
401 // duplicates. 461 // duplicates.
402 base::hash_set<std::string> seen_manifest_urls; 462 base::hash_set<std::string> seen_manifest_urls;
403 463
404 // Attempt to fetch manifests for starting hosts up to the maximum top sites 464 // Attempt to fetch manifests for starting hosts up to the maximum top sites
405 // count. If a manifest does not exist for a particular starting host, then 465 // count. If a manifest does not exist for a particular starting host, then
406 // the fetch will fail, and that starting host will be ignored. 466 // the fetch will fail, and that starting host will be ignored. Starting
407 int64_t rank = 0; 467 // hosts are not added if this is a continuation from a previous precache
408 for (const std::string& host : starting_hosts_) { 468 // session.
409 ++rank; 469 if (manifest_urls_to_fetch_.empty()) {
sclittle 2016/05/10 00:01:26 What about if the UnfinishedWork already finished
bengr 2016/05/19 01:25:44 Good catch. Thanks.
410 if (rank > config_->top_sites_count()) 470 int64_t rank = 0;
411 break; 471 for (const std::string& host : starting_hosts_) {
412 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, 472 ++rank;
413 &manifest_urls_to_fetch_); 473 if (rank > config_->top_sites_count())
474 break;
475 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls,
476 &manifest_urls_to_fetch_);
477 }
478
479 for (const std::string& host : config_->forced_site()) {
480 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls,
481 &manifest_urls_to_fetch_);
482 }
414 } 483 }
415
416 for (const std::string& host : config_->forced_site())
417 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls,
418 &manifest_urls_to_fetch_);
419
420 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size(); 484 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size();
421 } 485 }
422 pool_.Delete(source); 486 pool_.Delete(source);
423 487
424 StartNextFetch(); 488 StartNextFetch();
425 } 489 }
426 490
427 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) { 491 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) {
428 UpdateStats(source.response_bytes(), source.network_response_bytes()); 492 UpdateStats(source.response_bytes(), source.network_response_bytes());
429 if (source.network_url_fetcher() == nullptr) { 493 if (source.network_url_fetcher() == nullptr) {
430 pool_.DeleteAll(); // Cancel any other ongoing request. 494 pool_.DeleteAll(); // Cancel any other ongoing request.
431 } else { 495 } else {
432 PrecacheManifest manifest; 496 PrecacheManifest manifest;
433 497
434 if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) { 498 if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) {
435 const int32_t len = 499 const int32_t len =
436 std::min(manifest.resource_size(), config_->top_resources_count()); 500 std::min(manifest.resource_size(), config_->top_resources_count());
437 for (int i = 0; i < len; ++i) { 501 for (int i = 0; i < len; ++i) {
438 if (manifest.resource(i).has_url()) { 502 if (manifest.resource(i).has_url())
439 resource_urls_to_fetch_.push_back(GURL(manifest.resource(i).url())); 503 resource_urls_to_fetch_.push_back(GURL(manifest.resource(i).url()));
440 }
441 } 504 }
442 } 505 }
443 } 506 }
444 507
445 pool_.Delete(source); 508 pool_.Delete(source);
446 StartNextFetch(); 509 StartNextFetch();
447 } 510 }
448 511
449 void PrecacheFetcher::OnResourceFetchComplete(const Fetcher& source) { 512 void PrecacheFetcher::OnResourceFetchComplete(const Fetcher& source) {
450 UpdateStats(source.response_bytes(), source.network_response_bytes()); 513 UpdateStats(source.response_bytes(), source.network_response_bytes());
451 pool_.Delete(source); 514 pool_.Delete(source);
452 // The resource has already been put in the cache during the fetch process, so 515 // The resource has already been put in the cache during the fetch process, so
453 // nothing more needs to be done for the resource. 516 // nothing more needs to be done for the resource.
454 StartNextFetch(); 517 StartNextFetch();
455 } 518 }
456 519
457 void PrecacheFetcher::UpdateStats(int64_t response_bytes, 520 void PrecacheFetcher::UpdateStats(int64_t response_bytes,
458 int64_t network_response_bytes) { 521 int64_t network_response_bytes) {
459 total_response_bytes_ += response_bytes; 522 total_response_bytes_ += response_bytes;
460 network_response_bytes_ += network_response_bytes; 523 network_response_bytes_ += network_response_bytes;
461 } 524 }
462 525
526 void PrecacheFetcher::AssignWorkForTest(const std::list<GURL>& manifests,
527 const std::list<GURL>& resources,
528 size_t total_response_bytes,
529 size_t network_response_bytes,
530 int num_manifest_urls_to_fetch,
531 const base::TimeTicks& start_time) {
532 DCHECK(manifest_urls_to_fetch_.empty());
533 DCHECK(resource_urls_to_fetch_.empty());
534 manifest_urls_to_fetch_ = manifests;
535 resource_urls_to_fetch_ = resources;
536 total_response_bytes_ = total_response_bytes;
537 network_response_bytes_ = network_response_bytes;
538 num_manifest_urls_to_fetch_ = num_manifest_urls_to_fetch;
539 start_time_ = start_time;
540 }
541
463 } // namespace precache 542 } // namespace precache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698