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

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

Powered by Google App Engine
This is Rietveld 408576698