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

Side by Side Diff: components/offline_pages/offline_page_metadata_store_sql.cc

Issue 2497703002: [Offline pages] Resetting offline page metadata store to handle LOAD/INIT failures (Closed)
Patch Set: Fixing newly added test Created 4 years, 1 month 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/offline_page_metadata_store_sql.h" 5 #include "components/offline_pages/offline_page_metadata_store_sql.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 const std::vector<OfflinePageItem>& result) { 282 const std::vector<OfflinePageItem>& result) {
283 // TODO(fgorski): Switch to SQL specific UMA metrics. 283 // TODO(fgorski): Switch to SQL specific UMA metrics.
284 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status, 284 UMA_HISTOGRAM_ENUMERATION("OfflinePages.LoadStatus", status,
285 OfflinePageMetadataStore::LOAD_STATUS_COUNT); 285 OfflinePageMetadataStore::LOAD_STATUS_COUNT);
286 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) { 286 if (status == OfflinePageMetadataStore::LOAD_SUCCEEDED) {
287 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount", 287 UMA_HISTOGRAM_COUNTS("OfflinePages.SavedPageCount",
288 static_cast<int32_t>(result.size())); 288 static_cast<int32_t>(result.size()));
289 } else { 289 } else {
290 DVLOG(1) << "Offline pages database loading failed: " << status; 290 DVLOG(1) << "Offline pages database loading failed: " << status;
291 } 291 }
292 runner->PostTask(FROM_HERE, base::Bind(callback, status, result)); 292 runner->PostTask(FROM_HERE, base::Bind(callback, result));
293 } 293 }
294 294
295 void OpenConnectionSync(sql::Connection* db, 295 void OpenConnectionSync(sql::Connection* db,
296 scoped_refptr<base::SingleThreadTaskRunner> runner, 296 scoped_refptr<base::SingleThreadTaskRunner> runner,
297 const base::FilePath& path, 297 const base::FilePath& path,
298 const base::Callback<void(StoreState)>& callback) { 298 const base::Callback<void(bool)>& callback) {
299 StoreState state = 299 bool success = InitDatabase(db, path);
300 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; 300 runner->PostTask(FROM_HERE, base::Bind(callback, success));
301 runner->PostTask(FROM_HERE, base::Bind(callback, state));
302 } 301 }
303 302
304 bool GetPageByOfflineIdSync(sql::Connection* db, 303 bool GetPageByOfflineIdSync(sql::Connection* db,
305 int64_t offline_id, 304 int64_t offline_id,
306 OfflinePageItem* item) { 305 OfflinePageItem* item) {
307 const char kSql[] = 306 const char kSql[] =
308 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; 307 "SELECT * FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?";
309 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); 308 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
310 statement.BindInt64(0, offline_id); 309 statement.BindInt64(0, offline_id);
311 310
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 PostStoreErrorForAllIds(runner, offline_ids, callback); 446 PostStoreErrorForAllIds(runner, offline_ids, callback);
448 return; 447 return;
449 } 448 }
450 449
451 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); 450 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
452 } 451 }
453 452
454 void ResetSync(sql::Connection* db, 453 void ResetSync(sql::Connection* db,
455 const base::FilePath& db_file_path, 454 const base::FilePath& db_file_path,
456 scoped_refptr<base::SingleThreadTaskRunner> runner, 455 scoped_refptr<base::SingleThreadTaskRunner> runner,
457 const base::Callback<void(StoreState)>& callback) { 456 const base::Callback<void(bool)>& callback) {
458 // This method deletes the content of the whole store and reinitializes it. 457 // This method deletes the content of the whole store and reinitializes it.
459 bool success = db->Raze(); 458 bool success = true;
460 db->Close(); 459 if (db) {
461 StoreState state; 460 success = db->Raze();
462 if (success) { 461 db->Close();
463 state = InitDatabase(db, db_file_path) ? StoreState::LOADED
464 : StoreState::FAILED_LOADING;
465 } else {
466 state = StoreState::FAILED_RESET;
467 } 462 }
468 runner->PostTask(FROM_HERE, base::Bind(callback, state)); 463 success = base::DeleteFile(db_file_path, true /*recursive*/) && success;
464 runner->PostTask(FROM_HERE, base::Bind(callback, success));
469 } 465 }
470 466
471 } // anonymous namespace 467 } // anonymous namespace
472 468
473 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL( 469 OfflinePageMetadataStoreSQL::OfflinePageMetadataStoreSQL(
474 scoped_refptr<base::SequencedTaskRunner> background_task_runner, 470 scoped_refptr<base::SequencedTaskRunner> background_task_runner,
475 const base::FilePath& path) 471 const base::FilePath& path)
476 : background_task_runner_(std::move(background_task_runner)), 472 : background_task_runner_(std::move(background_task_runner)),
477 db_file_path_(path.AppendASCII("OfflinePages.db")), 473 db_file_path_(path.AppendASCII("OfflinePages.db")),
478 state_(StoreState::NOT_LOADED), 474 state_(StoreState::NOT_LOADED),
479 weak_ptr_factory_(this) { 475 weak_ptr_factory_(this) {
480 OpenConnection();
481 } 476 }
482 477
483 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() { 478 OfflinePageMetadataStoreSQL::~OfflinePageMetadataStoreSQL() {
484 if (db_.get() && 479 if (db_.get() &&
485 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) { 480 !background_task_runner_->DeleteSoon(FROM_HERE, db_.release())) {
486 DLOG(WARNING) << "SQL database will not be deleted."; 481 DLOG(WARNING) << "SQL database will not be deleted.";
487 } 482 }
488 } 483 }
489 484
485 void OfflinePageMetadataStoreSQL::Initialize(
486 const InitializeCallback& callback) {
487 DCHECK(!db_);
488 db_.reset(new sql::Connection());
489 background_task_runner_->PostTask(
490 FROM_HERE,
491 base::Bind(&OpenConnectionSync, db_.get(),
492 base::ThreadTaskRunnerHandle::Get(), db_file_path_,
493 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone,
494 weak_ptr_factory_.GetWeakPtr(), callback)));
495 }
496
490 void OfflinePageMetadataStoreSQL::GetOfflinePages( 497 void OfflinePageMetadataStoreSQL::GetOfflinePages(
491 const LoadCallback& callback) { 498 const LoadCallback& callback) {
492 if (!CheckDb(base::Bind( 499 if (!CheckDb()) {
493 callback, STORE_INIT_FAILED, std::vector<OfflinePageItem>()))) { 500 base::ThreadTaskRunnerHandle::Get()->PostTask(
501 FROM_HERE, base::Bind(callback, std::vector<OfflinePageItem>()));
494 return; 502 return;
495 } 503 }
496 504
497 background_task_runner_->PostTask( 505 background_task_runner_->PostTask(
498 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(), 506 FROM_HERE, base::Bind(&GetOfflinePagesSync, db_.get(),
499 base::ThreadTaskRunnerHandle::Get(), callback)); 507 base::ThreadTaskRunnerHandle::Get(), callback));
500 } 508 }
501 509
502 void OfflinePageMetadataStoreSQL::AddOfflinePage( 510 void OfflinePageMetadataStoreSQL::AddOfflinePage(
503 const OfflinePageItem& offline_page, 511 const OfflinePageItem& offline_page,
504 const AddCallback& callback) { 512 const AddCallback& callback) {
505 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) 513 if (!CheckDb()) {
514 base::ThreadTaskRunnerHandle::Get()->PostTask(
515 FROM_HERE, base::Bind(callback, ItemActionStatus::STORE_ERROR));
506 return; 516 return;
517 }
507 518
508 background_task_runner_->PostTask( 519 background_task_runner_->PostTask(
509 FROM_HERE, 520 FROM_HERE,
510 base::Bind(&AddOfflinePageSync, db_.get(), 521 base::Bind(&AddOfflinePageSync, db_.get(),
511 base::ThreadTaskRunnerHandle::Get(), offline_page, callback)); 522 base::ThreadTaskRunnerHandle::Get(), offline_page, callback));
512 } 523 }
513 524
514 void OfflinePageMetadataStoreSQL::UpdateOfflinePages( 525 void OfflinePageMetadataStoreSQL::UpdateOfflinePages(
515 const std::vector<OfflinePageItem>& pages, 526 const std::vector<OfflinePageItem>& pages,
516 const UpdateCallback& callback) { 527 const UpdateCallback& callback) {
517 if (!db_.get()) { 528 if (!CheckDb()) {
518 PostStoreErrorForAllPages(base::ThreadTaskRunnerHandle::Get(), pages, 529 PostStoreErrorForAllPages(base::ThreadTaskRunnerHandle::Get(), pages,
519 callback); 530 callback);
520 return; 531 return;
521 } 532 }
522 533
523 background_task_runner_->PostTask( 534 background_task_runner_->PostTask(
524 FROM_HERE, 535 FROM_HERE,
525 base::Bind(&UpdateOfflinePagesSync, db_.get(), 536 base::Bind(&UpdateOfflinePagesSync, db_.get(),
526 base::ThreadTaskRunnerHandle::Get(), pages, callback)); 537 base::ThreadTaskRunnerHandle::Get(), pages, callback));
527 } 538 }
528 539
529 void OfflinePageMetadataStoreSQL::RemoveOfflinePages( 540 void OfflinePageMetadataStoreSQL::RemoveOfflinePages(
530 const std::vector<int64_t>& offline_ids, 541 const std::vector<int64_t>& offline_ids,
531 const UpdateCallback& callback) { 542 const UpdateCallback& callback) {
532 DCHECK(db_.get()); 543 if (!CheckDb()) {
544 PostStoreErrorForAllIds(base::ThreadTaskRunnerHandle::Get(), offline_ids,
545 callback);
546 return;
547 }
533 548
534 if (offline_ids.empty()) { 549 if (offline_ids.empty()) {
535 // Nothing to do, but post a callback instead of calling directly 550 // Nothing to do, but post a callback instead of calling directly
536 // to preserve the async style behavior to prevent bugs. 551 // to preserve the async style behavior to prevent bugs.
537 PostStoreUpdateResultForIds( 552 PostStoreUpdateResultForIds(
538 base::ThreadTaskRunnerHandle::Get(), state(), offline_ids, 553 base::ThreadTaskRunnerHandle::Get(), state(), offline_ids,
539 ItemActionStatus::NOT_FOUND /* will be ignored */, callback); 554 ItemActionStatus::NOT_FOUND /* will be ignored */, callback);
540 return; 555 return;
541 } 556 }
542 557
543 background_task_runner_->PostTask( 558 background_task_runner_->PostTask(
544 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(), 559 FROM_HERE, base::Bind(&RemoveOfflinePagesSync, offline_ids, db_.get(),
545 base::ThreadTaskRunnerHandle::Get(), callback)); 560 base::ThreadTaskRunnerHandle::Get(), callback));
546 } 561 }
547 562
548 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) { 563 void OfflinePageMetadataStoreSQL::Reset(const ResetCallback& callback) {
549 if (!CheckDb(base::Bind(callback, false)))
550 return;
551
552 background_task_runner_->PostTask( 564 background_task_runner_->PostTask(
553 FROM_HERE, 565 FROM_HERE,
554 base::Bind(&ResetSync, db_.get(), db_file_path_, 566 base::Bind(&ResetSync, db_.get(), db_file_path_,
555 base::ThreadTaskRunnerHandle::Get(), 567 base::ThreadTaskRunnerHandle::Get(),
556 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone, 568 base::Bind(&OfflinePageMetadataStoreSQL::OnResetDone,
557 weak_ptr_factory_.GetWeakPtr(), callback))); 569 weak_ptr_factory_.GetWeakPtr(), callback)));
558 } 570 }
559 571
560 StoreState OfflinePageMetadataStoreSQL::state() const { 572 StoreState OfflinePageMetadataStoreSQL::state() const {
561 return state_; 573 return state_;
562 } 574 }
563 575
564 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state, 576 void OfflinePageMetadataStoreSQL::SetStateForTesting(StoreState state,
565 bool reset_db) { 577 bool reset_db) {
566 state_ = state; 578 state_ = state;
567 if (reset_db) 579 if (reset_db)
568 db_.reset(nullptr); 580 db_.reset(nullptr);
569 } 581 }
570 582
571 void OfflinePageMetadataStoreSQL::OpenConnection() { 583 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone(
572 DCHECK(!db_); 584 const InitializeCallback& callback,
573 db_.reset(new sql::Connection()); 585 bool success) {
574 background_task_runner_->PostTask(
575 FROM_HERE,
576 base::Bind(&OpenConnectionSync, db_.get(),
577 base::ThreadTaskRunnerHandle::Get(), db_file_path_,
578 base::Bind(&OfflinePageMetadataStoreSQL::OnOpenConnectionDone,
579 weak_ptr_factory_.GetWeakPtr())));
580 }
581
582 void OfflinePageMetadataStoreSQL::OnOpenConnectionDone(StoreState state) {
583 DCHECK(db_.get()); 586 DCHECK(db_.get());
584 587 state_ = success ? StoreState::LOADED : StoreState::FAILED_LOADING;
585 state_ = state; 588 callback.Run(success);
586
587 // Unfortunately we were not able to open DB connection.
588 if (state != StoreState::LOADED)
589 db_.reset();
590
591 // TODO(fgorski): This might be a place to start store recovery. Alternatively
592 // that can be attempted in the OfflinePageModel.
593 } 589 }
594 590
595 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback, 591 void OfflinePageMetadataStoreSQL::OnResetDone(const ResetCallback& callback,
596 StoreState state) { 592 bool success) {
597 OnOpenConnectionDone(state); 593 state_ = success ? StoreState::NOT_LOADED : StoreState::FAILED_RESET;
598 callback.Run(state == StoreState::LOADED); 594 db_.reset();
595 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
596 base::Bind(callback, success));
599 } 597 }
600 598
601 bool OfflinePageMetadataStoreSQL::CheckDb(const base::Closure& callback) { 599 bool OfflinePageMetadataStoreSQL::CheckDb() {
602 if (!db_.get() || state_ != StoreState::LOADED) { 600 return db_ && state_ == StoreState::LOADED;
603 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
604 return false;
605 }
606 return true;
607 } 601 }
608 602
609 } // namespace offline_pages 603 } // namespace offline_pages
OLDNEW
« no previous file with comments | « components/offline_pages/offline_page_metadata_store_sql.h ('k') | components/offline_pages/offline_page_model_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698