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

Side by Side Diff: components/offline_pages/offline_page_model_impl.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_model_impl.h" 5 #include "components/offline_pages/offline_page_model_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 if (online_url_without_fragment == 639 if (online_url_without_fragment ==
640 id_page_pair.second.url.ReplaceComponents(remove_params)) { 640 id_page_pair.second.url.ReplaceComponents(remove_params)) {
641 result.push_back(id_page_pair.second); 641 result.push_back(id_page_pair.second);
642 } 642 }
643 } 643 }
644 644
645 callback.Run(result); 645 callback.Run(result);
646 } 646 }
647 647
648 void OfflinePageModelImpl::CheckMetadataConsistency() { 648 void OfflinePageModelImpl::CheckMetadataConsistency() {
649 DCHECK(is_loaded_);
650 archive_manager_->GetAllArchives( 649 archive_manager_->GetAllArchives(
651 base::Bind(&OfflinePageModelImpl::CheckMetadataConsistencyForArchivePaths, 650 base::Bind(&OfflinePageModelImpl::CheckMetadataConsistencyForArchivePaths,
652 weak_ptr_factory_.GetWeakPtr())); 651 weak_ptr_factory_.GetWeakPtr()));
653 } 652 }
654 653
655 void OfflinePageModelImpl::ExpirePages( 654 void OfflinePageModelImpl::ExpirePages(
656 const std::vector<int64_t>& offline_ids, 655 const std::vector<int64_t>& offline_ids,
657 const base::Time& expiration_time, 656 const base::Time& expiration_time,
658 const base::Callback<void(bool)>& callback) { 657 const base::Callback<void(bool)>& callback) {
659 std::vector<base::FilePath> paths_to_delete; 658 std::vector<base::FilePath> paths_to_delete;
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 } else if (status == ItemActionStatus::ALREADY_EXISTS) { 785 } else if (status == ItemActionStatus::ALREADY_EXISTS) {
787 result = SavePageResult::ALREADY_EXISTS; 786 result = SavePageResult::ALREADY_EXISTS;
788 } else { 787 } else {
789 result = SavePageResult::STORE_FAILURE; 788 result = SavePageResult::STORE_FAILURE;
790 } 789 }
791 InformSavePageDone(callback, result, offline_page.client_id, 790 InformSavePageDone(callback, result, offline_page.client_id,
792 offline_page.offline_id); 791 offline_page.offline_id);
793 if (result == SavePageResult::SUCCESS) { 792 if (result == SavePageResult::SUCCESS) {
794 DeleteExistingPagesWithSameURL(offline_page); 793 DeleteExistingPagesWithSameURL(offline_page);
795 } else { 794 } else {
796 PostClearStorageIfNeededTask(); 795 PostClearStorageIfNeededTask(false /* delayed */);
797 } 796 }
798 797
799 DeletePendingArchiver(archiver); 798 DeletePendingArchiver(archiver);
800 for (Observer& observer : observers_) 799 for (Observer& observer : observers_)
801 observer.OfflinePageModelChanged(this); 800 observer.OfflinePageModelChanged(this);
802 } 801 }
803 802
804 void OfflinePageModelImpl::OnMarkPageAccesseDone( 803 void OfflinePageModelImpl::OnMarkPageAccesseDone(
805 const OfflinePageItem& offline_page_item, 804 const OfflinePageItem& offline_page_item,
806 std::unique_ptr<OfflinePagesUpdateResult> result) { 805 std::unique_ptr<OfflinePagesUpdateResult> result) {
807 // Update the item in the cache only upon success. 806 // Update the item in the cache only upon success.
808 if (result->updated_items.size() > 0) 807 if (result->updated_items.size() > 0)
809 offline_pages_[offline_page_item.offline_id] = offline_page_item; 808 offline_pages_[offline_page_item.offline_id] = offline_page_item;
810 809
811 // No need to fire OfflinePageModelChanged event since updating access info 810 // No need to fire OfflinePageModelChanged event since updating access info
812 // should not have any impact to the UI. 811 // should not have any impact to the UI.
813 } 812 }
814 813
815 void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone( 814 void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone(
816 const base::TimeTicks& start_time) { 815 const base::TimeTicks& start_time) {
817 UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime", 816 UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime",
818 base::TimeTicks::Now() - start_time); 817 base::TimeTicks::Now() - start_time);
819 818
820 store_->GetOfflinePages(base::Bind(&OfflinePageModelImpl::OnLoadDone, 819 const int kResetAttemptsLeft = 1;
821 weak_ptr_factory_.GetWeakPtr(), 820 store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
822 start_time)); 821 weak_ptr_factory_.GetWeakPtr(), start_time,
822 kResetAttemptsLeft));
823 } 823 }
824 824
825 void OfflinePageModelImpl::OnLoadDone( 825 void OfflinePageModelImpl::OnStoreInitialized(const base::TimeTicks& start_time,
826 int reset_attempts_left,
827 bool success) {
828 if (success) {
829 DCHECK_EQ(store_->state(), StoreState::LOADED);
830 store_->GetOfflinePages(
831 base::Bind(&OfflinePageModelImpl::OnInitialGetOfflinePagesDone,
832 weak_ptr_factory_.GetWeakPtr(), start_time));
833 return;
834 }
835
836 DCHECK_EQ(store_->state(), StoreState::FAILED_LOADING);
837 // If there are no more reset attempts left, stop here.
838 if (reset_attempts_left == 0) {
839 FinalizeModelLoad();
840 return;
841 }
842
843 // Otherwise reduce the remaining attempts counter and reset store.
844 store_->Reset(base::Bind(&OfflinePageModelImpl::OnStoreResetDone,
845 weak_ptr_factory_.GetWeakPtr(), start_time,
846 reset_attempts_left - 1));
847 }
848
849 void OfflinePageModelImpl::OnStoreResetDone(const base::TimeTicks& start_time,
850 int reset_attempts_left,
851 bool success) {
852 if (success) {
853 DCHECK_EQ(store_->state(), StoreState::NOT_LOADED);
854 store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
855 weak_ptr_factory_.GetWeakPtr(), start_time,
856 reset_attempts_left));
857 return;
858 }
859
860 DCHECK_EQ(store_->state(), StoreState::FAILED_RESET);
861 FinalizeModelLoad();
862 }
863
864 void OfflinePageModelImpl::OnInitialGetOfflinePagesDone(
826 const base::TimeTicks& start_time, 865 const base::TimeTicks& start_time,
827 OfflinePageMetadataStore::LoadStatus load_status,
828 const std::vector<OfflinePageItem>& offline_pages) { 866 const std::vector<OfflinePageItem>& offline_pages) {
829 DCHECK(!is_loaded_); 867 DCHECK(!is_loaded_);
830 is_loaded_ = true;
831
832 // TODO(jianli): rebuild the store upon failure.
833
834 if (load_status == OfflinePageMetadataStore::LOAD_SUCCEEDED)
835 CacheLoadedData(offline_pages);
836 868
837 UMA_HISTOGRAM_TIMES("OfflinePages.Model.ConstructionToLoadedEventTime", 869 UMA_HISTOGRAM_TIMES("OfflinePages.Model.ConstructionToLoadedEventTime",
838 base::TimeTicks::Now() - start_time); 870 base::TimeTicks::Now() - start_time);
839 871
840 // Create Storage Manager. 872 CacheLoadedData(offline_pages);
841 storage_manager_.reset(new OfflinePageStorageManager( 873 FinalizeModelLoad();
842 this, GetPolicyController(), archive_manager_.get())); 874
875 // Ensure necessary cleanup operations are started.
876 CheckMetadataConsistency();
877 }
878
879 void OfflinePageModelImpl::FinalizeModelLoad() {
880 is_loaded_ = true;
881
882 // All actions below are meant to be taken regardless of successful load of
883 // the store.
884
885 // Inform observers the load is done.
886 for (Observer& observer : observers_)
887 observer.OfflinePageModelLoaded(this);
843 888
844 // Run all the delayed tasks. 889 // Run all the delayed tasks.
845 for (const auto& delayed_task : delayed_tasks_) 890 for (const auto& delayed_task : delayed_tasks_)
846 delayed_task.Run(); 891 delayed_task.Run();
847 delayed_tasks_.clear(); 892 delayed_tasks_.clear();
848 893
849 for (Observer& observer : observers_) 894 // Clear storage.
850 observer.OfflinePageModelLoaded(this); 895 PostClearStorageIfNeededTask(true /* delayed */);
851
852 CheckMetadataConsistency();
853
854 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
855 FROM_HERE, base::Bind(&OfflinePageModelImpl::ClearStorageIfNeeded,
856 weak_ptr_factory_.GetWeakPtr(),
857 base::Bind(&OfflinePageModelImpl::OnStorageCleared,
858 weak_ptr_factory_.GetWeakPtr())),
859 kStorageManagerStartingDelay);
860 } 896 }
861 897
862 void OfflinePageModelImpl::InformSavePageDone(const SavePageCallback& callback, 898 void OfflinePageModelImpl::InformSavePageDone(const SavePageCallback& callback,
863 SavePageResult result, 899 SavePageResult result,
864 const ClientId& client_id, 900 const ClientId& client_id,
865 int64_t offline_id) { 901 int64_t offline_id) {
866 ReportSavePageResultHistogramAfterSave(client_id, result); 902 ReportSavePageResultHistogramAfterSave(client_id, result);
867 archive_manager_->GetStorageStats( 903 archive_manager_->GetStorageStats(
868 base::Bind(&ReportStorageHistogramsAfterSave)); 904 base::Bind(&ReportStorageHistogramsAfterSave));
869 callback.Run(result, offline_id); 905 callback.Run(result, offline_id);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 page_ids_to_delete.push_back(item.offline_id); 944 page_ids_to_delete.push_back(item.offline_id);
909 DeletePagesByOfflineId( 945 DeletePagesByOfflineId(
910 page_ids_to_delete, 946 page_ids_to_delete,
911 base::Bind(&OfflinePageModelImpl::OnDeleteOldPagesWithSameURL, 947 base::Bind(&OfflinePageModelImpl::OnDeleteOldPagesWithSameURL,
912 weak_ptr_factory_.GetWeakPtr())); 948 weak_ptr_factory_.GetWeakPtr()));
913 } 949 }
914 950
915 void OfflinePageModelImpl::OnDeleteOldPagesWithSameURL( 951 void OfflinePageModelImpl::OnDeleteOldPagesWithSameURL(
916 DeletePageResult result) { 952 DeletePageResult result) {
917 // TODO(romax) Add UMAs for failure cases. 953 // TODO(romax) Add UMAs for failure cases.
918 PostClearStorageIfNeededTask(); 954 PostClearStorageIfNeededTask(false /* delayed */);
919 } 955 }
920 956
921 void OfflinePageModelImpl::DeletePendingArchiver( 957 void OfflinePageModelImpl::DeletePendingArchiver(
922 OfflinePageArchiver* archiver) { 958 OfflinePageArchiver* archiver) {
923 pending_archivers_.erase(std::find(pending_archivers_.begin(), 959 pending_archivers_.erase(std::find(pending_archivers_.begin(),
924 pending_archivers_.end(), archiver)); 960 pending_archivers_.end(), archiver));
925 } 961 }
926 962
927 void OfflinePageModelImpl::OnDeleteArchiveFilesDone( 963 void OfflinePageModelImpl::OnDeleteArchiveFilesDone(
928 const std::vector<int64_t>& offline_ids, 964 const std::vector<int64_t>& offline_ids,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 1083
1048 void OfflinePageModelImpl::CacheLoadedData( 1084 void OfflinePageModelImpl::CacheLoadedData(
1049 const std::vector<OfflinePageItem>& offline_pages) { 1085 const std::vector<OfflinePageItem>& offline_pages) {
1050 offline_pages_.clear(); 1086 offline_pages_.clear();
1051 for (const auto& offline_page : offline_pages) 1087 for (const auto& offline_page : offline_pages)
1052 offline_pages_[offline_page.offline_id] = offline_page; 1088 offline_pages_[offline_page.offline_id] = offline_page;
1053 } 1089 }
1054 1090
1055 void OfflinePageModelImpl::ClearStorageIfNeeded( 1091 void OfflinePageModelImpl::ClearStorageIfNeeded(
1056 const ClearStorageCallback& callback) { 1092 const ClearStorageCallback& callback) {
1093 // Create Storage Manager if necessary.
1094 if (!storage_manager_) {
1095 storage_manager_.reset(new OfflinePageStorageManager(
1096 this, GetPolicyController(), archive_manager_.get()));
1097 }
1057 storage_manager_->ClearPagesIfNeeded(callback); 1098 storage_manager_->ClearPagesIfNeeded(callback);
1058 } 1099 }
1059 1100
1060 void OfflinePageModelImpl::OnStorageCleared(size_t expired_page_count, 1101 void OfflinePageModelImpl::OnStorageCleared(size_t expired_page_count,
1061 ClearStorageResult result) { 1102 ClearStorageResult result) {
1062 UMA_HISTOGRAM_ENUMERATION("OfflinePages.ClearStorageResult", 1103 UMA_HISTOGRAM_ENUMERATION("OfflinePages.ClearStorageResult",
1063 static_cast<int>(result), 1104 static_cast<int>(result),
1064 static_cast<int>(ClearStorageResult::RESULT_COUNT)); 1105 static_cast<int>(ClearStorageResult::RESULT_COUNT));
1065 if (expired_page_count > 0) { 1106 if (expired_page_count > 0) {
1066 UMA_HISTOGRAM_COUNTS("OfflinePages.ExpirePage.BatchSize", 1107 UMA_HISTOGRAM_COUNTS("OfflinePages.ExpirePage.BatchSize",
1067 static_cast<int32_t>(expired_page_count)); 1108 static_cast<int32_t>(expired_page_count));
1068 } 1109 }
1069 } 1110 }
1070 1111
1071 void OfflinePageModelImpl::PostClearStorageIfNeededTask() { 1112 void OfflinePageModelImpl::PostClearStorageIfNeededTask(bool delayed) {
1072 base::ThreadTaskRunnerHandle::Get()->PostTask( 1113 base::TimeDelta delay =
1114 delayed ? kStorageManagerStartingDelay : base::TimeDelta();
1115 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1073 FROM_HERE, base::Bind(&OfflinePageModelImpl::ClearStorageIfNeeded, 1116 FROM_HERE, base::Bind(&OfflinePageModelImpl::ClearStorageIfNeeded,
1074 weak_ptr_factory_.GetWeakPtr(), 1117 weak_ptr_factory_.GetWeakPtr(),
1075 base::Bind(&OfflinePageModelImpl::OnStorageCleared, 1118 base::Bind(&OfflinePageModelImpl::OnStorageCleared,
1076 weak_ptr_factory_.GetWeakPtr()))); 1119 weak_ptr_factory_.GetWeakPtr())),
1120 delay);
1077 } 1121 }
1078 1122
1079 bool OfflinePageModelImpl::IsRemovedOnCacheReset( 1123 bool OfflinePageModelImpl::IsRemovedOnCacheReset(
1080 const OfflinePageItem& offline_page) const { 1124 const OfflinePageItem& offline_page) const {
1081 return policy_controller_->IsRemovedOnCacheReset( 1125 return policy_controller_->IsRemovedOnCacheReset(
1082 offline_page.client_id.name_space); 1126 offline_page.client_id.name_space);
1083 } 1127 }
1084 1128
1085 void OfflinePageModelImpl::RunWhenLoaded(const base::Closure& task) { 1129 void OfflinePageModelImpl::RunWhenLoaded(const base::Closure& task) {
1086 if (!is_loaded_) { 1130 if (!is_loaded_) {
1087 delayed_tasks_.push_back(task); 1131 delayed_tasks_.push_back(task);
1088 return; 1132 return;
1089 } 1133 }
1090 1134
1091 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); 1135 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
1092 } 1136 }
1093 1137
1094 base::Time OfflinePageModelImpl::GetCurrentTime() const { 1138 base::Time OfflinePageModelImpl::GetCurrentTime() const {
1095 return testing_clock_ ? testing_clock_->Now() : base::Time::Now(); 1139 return testing_clock_ ? testing_clock_->Now() : base::Time::Now();
1096 } 1140 }
1097 1141
1098 } // namespace offline_pages 1142 } // namespace offline_pages
OLDNEW
« no previous file with comments | « components/offline_pages/offline_page_model_impl.h ('k') | components/offline_pages/offline_page_model_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698