Index: chrome/browser/history/in_memory_url_index.h |
=================================================================== |
--- chrome/browser/history/in_memory_url_index.h (revision 151481) |
+++ chrome/browser/history/in_memory_url_index.h (working copy) |
@@ -16,7 +16,9 @@ |
#include "base/gtest_prod_util.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/weak_ptr.h" |
+#include "base/observer_list.h" |
#include "base/string16.h" |
+#include "base/threading/sequenced_worker_pool.h" |
#include "chrome/browser/autocomplete/autocomplete_match.h" |
#include "chrome/browser/autocomplete/history_provider_util.h" |
#include "chrome/browser/cancelable_request.h" |
@@ -24,6 +26,7 @@ |
#include "chrome/browser/history/history_types.h" |
#include "chrome/browser/history/in_memory_url_index_types.h" |
#include "chrome/browser/history/scored_history_match.h" |
+#include "chrome/browser/history/url_index_private_data.h" |
#include "content/public/browser/notification_observer.h" |
#include "content/public/browser/notification_registrar.h" |
#include "sql/connection.h" |
@@ -35,19 +38,13 @@ |
class Time; |
} |
-namespace in_memory_url_index { |
-class InMemoryURLIndexCacheItem; |
-} |
- |
namespace history { |
-namespace imui = in_memory_url_index; |
- |
-class HistoryDatabase; |
-class URLIndexPrivateData; |
+class InMemoryURLIndexObserver; |
+class URLDatabase; |
+struct URLsDeletedDetails; |
+struct URLsModifiedDetails; |
struct URLVisitedDetails; |
-struct URLsModifiedDetails; |
-struct URLsDeletedDetails; |
// The URL history source. |
// Holds portions of the URL database in memory in an indexed form. Used to |
@@ -68,31 +65,27 @@ |
// will eliminate such words except in the case where a single character |
// is being searched on and which character occurs as the second char16 of a |
// multi-char16 instance. |
-class InMemoryURLIndex : public content::NotificationObserver, |
- public base::SupportsWeakPtr<InMemoryURLIndex> { |
+class InMemoryURLIndex : public content::NotificationObserver { |
public: |
- // Defines an abstract class which is notified upon completion of restoring |
- // the index's private data either by reading from the cache file or by |
- // rebuilding from the history database. |
- class RestoreCacheObserver { |
+ // Observer is used for blocking until the InMemoryURLIndex has finished |
+ // loading. Usage typically follows this pattern: |
+ // InMemoryURLIndex::Observer observer(index); // Create observer. |
+ // MessageLoop::current()->Run(); // Blocks until loaded. |
+ // |
+ class Observer { |
public: |
- virtual ~RestoreCacheObserver(); |
+ explicit Observer(InMemoryURLIndex* index); |
- // Callback that lets the observer know that the restore operation has |
- // completed. |succeeded| indicates if the restore was successful. This is |
- // called on the UI thread. |
- virtual void OnCacheRestoreFinished(bool succeeded) = 0; |
- }; |
+ // Called when the InMemoryURLIndex has completed loading. |
+ virtual void Loaded(); |
- // Defines an abstract class which is notified upon completion of saving |
- // the index's private data to the cache file. |
- class SaveCacheObserver { |
- public: |
- virtual ~SaveCacheObserver(); |
+ private: |
+ friend class InMemoryURLIndexBaseTest; |
+ virtual ~Observer(); |
- // Callback that lets the observer know that the save succeeded. |
- // This is called on the UI thread. |
- virtual void OnCacheSaveFinished(bool succeeded) = 0; |
+ InMemoryURLIndex* index_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Observer); |
}; |
// |profile|, which may be NULL during unit testing, is used to register for |
@@ -106,46 +99,44 @@ |
virtual ~InMemoryURLIndex(); |
// Opens and prepares the index of historical URL visits. If the index private |
- // data cannot be restored from its cache file then it is rebuilt from the |
- // history database. |
- void Init(); |
+ // data cannot be restored from its cache database then it is rebuilt from the |
+ // history database. |disable_cache| causes the InMemoryURLIndex to not create |
+ // or use its cache database. |
+ void Init(bool disable_cache); |
- // Signals that any outstanding initialization should be canceled and |
- // flushes the cache to disk. |
- void ShutDown(); |
+ // Signals that any outstanding initialization should be canceled. |
+ void Shutdown(); |
+ // Returns true if the index has been loaded or rebuilt and so is available |
+ // for use. |
+ bool index_available() const { return index_available_; } |
+ |
// Scans the history index and returns a vector with all scored, matching |
// history items. This entry point simply forwards the call on to the |
// URLIndexPrivateData class. For a complete description of this function |
// refer to that class. |
ScoredHistoryMatches HistoryItemsForTerms(const string16& term_string); |
- // Sets the optional observers for completion of restoral and saving of the |
- // index's private data. |
- void set_restore_cache_observer( |
- RestoreCacheObserver* restore_cache_observer) { |
- restore_cache_observer_ = restore_cache_observer; |
- } |
- void set_save_cache_observer(SaveCacheObserver* save_cache_observer) { |
- save_cache_observer_ = save_cache_observer; |
- } |
+ // Deletes the index entry, if any, for the given |url|. |
+ void DeleteURL(const GURL& url); |
private: |
friend class ::HistoryQuickProviderTest; |
+ friend class InMemoryURLIndex::Observer; |
+ friend class InMemoryURLIndexCacheTest; |
friend class InMemoryURLIndexTest; |
- friend class InMemoryURLIndexCacheTest; |
+ friend class InMemoryURLIndexBaseTest; |
+ friend class IntercessionaryIndexTest; |
+ FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, ExpireRow); |
+ FRIEND_TEST_ALL_PREFIXES(IntercessionaryIndexTest, CacheDatabaseFailure); |
+ FRIEND_TEST_ALL_PREFIXES(IntercessionaryIndexTest, |
+ ShutdownDuringCacheRefresh); |
FRIEND_TEST_ALL_PREFIXES(LimitedInMemoryURLIndexTest, Initialization); |
- // Creating one of me without a history path is not allowed (tests excepted). |
- InMemoryURLIndex(); |
- |
// HistoryDBTask used to rebuild our private data from the history database. |
class RebuildPrivateDataFromHistoryDBTask : public HistoryDBTask { |
public: |
- explicit RebuildPrivateDataFromHistoryDBTask( |
- InMemoryURLIndex* index, |
- const std::string& languages, |
- const std::set<std::string>& scheme_whitelist); |
+ explicit RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index); |
virtual bool RunOnDBThread(HistoryBackend* backend, |
history::HistoryDatabase* db) OVERRIDE; |
@@ -155,28 +146,57 @@ |
virtual ~RebuildPrivateDataFromHistoryDBTask(); |
InMemoryURLIndex* index_; // Call back to this index at completion. |
- std::string languages_; // Languages for word-breaking. |
- std::set<std::string> scheme_whitelist_; // Schemes to be indexed. |
bool succeeded_; // Indicates if the rebuild was successful. |
scoped_refptr<URLIndexPrivateData> data_; // The rebuilt private data. |
DISALLOW_COPY_AND_ASSIGN(RebuildPrivateDataFromHistoryDBTask); |
}; |
- // Initializes all index data members in preparation for restoring the index |
- // from the cache or a complete rebuild from the history database. |
- void ClearPrivateData(); |
+ // For unit testing only. |
+ InMemoryURLIndex(const FilePath& history_dir, const std::string& languages); |
- // Constructs a file path for the cache file within the same directory where |
- // the history database is kept and saves that path to |file_path|. Returns |
- // true if |file_path| can be successfully constructed. (This function |
- // provided as a hook for unit testing.) |
- bool GetCacheFilePath(FilePath* file_path); |
+ // Completes index initialization once the cache DB has been initialized. |
+ void OnPrivateDataInitDone(bool succeeded); |
- // Restores the index's private data from the cache file stored in the |
- // profile directory. |
- void PostRestoreFromCacheFileTask(); |
+ // Adds or removes an observer that is notified when the index has been |
+ // loaded. |
+ void AddObserver(InMemoryURLIndex::Observer* observer); |
+ void RemoveObserver(InMemoryURLIndex::Observer* observer); |
+ // Handles notifications of history changes. |
+ virtual void Observe(int notification_type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) OVERRIDE; |
+ |
+ // Notification handlers. |
+ void OnURLVisited(const URLVisitedDetails* details); |
+ void OnURLsModified(const URLsModifiedDetails* details); |
+ void OnURLsDeleted(const URLsDeletedDetails* details); |
+ |
+ // Posts any outstanding updates to the index which were queued while the |
+ // index was being initialized. |
+ void FlushPendingUpdates(); |
+ |
+ // Restores the index's private data from the cache database stored in the |
+ // profile directory. If no database is found or can be restored then look |
+ // for an old version protobuf-based cache file. |
+ void PostRestoreFromCacheTask(); |
+ |
+ // Determines if the private data was successfully restored from the cache |
+ // database, as indicated by |succeeded|, or if the private data must be |
+ // rebuilt from the history database. If successful, notifies any |
+ // |restore_cache_observer_|. Otherwise, kicks off a rebuild from the history |
+ // database. |
+ void OnCacheRestoreDone(bool succeeded); |
+ |
+ // Notifies all observers that the index has been loaded or rebuilt. |
+ void NotifyHasLoaded(); |
+ |
+ // Rebuilds the index from the history database if the history database has |
+ // been loaded, otherwise registers for the history loaded notification so |
+ // that the rebuild can take place at a later time. |
+ void RebuildFromHistoryIfLoaded(); |
+ |
// Schedules a history task to rebuild our private data from the history |
// database. |
void ScheduleRebuildFromHistory(); |
@@ -189,90 +209,77 @@ |
bool succeeded, |
scoped_refptr<URLIndexPrivateData> private_data); |
- // Rebuilds the history index from the history database in |history_db|. |
- // Used for unit testing only. |
- void RebuildFromHistory(HistoryDatabase* history_db); |
+ // Posts a task to completely reset the private data and the backing cache. |
+ void PostResetPrivateDataTask(); |
- // Determines if the private data was successfully reloaded from the cache |
- // file or if the private data must be rebuilt from the history database. |
- // |private_data_ptr|'s data will be NULL if the cache file load failed. If |
- // successful, sets the private data and notifies any |
- // |restore_cache_observer_|. Otherwise, kicks off a rebuild from the history |
- // database. |
- void OnCacheLoadDone( |
- scoped_refptr<URLIndexPrivateData> private_data_ptr); |
+ // Posts a task to completely replace the cache database with a current |
+ // image of the index private data. |
+ void PostRefreshCacheTask(); |
- // Callback function that sets the private data from the just-restored-from- |
- // file |private_data|. Notifies any |restore_cache_observer_| that the |
- // restore has succeeded. |
- void OnCacheRestored(URLIndexPrivateData* private_data); |
+ // Callback used by PostRefreshCacheTask and PostResetPrivateDataTask to |
+ // notify observers that the cache database contents have been refreshed or |
+ // reset and that the loading of the index is complete. |
+ void OnCacheRefreshOrResetDone(); |
- // Posts a task to cache the index private data and write the cache file to |
- // the profile directory. |
- void PostSaveToCacheFileTask(); |
+ // Attempts to refresh the cache database in response to a notification that |
+ // an update transaction has failed. If the refresh fails then the cache |
+ // database is ignored and an attempt will be made to rebuild the cache |
+ // the next time the associated profile is opened. |
+ void RepairCacheDatabase(); |
- // Saves private_data_ to the given |path|. Runs on the UI thread. |
- // Provided for unit testing so that a test cache file can be used. |
- void DoSaveToCacheFile(const FilePath& path); |
+ // Returns a pointer to our private data. |
+ scoped_refptr<URLIndexPrivateData> private_data() { return private_data_; } |
- // Notifies the observer, if any, of the success of the private data caching. |
- // |succeeded| is true on a successful save. |
- void OnCacheSaveDone(scoped_refptr<RefCountedBool> succeeded); |
+ // Returns the blocking pool sequence token. |
+ base::SequencedWorkerPool::SequenceToken sequence_token_for_testing() { |
+ return sequence_token_; |
+ } |
- // Handles notifications of history changes. |
- virtual void Observe(int notification_type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) OVERRIDE; |
- |
- // Notification handlers. |
- void OnURLVisited(const URLVisitedDetails* details); |
- void OnURLsModified(const URLsModifiedDetails* details); |
- void OnURLsDeleted(const URLsDeletedDetails* details); |
- |
- // Sets the directory wherein the cache file will be maintained. |
- // For unit test usage only. |
- void set_history_dir(const FilePath& dir_path) { history_dir_ = dir_path; } |
- |
- // Returns a pointer to our private data. For unit testing only. |
- URLIndexPrivateData* private_data() { return private_data_.get(); } |
- |
- // Returns the set of whitelisted schemes. For unit testing only. |
- const std::set<std::string>& scheme_whitelist() { return scheme_whitelist_; } |
- |
// The profile, may be null when testing. |
Profile* profile_; |
- // Directory where cache file resides. This is, except when unit testing, |
- // the same directory in which the profile's history database is found. It |
- // should never be empty. |
- FilePath history_dir_; |
- |
// Languages used during the word-breaking process during indexing. |
std::string languages_; |
- // Only URLs with a whitelisted scheme are indexed. |
- std::set<std::string> scheme_whitelist_; |
+ // Directory where cache database or protobuf-based cache file resides. |
+ // This is, except when unit testing, the same directory in which the |
+ // profile's history database is found. |
+ FilePath history_dir_; |
// The index's durable private data. |
scoped_refptr<URLIndexPrivateData> private_data_; |
- // Observers to notify upon restoral or save of the private data cache. |
- RestoreCacheObserver* restore_cache_observer_; |
- SaveCacheObserver* save_cache_observer_; |
+ // Sequence token for coordinating database tasks. This is shared with |
+ // our private data and its cache database. |
+ const base::SequencedWorkerPool::SequenceToken sequence_token_; |
+ bool index_available_; // True when index is available for updating. |
+ |
+ // Contains index updates queued up while the index is unavailable. This |
+ // usually during profile startup. |
+ enum UpdateType { UPDATE_VISIT, DELETE_VISIT }; |
+ |
+ struct IndexUpdateItem { |
+ IndexUpdateItem(UpdateType update_type, URLRow row); |
+ ~IndexUpdateItem(); |
+ |
+ UpdateType update_type; |
+ URLRow row; // The row to be updated or deleted. |
+ }; |
+ typedef std::vector<IndexUpdateItem> PendingUpdates; |
+ PendingUpdates pending_updates_; |
+ |
+ ObserverList<InMemoryURLIndex::Observer> observers_; |
+ |
CancelableRequestConsumer cache_reader_consumer_; |
content::NotificationRegistrar registrar_; |
// Set to true once the shutdown process has begun. |
bool shutdown_; |
- // Set to true when changes to the index have been made and the index needs |
- // to be cached. Set to false when the index has been cached. Used as a |
- // temporary safety check to insure that the cache is saved before the |
- // index has been destructed. |
- // TODO(mrossetti): Eliminate once the transition to SQLite has been done. |
- // http://crbug.com/83659 |
- bool needs_to_be_cached_; |
+ // Note: This should remain the last member so it'll be destroyed and |
+ // invalidate its weak pointers before any other members are destroyed. |
+ base::WeakPtrFactory<InMemoryURLIndex> weak_ptr_factory_; |
DISALLOW_COPY_AND_ASSIGN(InMemoryURLIndex); |
}; |