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

Side by Side Diff: chrome/browser/history/in_memory_url_index.cc

Issue 9030031: Move InMemoryURLIndex Caching Operations to FILE Thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/history/in_memory_url_index.h" 5 #include "chrome/browser/history/in_memory_url_index.h"
6 6
7 #include "base/file_util.h"
7 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/history/history_notifications.h" 9 #include "chrome/browser/history/history_notifications.h"
9 #include "chrome/browser/history/url_database.h" 10 #include "chrome/browser/history/url_database.h"
10 #include "chrome/browser/history/url_index_private_data.h" 11 #include "chrome/browser/history/url_index_private_data.h"
11 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/chrome_notification_types.h" 13 #include "chrome/common/chrome_notification_types.h"
14 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/notification_details.h" 15 #include "content/public/browser/notification_details.h"
16 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/notification_source.h" 17 #include "content/public/browser/notification_source.h"
15 18
16 using in_memory_url_index::InMemoryURLIndexCacheItem; 19 using in_memory_url_index::InMemoryURLIndexCacheItem;
17 20
18 namespace history { 21 namespace history {
19 22
23 // Called by DoSaveToCacheFile to delete any old cache file at |path| when
24 // there is no private data to save. Runs on the FILE thread.
25 void DeleteCacheFile(const FilePath& path) {
26 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
27 file_util::Delete(path, false);
28 }
29
30 // Restore/SaveCacheObserver ---------------------------------------------------
31
32 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
33
34 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
35
36 // RebuildPrivateDataFromHistoryDBTask -----------------------------------------
37
20 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 38 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
21 RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index) 39 RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index)
22 : index_(index), 40 : index_(index),
23 succeeded_(false) {} 41 succeeded_(false) {
42 }
24 43
25 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 44 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
26 ~RebuildPrivateDataFromHistoryDBTask() {} 45 ~RebuildPrivateDataFromHistoryDBTask() {}
27 46
28 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( 47 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
29 HistoryBackend* backend, 48 HistoryBackend* backend,
30 HistoryDatabase* db) { 49 HistoryDatabase* db) {
31 data_.reset(URLIndexPrivateData::RebuildFromHistory(db)); 50 data_.reset(URLIndexPrivateData::RebuildFromHistory(db));
32 succeeded_ = data_.get() && !data_->history_info_map_.empty(); 51 succeeded_ = data_.get() && !data_->history_info_map_.empty();
33 if (!succeeded_) 52 if (!succeeded_)
34 data_.reset(); 53 data_.reset();
35 return true; 54 return true;
36 } 55 }
37 56
38 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 57 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
39 DoneRunOnMainThread() { 58 DoneRunOnMainThread() {
40 if (succeeded_) 59 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_.release());
41 index_->DoneRebuidingPrivateDataFromHistoryDB(data_.release());
42 } 60 }
43 61
62 // InMemoryURLIndex ------------------------------------------------------------
63
44 InMemoryURLIndex::InMemoryURLIndex(Profile* profile, 64 InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
45 const FilePath& history_dir, 65 const FilePath& history_dir,
46 const std::string& languages) 66 const std::string& languages)
47 : profile_(profile), 67 : profile_(profile),
48 history_dir_(history_dir), 68 history_dir_(history_dir),
49 private_data_(new URLIndexPrivateData), 69 private_data_(new URLIndexPrivateData),
70 restore_cache_observer_(NULL),
71 save_cache_observer_(NULL),
50 shutdown_(false), 72 shutdown_(false),
51 needs_to_be_cached_(false) { 73 needs_to_be_cached_(false) {
52 private_data_->set_languages(languages); 74 private_data_->set_languages(languages);
53 if (profile) { 75 if (profile) {
54 // TODO(mrossetti): Register for language change notifications. 76 // TODO(mrossetti): Register for language change notifications.
55 content::Source<Profile> source(profile); 77 content::Source<Profile> source(profile);
56 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source); 78 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
57 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED, 79 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED,
58 source); 80 source);
59 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); 81 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
60 } 82 }
61 } 83 }
62 84
63 // Called only by unit tests. 85 // Called only by unit tests.
64 InMemoryURLIndex::InMemoryURLIndex() 86 InMemoryURLIndex::InMemoryURLIndex()
65 : profile_(NULL), 87 : profile_(NULL),
66 private_data_(new URLIndexPrivateData), 88 private_data_(new URLIndexPrivateData),
89 restore_cache_observer_(NULL),
90 save_cache_observer_(NULL),
67 shutdown_(false), 91 shutdown_(false),
68 needs_to_be_cached_(false) { 92 needs_to_be_cached_(false) {
69 } 93 }
70 94
71 InMemoryURLIndex::~InMemoryURLIndex() { 95 InMemoryURLIndex::~InMemoryURLIndex() {
72 // If there was a history directory (which there won't be for some unit tests) 96 // If there was a history directory (which there won't be for some unit tests)
73 // then insure that the cache has already been saved. 97 // then insure that the cache has already been saved.
74 DCHECK(history_dir_.empty() || !needs_to_be_cached_); 98 DCHECK(history_dir_.empty() || !needs_to_be_cached_);
75 } 99 }
76 100
77 void InMemoryURLIndex::Init() { 101 void InMemoryURLIndex::Init() {
78 RestoreFromCacheFile(); 102 PostRestoreFromCacheFileTask();
79 } 103 }
80 104
81 void InMemoryURLIndex::ShutDown() { 105 void InMemoryURLIndex::ShutDown() {
82 registrar_.RemoveAll(); 106 registrar_.RemoveAll();
83 cache_reader_consumer_.CancelAllRequests(); 107 cache_reader_consumer_.CancelAllRequests();
84 shutdown_ = true; 108 shutdown_ = true;
85 SaveToCacheFile(); 109 PostSaveToCacheFileTask();
86 needs_to_be_cached_ = false; 110 needs_to_be_cached_ = false;
87 } 111 }
88 112
89 void InMemoryURLIndex::ClearPrivateData() { 113 void InMemoryURLIndex::ClearPrivateData() {
90 private_data_->Clear(); 114 private_data_->Clear();
91 } 115 }
92 116
93 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) { 117 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) {
94 if (history_dir_.empty()) 118 if (history_dir_.empty())
95 return false; 119 return false;
(...skipping 18 matching lines...) Expand all
114 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr()); 138 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr());
115 break; 139 break;
116 case chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED: 140 case chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED:
117 OnURLsModified( 141 OnURLsModified(
118 content::Details<history::URLsModifiedDetails>(details).ptr()); 142 content::Details<history::URLsModifiedDetails>(details).ptr());
119 break; 143 break;
120 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: 144 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
121 OnURLsDeleted( 145 OnURLsDeleted(
122 content::Details<history::URLsDeletedDetails>(details).ptr()); 146 content::Details<history::URLsDeletedDetails>(details).ptr());
123 break; 147 break;
124 case chrome::NOTIFICATION_HISTORY_LOADED: { 148 case chrome::NOTIFICATION_HISTORY_LOADED:
125 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED, 149 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED,
126 content::Source<Profile>(profile_)); 150 content::Source<Profile>(profile_));
127 ScheduleRebuildFromHistory(); 151 ScheduleRebuildFromHistory();
128 break; 152 break;
129 }
130 default: 153 default:
131 // For simplicity, the unit tests send us all notifications, even when 154 // For simplicity, the unit tests send us all notifications, even when
132 // we haven't registered for them, so don't assert here. 155 // we haven't registered for them, so don't assert here.
133 break; 156 break;
134 } 157 }
135 } 158 }
136 159
137 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) { 160 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) {
138 needs_to_be_cached_ |= private_data_->UpdateURL(details->row); 161 needs_to_be_cached_ |= private_data_->UpdateURL(details->row);
139 } 162 }
(...skipping 10 matching lines...) Expand all
150 needs_to_be_cached_ = true; 173 needs_to_be_cached_ = true;
151 } else { 174 } else {
152 for (URLRows::const_iterator row = details->rows.begin(); 175 for (URLRows::const_iterator row = details->rows.begin();
153 row != details->rows.end(); ++row) 176 row != details->rows.end(); ++row)
154 needs_to_be_cached_ |= private_data_->DeleteURL(row->url()); 177 needs_to_be_cached_ |= private_data_->DeleteURL(row->url());
155 } 178 }
156 } 179 }
157 180
158 // Restoring from Cache -------------------------------------------------------- 181 // Restoring from Cache --------------------------------------------------------
159 182
160 void InMemoryURLIndex::RestoreFromCacheFile() { 183 void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
161 FilePath path; 184 FilePath path;
162 if (GetCacheFilePath(&path) && !shutdown_) 185 if (!GetCacheFilePath(&path) || shutdown_)
163 DoRestoreFromCacheFile(path); 186 return;
187 scoped_refptr<RefCountedURLIndexPrivateDataPtr> restored_private_data =
188 new RefCountedURLIndexPrivateDataPtr;
189 content::BrowserThread::PostTaskAndReply(
190 content::BrowserThread::FILE, FROM_HERE,
191 base::Bind(&URLIndexPrivateData::RestoreFromFileTask, path,
192 restored_private_data),
193 base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr(),
194 restored_private_data));
164 } 195 }
165 196
166 void InMemoryURLIndex::DoRestoreFromCacheFile(const FilePath& path) { 197 void InMemoryURLIndex::OnCacheLoadDone(
167 if (private_data_->RestoreFromFile(path)) 198 scoped_refptr<RefCountedURLIndexPrivateDataPtr> private_data_ptr) {
168 return; 199 URLIndexPrivateData* private_data = private_data_ptr->release();
200 if (private_data) {
201 OnCacheRestored(private_data, true);
202 } else if (profile_) {
203 // When unable to restore from the cache file delete the cache file, if
204 // it exists, and then rebuild from the history database if it's available,
205 // otherwise wait until the history database loaded and then rebuild.
206 FilePath path;
207 if (!GetCacheFilePath(&path) || shutdown_)
208 return;
209 content::BrowserThread::PostBlockingPoolTask(
210 FROM_HERE, base::Bind(DeleteCacheFile, path));
211 HistoryService* service = profile_->GetHistoryServiceWithoutCreating();
212 if (service && service->backend_loaded())
213 ScheduleRebuildFromHistory();
214 else
215 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
216 content::Source<Profile>(profile_));
217 }
218 }
169 219
170 // When unable to restore from the cache file we must rebuild from the 220 void InMemoryURLIndex::OnCacheRestored(URLIndexPrivateData* private_data,
171 // history database. 221 bool succeeded) {
172 HistoryService* service = profile_->GetHistoryServiceWithoutCreating(); 222 // TODO(mrossetti): Take care of remembering any visit transactions while
173 if (service && service->backend_loaded()) 223 // we were away rebuilding the index and then apply them here.
174 ScheduleRebuildFromHistory(); 224 if (succeeded)
175 // We must wait to rebuild until the history backend has been loaded. 225 private_data_.reset(private_data);
176 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED, 226 else
177 content::Source<Profile>(profile_)); 227 private_data_->Clear();
brettw 2012/03/12 04:37:40 You leak the data here.
mrossetti 2012/03/12 23:21:13 Fixed. On 2012/03/12 04:37:40, brettw wrote:
228 if (restore_cache_observer_)
229 restore_cache_observer_->OnCacheRestoreFinished(succeeded);
178 } 230 }
179 231
180 // Restoring from the History DB ----------------------------------------------- 232 // Restoring from the History DB -----------------------------------------------
181 233
182 void InMemoryURLIndex::ScheduleRebuildFromHistory() { 234 void InMemoryURLIndex::ScheduleRebuildFromHistory() {
183 HistoryService* service = 235 HistoryService* service =
184 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 236 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
185 service->ScheduleDBTask( 237 service->ScheduleDBTask(
186 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(this), 238 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(this),
187 &cache_reader_consumer_); 239 &cache_reader_consumer_);
188 } 240 }
189 241
190 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( 242 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
243 bool succeeded,
191 URLIndexPrivateData* data) { 244 URLIndexPrivateData* data) {
245 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
192 scoped_ptr<URLIndexPrivateData> private_data(data); 246 scoped_ptr<URLIndexPrivateData> private_data(data);
193 private_data_.swap(private_data); 247 if (succeeded) {
194 // Cache the newly rebuilt index. 248 private_data_.swap(private_data);
195 FilePath cache_file_path; 249 PostSaveToCacheFileTask(); // Cache the newly rebuilt index.
196 if (GetCacheFilePath(&cache_file_path)) 250 } else {
197 private_data_->SaveToFile(cache_file_path); 251 private_data_->Clear(); // Dump the old private data.
252 // There is no need to do anything with the cache file as it was deleted
253 // when the rebuild from the history operation was kicked off.
254 }
255 if (restore_cache_observer_)
256 restore_cache_observer_->OnCacheRestoreFinished(succeeded);
198 } 257 }
199 258
200 void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) { 259 void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
201 private_data_.reset(URLIndexPrivateData::RebuildFromHistory(history_db)); 260 private_data_.reset(URLIndexPrivateData::RebuildFromHistory(history_db));
202 } 261 }
203 262
204 // Saving to Cache ------------------------------------------------------------- 263 // Saving to Cache -------------------------------------------------------------
205 264
206 void InMemoryURLIndex::SaveToCacheFile() { 265 void InMemoryURLIndex::PostSaveToCacheFileTask() {
207 FilePath path; 266 FilePath path;
208 if (GetCacheFilePath(&path)) 267 if (!GetCacheFilePath(&path))
209 DoSaveToCacheFile(path); 268 return;
269 // If there is anything in our private data then make a copy of it and tell
270 // it to save itself to a file.
271 URLIndexPrivateData* private_data = private_data_.get();
272 if (private_data && !private_data->Empty()) {
273 // Note that ownership of the copy of our private data is passed to the
274 // completion closure below.
275 scoped_ptr<URLIndexPrivateData> private_data_copy(
276 new URLIndexPrivateData(*private_data));
277 scoped_refptr<RefCountedBool> succeeded(new RefCountedBool(false));
278 content::BrowserThread::PostTaskAndReply(
279 content::BrowserThread::FILE, FROM_HERE,
280 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
281 base::Passed(&private_data_copy), path, succeeded),
282 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr(), succeeded));
283 } else {
284 // If there is no data in our index then delete any existing cache file.
285 content::BrowserThread::PostBlockingPoolTask(
286 FROM_HERE,
287 base::Bind(DeleteCacheFile, path));
288 }
210 } 289 }
211 290
212 void InMemoryURLIndex::DoSaveToCacheFile(const FilePath& path) { 291 void InMemoryURLIndex::OnCacheSaveDone(
213 private_data_->SaveToFile(path); 292 scoped_refptr<RefCountedBool> succeeded) {
293 if (save_cache_observer_)
294 save_cache_observer_->OnCacheSaveFinished(succeeded->value());
214 } 295 }
215 296
216 } // namespace history 297 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698