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

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

Powered by Google App Engine
This is Rietveld 408576698