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

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

Powered by Google App Engine
This is Rietveld 408576698