Index: chrome/browser/history/in_memory_url_index.cc |
=================================================================== |
--- chrome/browser/history/in_memory_url_index.cc (revision 125078) |
+++ chrome/browser/history/in_memory_url_index.cc (working copy) |
@@ -4,23 +4,35 @@ |
#include "chrome/browser/history/in_memory_url_index.h" |
+#include "base/file_util.h" |
#include "base/utf_string_conversions.h" |
#include "chrome/browser/history/history_notifications.h" |
#include "chrome/browser/history/url_database.h" |
#include "chrome/browser/history/url_index_private_data.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/common/chrome_notification_types.h" |
+#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_service.h" |
#include "content/public/browser/notification_source.h" |
using in_memory_url_index::InMemoryURLIndexCacheItem; |
namespace history { |
+// Restore/SaveCacheObserver --------------------------------------------------- |
+ |
+InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {} |
+ |
+InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {} |
+ |
+// RebuildPrivateDataFromHistoryDBTask ----------------------------------------- |
+ |
InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index) |
: index_(index), |
- succeeded_(false) {} |
+ succeeded_(false) { |
+} |
InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
~RebuildPrivateDataFromHistoryDBTask() {} |
@@ -37,16 +49,19 @@ |
void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
DoneRunOnMainThread() { |
- if (succeeded_) |
- index_->DoneRebuidingPrivateDataFromHistoryDB(data_.release()); |
+ index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_.release()); |
brettw
2012/03/08 22:03:54
Style: outdent 2 sp
mrossetti
2012/03/10 00:03:46
Done.
|
} |
+// InMemoryURLIndex ------------------------------------------------------------ |
+ |
InMemoryURLIndex::InMemoryURLIndex(Profile* profile, |
const FilePath& history_dir, |
const std::string& languages) |
: profile_(profile), |
history_dir_(history_dir), |
private_data_(new URLIndexPrivateData), |
+ restore_cache_observer_(NULL), |
+ save_cache_observer_(NULL), |
shutdown_(false), |
needs_to_be_cached_(false) { |
private_data_->set_languages(languages); |
@@ -64,6 +79,8 @@ |
InMemoryURLIndex::InMemoryURLIndex() |
: profile_(NULL), |
private_data_(new URLIndexPrivateData), |
+ restore_cache_observer_(NULL), |
+ save_cache_observer_(NULL), |
shutdown_(false), |
needs_to_be_cached_(false) { |
} |
@@ -75,14 +92,14 @@ |
} |
void InMemoryURLIndex::Init() { |
- RestoreFromCacheFile(); |
+ PostRestoreFromCacheFileTask(); |
} |
void InMemoryURLIndex::ShutDown() { |
registrar_.RemoveAll(); |
cache_reader_consumer_.CancelAllRequests(); |
shutdown_ = true; |
- SaveToCacheFile(); |
+ PostSaveToCacheFileTask(); |
needs_to_be_cached_ = false; |
} |
@@ -121,12 +138,11 @@ |
OnURLsDeleted( |
content::Details<history::URLsDeletedDetails>(details).ptr()); |
break; |
- case chrome::NOTIFICATION_HISTORY_LOADED: { |
+ case chrome::NOTIFICATION_HISTORY_LOADED: |
registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED, |
content::Source<Profile>(profile_)); |
ScheduleRebuildFromHistory(); |
break; |
- } |
default: |
// For simplicity, the unit tests send us all notifications, even when |
// we haven't registered for them, so don't assert here. |
@@ -157,24 +173,50 @@ |
// Restoring from Cache -------------------------------------------------------- |
-void InMemoryURLIndex::RestoreFromCacheFile() { |
+void InMemoryURLIndex::PostRestoreFromCacheFileTask() { |
FilePath path; |
- if (GetCacheFilePath(&path) && !shutdown_) |
- DoRestoreFromCacheFile(path); |
+ if (!GetCacheFilePath(&path) || shutdown_) |
+ return; |
+ 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
|
+ content::BrowserThread::PostTaskAndReply( |
+ content::BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&URLIndexPrivateData::RestoreFromFileTask, path, |
+ restored_private_data), |
+ base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr(), |
+ restored_private_data)); |
} |
-void InMemoryURLIndex::DoRestoreFromCacheFile(const FilePath& path) { |
- if (private_data_->RestoreFromFile(path)) |
- return; |
+void InMemoryURLIndex::OnCacheLoadDone(URLIndexPrivateData* private_data) { |
+ if (private_data) { |
+ OnCacheRestored(private_data, true); |
+ } else if (profile_) { |
+ // When unable to restore from the cache file delete the cache file, if |
+ // it exists, and then rebuild from the history database if it's available, |
+ // otherwise wait until the history database loaded and then rebuild. |
+ FilePath path; |
+ if (!GetCacheFilePath(&path) || shutdown_) |
+ return; |
+ content::BrowserThread::PostBlockingPoolTask( |
+ FROM_HERE, base::Bind(InMemoryURLIndex::DeleteCacheFile, path)); |
+ HistoryService* service = profile_->GetHistoryServiceWithoutCreating(); |
+ if (service && service->backend_loaded()) |
+ ScheduleRebuildFromHistory(); |
+ else |
+ registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED, |
+ content::Source<Profile>(profile_)); |
+ } |
+} |
- // When unable to restore from the cache file we must rebuild from the |
- // history database. |
- HistoryService* service = profile_->GetHistoryServiceWithoutCreating(); |
- if (service && service->backend_loaded()) |
- ScheduleRebuildFromHistory(); |
- // We must wait to rebuild until the history backend has been loaded. |
- registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED, |
- content::Source<Profile>(profile_)); |
+void InMemoryURLIndex::OnCacheRestored(URLIndexPrivateData* private_data, |
+ bool succeeded) { |
+ // TODO(mrossetti): Take care of remembering any visit transactions while |
+ // we were away rebuilding the index and then apply them here. |
+ if (succeeded) |
+ private_data_.reset(private_data); |
+ else |
+ private_data_->Clear(); |
+ if (restore_cache_observer_) |
+ restore_cache_observer_->OnCacheRestoreFinished(succeeded); |
} |
// Restoring from the History DB ----------------------------------------------- |
@@ -188,13 +230,20 @@ |
} |
void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( |
+ bool succeeded, |
URLIndexPrivateData* data) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
scoped_ptr<URLIndexPrivateData> private_data(data); |
- private_data_.swap(private_data); |
- // Cache the newly rebuilt index. |
- FilePath cache_file_path; |
- if (GetCacheFilePath(&cache_file_path)) |
- private_data_->SaveToFile(cache_file_path); |
+ if (succeeded) { |
+ private_data_.swap(private_data); |
+ PostSaveToCacheFileTask(); // Cache the newly rebuilt index. |
mrossetti
2012/03/06 03:49:30
I'll fix the lint complaint about needing two spac
|
+ } else { |
+ private_data_->Clear(); // Dump the old private data. |
+ // There is no need to do anything with the cache file as it was deleted |
+ // when the rebuild from the history operation was kicked off. |
+ } |
+ if (restore_cache_observer_) |
+ restore_cache_observer_->OnCacheRestoreFinished(succeeded); |
} |
void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) { |
@@ -203,14 +252,42 @@ |
// Saving to Cache ------------------------------------------------------------- |
-void InMemoryURLIndex::SaveToCacheFile() { |
+void InMemoryURLIndex::PostSaveToCacheFileTask() { |
FilePath path; |
- if (GetCacheFilePath(&path)) |
- DoSaveToCacheFile(path); |
+ if (!GetCacheFilePath(&path)) |
+ return; |
+ // If there is anything in our private data then make a copy of it and tell |
+ // it to save itself to a file. |
+ URLIndexPrivateData* private_data = private_data_.get(); |
+ if (private_data && !private_data->Empty()) { |
+ // Note that ownership of the copy of our private data is passed to the |
+ // completion closure below. |
+ scoped_ptr<URLIndexPrivateData> private_data_copy( |
+ 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.
|
+ scoped_refptr<RefCountedBool> succeeded(new RefCountedBool(false)); |
+ content::BrowserThread::PostTaskAndReply( |
+ content::BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask, |
+ base::Passed(&private_data_copy), path, succeeded), |
+ base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr(), succeeded)); |
+ } else { |
+ // If there is no data in our index then delete any existing cache file. |
+ content::BrowserThread::PostBlockingPoolTask( |
+ FROM_HERE, |
+ base::Bind(InMemoryURLIndex::DeleteCacheFile, path)); |
+ } |
} |
-void InMemoryURLIndex::DoSaveToCacheFile(const FilePath& path) { |
- private_data_->SaveToFile(path); |
+void InMemoryURLIndex::OnCacheSaveDone( |
+ scoped_refptr<RefCountedBool> succeeded) { |
+ if (save_cache_observer_) |
+ save_cache_observer_->OnCacheSaveFinished(succeeded->value()); |
} |
+// static |
+void InMemoryURLIndex::DeleteCacheFile(const FilePath& path) { |
+ DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
+ file_util::Delete(path, false); |
+} |
+ |
} // namespace history |