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

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

Issue 10837244: Replace HistoryQuickProvider protobuf-based caching with an SQLite-based database. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Tweak suppression. Created 8 years, 4 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 #ifndef CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ 5 #ifndef CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_
6 #define CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ 6 #define CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_
7 7
8 #include <functional> 8 #include <functional>
9 #include <map> 9 #include <map>
10 #include <set> 10 #include <set>
11 #include <string> 11 #include <string>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/basictypes.h" 14 #include "base/basictypes.h"
15 #include "base/file_path.h" 15 #include "base/file_path.h"
16 #include "base/gtest_prod_util.h" 16 #include "base/gtest_prod_util.h"
17 #include "base/memory/ref_counted.h" 17 #include "base/memory/ref_counted.h"
18 #include "base/memory/weak_ptr.h" 18 #include "base/memory/weak_ptr.h"
19 #include "base/observer_list.h"
19 #include "base/string16.h" 20 #include "base/string16.h"
21 #include "base/threading/sequenced_worker_pool.h"
20 #include "chrome/browser/autocomplete/autocomplete_match.h" 22 #include "chrome/browser/autocomplete/autocomplete_match.h"
21 #include "chrome/browser/autocomplete/history_provider_util.h" 23 #include "chrome/browser/autocomplete/history_provider_util.h"
22 #include "chrome/browser/cancelable_request.h" 24 #include "chrome/browser/cancelable_request.h"
23 #include "chrome/browser/history/history.h" 25 #include "chrome/browser/history/history.h"
24 #include "chrome/browser/history/history_types.h" 26 #include "chrome/browser/history/history_types.h"
25 #include "chrome/browser/history/in_memory_url_index_types.h" 27 #include "chrome/browser/history/in_memory_url_index_types.h"
26 #include "chrome/browser/history/scored_history_match.h" 28 #include "chrome/browser/history/scored_history_match.h"
29 #include "chrome/browser/history/url_index_private_data.h"
27 #include "content/public/browser/notification_observer.h" 30 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h" 31 #include "content/public/browser/notification_registrar.h"
29 #include "sql/connection.h" 32 #include "sql/connection.h"
30 33
31 class HistoryQuickProviderTest; 34 class HistoryQuickProviderTest;
32 class Profile; 35 class Profile;
33 36
34 namespace base { 37 namespace base {
35 class Time; 38 class Time;
36 } 39 }
37 40
38 namespace in_memory_url_index {
39 class InMemoryURLIndexCacheItem;
40 }
41
42 namespace history { 41 namespace history {
43 42
44 namespace imui = in_memory_url_index; 43 class InMemoryURLIndexObserver;
45 44 class URLDatabase;
46 class HistoryDatabase; 45 struct URLsDeletedDetails;
47 class URLIndexPrivateData; 46 struct URLsModifiedDetails;
48 struct URLVisitedDetails; 47 struct URLVisitedDetails;
49 struct URLsModifiedDetails;
50 struct URLsDeletedDetails;
51 48
52 // The URL history source. 49 // The URL history source.
53 // Holds portions of the URL database in memory in an indexed form. Used to 50 // Holds portions of the URL database in memory in an indexed form. Used to
54 // quickly look up matching URLs for a given query string. Used by 51 // quickly look up matching URLs for a given query string. Used by
55 // the HistoryURLProvider for inline autocomplete and to provide URL 52 // the HistoryURLProvider for inline autocomplete and to provide URL
56 // matches to the omnibox. 53 // matches to the omnibox.
57 // 54 //
58 // Note about multi-byte codepoints and the data structures in the 55 // Note about multi-byte codepoints and the data structures in the
59 // InMemoryURLIndex class: One will quickly notice that no effort is made to 56 // InMemoryURLIndex class: One will quickly notice that no effort is made to
60 // insure that multi-byte character boundaries are detected when indexing the 57 // insure that multi-byte character boundaries are detected when indexing the
61 // words and characters in the URL history database except when converting 58 // words and characters in the URL history database except when converting
62 // URL strings to lowercase. Multi-byte-edness makes no difference when 59 // URL strings to lowercase. Multi-byte-edness makes no difference when
63 // indexing or when searching the index as the final filtering of results 60 // indexing or when searching the index as the final filtering of results
64 // is dependent on the comparison of a string of bytes, not individual 61 // is dependent on the comparison of a string of bytes, not individual
65 // characters. While the lookup of those bytes during a search in the 62 // characters. While the lookup of those bytes during a search in the
66 // |char_word_map_| could serve up words in which the individual char16 63 // |char_word_map_| could serve up words in which the individual char16
67 // occurs as a portion of a composite character the next filtering step 64 // occurs as a portion of a composite character the next filtering step
68 // will eliminate such words except in the case where a single character 65 // will eliminate such words except in the case where a single character
69 // is being searched on and which character occurs as the second char16 of a 66 // is being searched on and which character occurs as the second char16 of a
70 // multi-char16 instance. 67 // multi-char16 instance.
71 class InMemoryURLIndex : public content::NotificationObserver, 68 class InMemoryURLIndex : public content::NotificationObserver {
72 public base::SupportsWeakPtr<InMemoryURLIndex> {
73 public: 69 public:
74 // Defines an abstract class which is notified upon completion of restoring 70 // Observer is used for blocking until the InMemoryURLIndex has finished
75 // the index's private data either by reading from the cache file or by 71 // loading. Usage typically follows this pattern:
76 // rebuilding from the history database. 72 // InMemoryURLIndex::Observer observer(index); // Create observer.
77 class RestoreCacheObserver { 73 // MessageLoop::current()->Run(); // Blocks until loaded.
74 //
75 class Observer {
78 public: 76 public:
79 virtual ~RestoreCacheObserver(); 77 explicit Observer(InMemoryURLIndex* index);
80 78
81 // Callback that lets the observer know that the restore operation has 79 // Called when the InMemoryURLIndex has completed loading.
82 // completed. |succeeded| indicates if the restore was successful. This is 80 virtual void Loaded();
83 // called on the UI thread.
84 virtual void OnCacheRestoreFinished(bool succeeded) = 0;
85 };
86 81
87 // Defines an abstract class which is notified upon completion of saving 82 private:
88 // the index's private data to the cache file. 83 friend class InMemoryURLIndexBaseTest;
89 class SaveCacheObserver { 84 virtual ~Observer();
90 public:
91 virtual ~SaveCacheObserver();
92 85
93 // Callback that lets the observer know that the save succeeded. 86 InMemoryURLIndex* index_;
94 // This is called on the UI thread. 87
95 virtual void OnCacheSaveFinished(bool succeeded) = 0; 88 DISALLOW_COPY_AND_ASSIGN(Observer);
96 }; 89 };
97 90
98 // |profile|, which may be NULL during unit testing, is used to register for 91 // |profile|, which may be NULL during unit testing, is used to register for
99 // history changes. |history_dir| is a path to the directory containing the 92 // history changes. |history_dir| is a path to the directory containing the
100 // history database within the profile wherein the cache and transaction 93 // history database within the profile wherein the cache and transaction
101 // journals will be stored. |languages| gives a list of language encodings by 94 // journals will be stored. |languages| gives a list of language encodings by
102 // which URLs and omnibox searches are broken down into words and characters. 95 // which URLs and omnibox searches are broken down into words and characters.
103 InMemoryURLIndex(Profile* profile, 96 InMemoryURLIndex(Profile* profile,
104 const FilePath& history_dir, 97 const FilePath& history_dir,
105 const std::string& languages); 98 const std::string& languages);
106 virtual ~InMemoryURLIndex(); 99 virtual ~InMemoryURLIndex();
107 100
108 // Opens and prepares the index of historical URL visits. If the index private 101 // Opens and prepares the index of historical URL visits. If the index private
109 // data cannot be restored from its cache file then it is rebuilt from the 102 // data cannot be restored from its cache database then it is rebuilt from the
110 // history database. 103 // history database. |disable_cache| causes the InMemoryURLIndex to not create
111 void Init(); 104 // or use its cache database.
105 void Init(bool disable_cache);
112 106
113 // Signals that any outstanding initialization should be canceled and 107 // Signals that any outstanding initialization should be canceled.
114 // flushes the cache to disk. 108 void Shutdown();
115 void ShutDown(); 109
110 // Returns true if the index has been loaded or rebuilt and so is available
111 // for use.
112 bool index_available() const { return index_available_; }
116 113
117 // Scans the history index and returns a vector with all scored, matching 114 // Scans the history index and returns a vector with all scored, matching
118 // history items. This entry point simply forwards the call on to the 115 // history items. This entry point simply forwards the call on to the
119 // URLIndexPrivateData class. For a complete description of this function 116 // URLIndexPrivateData class. For a complete description of this function
120 // refer to that class. 117 // refer to that class.
121 ScoredHistoryMatches HistoryItemsForTerms(const string16& term_string); 118 ScoredHistoryMatches HistoryItemsForTerms(const string16& term_string);
122 119
123 // Sets the optional observers for completion of restoral and saving of the 120 // Deletes the index entry, if any, for the given |url|.
124 // index's private data. 121 void DeleteURL(const GURL& url);
125 void set_restore_cache_observer(
126 RestoreCacheObserver* restore_cache_observer) {
127 restore_cache_observer_ = restore_cache_observer;
128 }
129 void set_save_cache_observer(SaveCacheObserver* save_cache_observer) {
130 save_cache_observer_ = save_cache_observer;
131 }
132 122
133 private: 123 private:
134 friend class ::HistoryQuickProviderTest; 124 friend class ::HistoryQuickProviderTest;
125 friend class InMemoryURLIndex::Observer;
126 friend class InMemoryURLIndexCacheTest;
135 friend class InMemoryURLIndexTest; 127 friend class InMemoryURLIndexTest;
136 friend class InMemoryURLIndexCacheTest; 128 friend class InMemoryURLIndexBaseTest;
129 friend class IntercessionaryIndexTest;
130 FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, ExpireRow);
131 FRIEND_TEST_ALL_PREFIXES(IntercessionaryIndexTest, CacheDatabaseFailure);
132 FRIEND_TEST_ALL_PREFIXES(IntercessionaryIndexTest,
133 ShutdownDuringCacheRefresh);
137 FRIEND_TEST_ALL_PREFIXES(LimitedInMemoryURLIndexTest, Initialization); 134 FRIEND_TEST_ALL_PREFIXES(LimitedInMemoryURLIndexTest, Initialization);
138 135
139 // Creating one of me without a history path is not allowed (tests excepted).
140 InMemoryURLIndex();
141
142 // HistoryDBTask used to rebuild our private data from the history database. 136 // HistoryDBTask used to rebuild our private data from the history database.
143 class RebuildPrivateDataFromHistoryDBTask : public HistoryDBTask { 137 class RebuildPrivateDataFromHistoryDBTask : public HistoryDBTask {
144 public: 138 public:
145 explicit RebuildPrivateDataFromHistoryDBTask( 139 explicit RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index);
146 InMemoryURLIndex* index,
147 const std::string& languages,
148 const std::set<std::string>& scheme_whitelist);
149 140
150 virtual bool RunOnDBThread(HistoryBackend* backend, 141 virtual bool RunOnDBThread(HistoryBackend* backend,
151 history::HistoryDatabase* db) OVERRIDE; 142 history::HistoryDatabase* db) OVERRIDE;
152 virtual void DoneRunOnMainThread() OVERRIDE; 143 virtual void DoneRunOnMainThread() OVERRIDE;
153 144
154 private: 145 private:
155 virtual ~RebuildPrivateDataFromHistoryDBTask(); 146 virtual ~RebuildPrivateDataFromHistoryDBTask();
156 147
157 InMemoryURLIndex* index_; // Call back to this index at completion. 148 InMemoryURLIndex* index_; // Call back to this index at completion.
158 std::string languages_; // Languages for word-breaking.
159 std::set<std::string> scheme_whitelist_; // Schemes to be indexed.
160 bool succeeded_; // Indicates if the rebuild was successful. 149 bool succeeded_; // Indicates if the rebuild was successful.
161 scoped_refptr<URLIndexPrivateData> data_; // The rebuilt private data. 150 scoped_refptr<URLIndexPrivateData> data_; // The rebuilt private data.
162 151
163 DISALLOW_COPY_AND_ASSIGN(RebuildPrivateDataFromHistoryDBTask); 152 DISALLOW_COPY_AND_ASSIGN(RebuildPrivateDataFromHistoryDBTask);
164 }; 153 };
165 154
166 // Initializes all index data members in preparation for restoring the index 155 // For unit testing only.
167 // from the cache or a complete rebuild from the history database. 156 InMemoryURLIndex(const FilePath& history_dir, const std::string& languages);
168 void ClearPrivateData();
169 157
170 // Constructs a file path for the cache file within the same directory where 158 // Completes index initialization once the cache DB has been initialized.
171 // the history database is kept and saves that path to |file_path|. Returns 159 void OnPrivateDataInitDone(bool succeeded);
172 // true if |file_path| can be successfully constructed. (This function
173 // provided as a hook for unit testing.)
174 bool GetCacheFilePath(FilePath* file_path);
175 160
176 // Restores the index's private data from the cache file stored in the 161 // Adds or removes an observer that is notified when the index has been
177 // profile directory. 162 // loaded.
178 void PostRestoreFromCacheFileTask(); 163 void AddObserver(InMemoryURLIndex::Observer* observer);
164 void RemoveObserver(InMemoryURLIndex::Observer* observer);
165
166 // Handles notifications of history changes.
167 virtual void Observe(int notification_type,
168 const content::NotificationSource& source,
169 const content::NotificationDetails& details) OVERRIDE;
170
171 // Notification handlers.
172 void OnURLVisited(const URLVisitedDetails* details);
173 void OnURLsModified(const URLsModifiedDetails* details);
174 void OnURLsDeleted(const URLsDeletedDetails* details);
175
176 // Posts any outstanding updates to the index which were queued while the
177 // index was being initialized.
178 void FlushPendingUpdates();
179
180 // Restores the index's private data from the cache database stored in the
181 // profile directory. If no database is found or can be restored then look
182 // for an old version protobuf-based cache file.
183 void PostRestoreFromCacheTask();
184
185 // Determines if the private data was successfully restored from the cache
186 // database, as indicated by |succeeded|, or if the private data must be
187 // rebuilt from the history database. If successful, notifies any
188 // |restore_cache_observer_|. Otherwise, kicks off a rebuild from the history
189 // database.
190 void OnCacheRestoreDone(bool succeeded);
191
192 // Notifies all observers that the index has been loaded or rebuilt.
193 void NotifyHasLoaded();
194
195 // Rebuilds the index from the history database if the history database has
196 // been loaded, otherwise registers for the history loaded notification so
197 // that the rebuild can take place at a later time.
198 void RebuildFromHistoryIfLoaded();
179 199
180 // Schedules a history task to rebuild our private data from the history 200 // Schedules a history task to rebuild our private data from the history
181 // database. 201 // database.
182 void ScheduleRebuildFromHistory(); 202 void ScheduleRebuildFromHistory();
183 203
184 // Callback used by RebuildPrivateDataFromHistoryDBTask to signal completion 204 // Callback used by RebuildPrivateDataFromHistoryDBTask to signal completion
185 // or rebuilding our private data from the history database. |succeeded| 205 // or rebuilding our private data from the history database. |succeeded|
186 // will be true if the rebuild was successful. |data| will point to a new 206 // will be true if the rebuild was successful. |data| will point to a new
187 // instanceof the private data just rebuilt. 207 // instanceof the private data just rebuilt.
188 void DoneRebuidingPrivateDataFromHistoryDB( 208 void DoneRebuidingPrivateDataFromHistoryDB(
189 bool succeeded, 209 bool succeeded,
190 scoped_refptr<URLIndexPrivateData> private_data); 210 scoped_refptr<URLIndexPrivateData> private_data);
191 211
192 // Rebuilds the history index from the history database in |history_db|. 212 // Posts a task to completely reset the private data and the backing cache.
193 // Used for unit testing only. 213 void PostResetPrivateDataTask();
194 void RebuildFromHistory(HistoryDatabase* history_db);
195 214
196 // Determines if the private data was successfully reloaded from the cache 215 // Posts a task to completely replace the cache database with a current
197 // file or if the private data must be rebuilt from the history database. 216 // image of the index private data.
198 // |private_data_ptr|'s data will be NULL if the cache file load failed. If 217 void PostRefreshCacheTask();
199 // successful, sets the private data and notifies any
200 // |restore_cache_observer_|. Otherwise, kicks off a rebuild from the history
201 // database.
202 void OnCacheLoadDone(
203 scoped_refptr<URLIndexPrivateData> private_data_ptr);
204 218
205 // Callback function that sets the private data from the just-restored-from- 219 // Callback used by PostRefreshCacheTask and PostResetPrivateDataTask to
206 // file |private_data|. Notifies any |restore_cache_observer_| that the 220 // notify observers that the cache database contents have been refreshed or
207 // restore has succeeded. 221 // reset and that the loading of the index is complete.
208 void OnCacheRestored(URLIndexPrivateData* private_data); 222 void OnCacheRefreshOrResetDone();
209 223
210 // Posts a task to cache the index private data and write the cache file to 224 // Attempts to refresh the cache database in response to a notification that
211 // the profile directory. 225 // an update transaction has failed. If the refresh fails then the cache
212 void PostSaveToCacheFileTask(); 226 // database is ignored and an attempt will be made to rebuild the cache
227 // the next time the associated profile is opened.
228 void RepairCacheDatabase();
213 229
214 // Saves private_data_ to the given |path|. Runs on the UI thread. 230 // Returns a pointer to our private data.
215 // Provided for unit testing so that a test cache file can be used. 231 scoped_refptr<URLIndexPrivateData> private_data() { return private_data_; }
216 void DoSaveToCacheFile(const FilePath& path);
217 232
218 // Notifies the observer, if any, of the success of the private data caching. 233 // Returns the blocking pool sequence token.
219 // |succeeded| is true on a successful save. 234 base::SequencedWorkerPool::SequenceToken sequence_token_for_testing() {
220 void OnCacheSaveDone(scoped_refptr<RefCountedBool> succeeded); 235 return sequence_token_;
221 236 }
222 // Handles notifications of history changes.
223 virtual void Observe(int notification_type,
224 const content::NotificationSource& source,
225 const content::NotificationDetails& details) OVERRIDE;
226
227 // Notification handlers.
228 void OnURLVisited(const URLVisitedDetails* details);
229 void OnURLsModified(const URLsModifiedDetails* details);
230 void OnURLsDeleted(const URLsDeletedDetails* details);
231
232 // Sets the directory wherein the cache file will be maintained.
233 // For unit test usage only.
234 void set_history_dir(const FilePath& dir_path) { history_dir_ = dir_path; }
235
236 // Returns a pointer to our private data. For unit testing only.
237 URLIndexPrivateData* private_data() { return private_data_.get(); }
238
239 // Returns the set of whitelisted schemes. For unit testing only.
240 const std::set<std::string>& scheme_whitelist() { return scheme_whitelist_; }
241 237
242 // The profile, may be null when testing. 238 // The profile, may be null when testing.
243 Profile* profile_; 239 Profile* profile_;
244 240
245 // Directory where cache file resides. This is, except when unit testing,
246 // the same directory in which the profile's history database is found. It
247 // should never be empty.
248 FilePath history_dir_;
249
250 // Languages used during the word-breaking process during indexing. 241 // Languages used during the word-breaking process during indexing.
251 std::string languages_; 242 std::string languages_;
252 243
253 // Only URLs with a whitelisted scheme are indexed. 244 // Directory where cache database or protobuf-based cache file resides.
254 std::set<std::string> scheme_whitelist_; 245 // This is, except when unit testing, the same directory in which the
246 // profile's history database is found.
247 FilePath history_dir_;
255 248
256 // The index's durable private data. 249 // The index's durable private data.
257 scoped_refptr<URLIndexPrivateData> private_data_; 250 scoped_refptr<URLIndexPrivateData> private_data_;
258 251
259 // Observers to notify upon restoral or save of the private data cache. 252 // Sequence token for coordinating database tasks. This is shared with
260 RestoreCacheObserver* restore_cache_observer_; 253 // our private data and its cache database.
261 SaveCacheObserver* save_cache_observer_; 254 const base::SequencedWorkerPool::SequenceToken sequence_token_;
255
256 bool index_available_; // True when index is available for updating.
257
258 // Contains index updates queued up while the index is unavailable. This
259 // usually during profile startup.
260 enum UpdateType { UPDATE_VISIT, DELETE_VISIT };
261
262 struct IndexUpdateItem {
263 IndexUpdateItem(UpdateType update_type, URLRow row);
264 ~IndexUpdateItem();
265
266 UpdateType update_type;
267 URLRow row; // The row to be updated or deleted.
268 };
269 typedef std::vector<IndexUpdateItem> PendingUpdates;
270 PendingUpdates pending_updates_;
271
272 ObserverList<InMemoryURLIndex::Observer> observers_;
262 273
263 CancelableRequestConsumer cache_reader_consumer_; 274 CancelableRequestConsumer cache_reader_consumer_;
264 content::NotificationRegistrar registrar_; 275 content::NotificationRegistrar registrar_;
265 276
266 // Set to true once the shutdown process has begun. 277 // Set to true once the shutdown process has begun.
267 bool shutdown_; 278 bool shutdown_;
268 279
269 // Set to true when changes to the index have been made and the index needs 280 // Note: This should remain the last member so it'll be destroyed and
270 // to be cached. Set to false when the index has been cached. Used as a 281 // invalidate its weak pointers before any other members are destroyed.
271 // temporary safety check to insure that the cache is saved before the 282 base::WeakPtrFactory<InMemoryURLIndex> weak_ptr_factory_;
272 // index has been destructed.
273 // TODO(mrossetti): Eliminate once the transition to SQLite has been done.
274 // http://crbug.com/83659
275 bool needs_to_be_cached_;
276 283
277 DISALLOW_COPY_AND_ASSIGN(InMemoryURLIndex); 284 DISALLOW_COPY_AND_ASSIGN(InMemoryURLIndex);
278 }; 285 };
279 286
280 } // namespace history 287 } // namespace history
281 288
282 #endif // CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ 289 #endif // CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698