1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Places code.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * the Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Marco Bonardo <mak77@bonardo.net> (Original Author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef mozilla_places_Database_h_
39 : #define mozilla_places_Database_h_
40 :
41 : #include "nsThreadUtils.h"
42 : #include "nsWeakReference.h"
43 : #include "nsIInterfaceRequestorUtils.h"
44 : #include "nsIObserver.h"
45 : #include "mozilla/storage.h"
46 : #include "mozilla/storage/StatementCache.h"
47 :
48 : // This is the schema version. Update it at any schema change and add a
49 : // corresponding migrateVxx method below.
50 : #define DATABASE_SCHEMA_VERSION 19
51 :
52 : // Fired after Places inited.
53 : #define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
54 : // Fired when initialization fails due to a locked database.
55 : #define TOPIC_DATABASE_LOCKED "places-database-locked"
56 : // This topic is received when the profile is about to be lost. Places does
57 : // initial shutdown work and notifies TOPIC_PLACES_SHUTDOWN to all listeners.
58 : // Any shutdown work that requires the Places APIs should happen here.
59 : #define TOPIC_PROFILE_CHANGE_TEARDOWN "profile-change-teardown"
60 : // This topic is received just before the profile is lost. Places begins
61 : // shutting down the connection and notifies TOPIC_PLACES_WILL_CLOSE_CONNECTION
62 : // to all listeners. Only critical database cleanups should happen here,
63 : // some APIs may bail out already.
64 : #define TOPIC_PROFILE_BEFORE_CHANGE "profile-before-change"
65 : // Fired when Places is shutting down. Any code should stop accessing Places
66 : // APIs after this notification. If you need to listen for Places shutdown
67 : // you should only use this notification, next ones are intended only for
68 : // internal Places use.
69 : #define TOPIC_PLACES_SHUTDOWN "places-shutdown"
70 : // For Internal use only. Fired when connection is about to be closed, only
71 : // cleanup tasks should run at this stage, nothing should be added to the
72 : // database, nor APIs should be called.
73 : #define TOPIC_PLACES_WILL_CLOSE_CONNECTION "places-will-close-connection"
74 : // Fired when the connection has gone, nothing will work from now on.
75 : #define TOPIC_PLACES_CONNECTION_CLOSED "places-connection-closed"
76 :
77 : class nsIStringBundle;
78 :
79 : namespace mozilla {
80 : namespace places {
81 :
82 : enum JournalMode {
83 : // Default SQLite journal mode.
84 : JOURNAL_DELETE = 0
85 : // Can reduce fsyncs on Linux when journal is deleted (See bug 460315).
86 : // We fallback to this mode when WAL is unavailable.
87 : , JOURNAL_TRUNCATE
88 : // Unsafe in case of crashes on database swap or low memory.
89 : , JOURNAL_MEMORY
90 : // Can reduce number of fsyncs. We try to use this mode by default.
91 : , JOURNAL_WAL
92 : };
93 :
94 : class Database : public nsIObserver
95 : , public nsSupportsWeakReference
96 : {
97 : typedef mozilla::storage::StatementCache<mozIStorageStatement> StatementCache;
98 : typedef mozilla::storage::StatementCache<mozIStorageAsyncStatement> AsyncStatementCache;
99 :
100 : public:
101 : NS_DECL_ISUPPORTS
102 : NS_DECL_NSIOBSERVER
103 :
104 : Database();
105 :
106 : /**
107 : * Initializes the database connection and the schema.
108 : * In case of corruption the database is copied to a backup file and replaced.
109 : */
110 : nsresult Init();
111 :
112 : /**
113 : * Finalizes the cached statements and closes the database connection.
114 : * A TOPIC_PLACES_CONNECTION_CLOSED notification is fired when done.
115 : */
116 : void Shutdown();
117 :
118 : /**
119 : * Getter to use when instantiating the class.
120 : *
121 : * @return Singleton instance of this class.
122 : */
123 7409 : static already_AddRefed<Database> GetDatabase()
124 : {
125 7409 : return GetSingleton();
126 : }
127 :
128 : /**
129 : * Returns last known database status.
130 : *
131 : * @return one of the nsINavHistoryService::DATABASE_STATUS_* constants.
132 : */
133 30 : PRUint16 GetDatabaseStatus() const
134 : {
135 30 : return mDatabaseStatus;
136 : }
137 :
138 : /**
139 : * Returns a pointer to the storage connection.
140 : *
141 : * @return The connection handle.
142 : */
143 18092 : mozIStorageConnection* MainConn() const
144 : {
145 18092 : return mMainConn;
146 : }
147 :
148 : /**
149 : * Dispatches a runnable to the connection async thread, to be serialized
150 : * with async statements.
151 : *
152 : * @param aEvent
153 : * The runnable to be dispatched.
154 : */
155 329 : void DispatchToAsyncThread(nsIRunnable* aEvent) const
156 : {
157 329 : if (mShuttingDown) {
158 0 : return;
159 : }
160 658 : nsCOMPtr<nsIEventTarget> target = do_GetInterface(mMainConn);
161 329 : if (target) {
162 329 : (void)target->Dispatch(aEvent, NS_DISPATCH_NORMAL);
163 : }
164 : }
165 :
166 : //////////////////////////////////////////////////////////////////////////////
167 : //// Statements Getters.
168 :
169 : /**
170 : * Gets a cached synchronous statement.
171 : *
172 : * @param aQuery
173 : * SQL query literal.
174 : * @return The cached statement.
175 : * @note Always null check the result.
176 : * @note Always use a scoper to reset the statement.
177 : */
178 : template<int N>
179 : already_AddRefed<mozIStorageStatement>
180 40672 : GetStatement(const char (&aQuery)[N]) const
181 : {
182 81344 : nsDependentCString query(aQuery, N - 1);
183 40672 : return GetStatement(query);
184 : }
185 :
186 : /**
187 : * Gets a cached synchronous statement.
188 : *
189 : * @param aQuery
190 : * nsCString of SQL query.
191 : * @return The cached statement.
192 : * @note Always null check the result.
193 : * @note Always use a scoper to reset the statement.
194 : */
195 : already_AddRefed<mozIStorageStatement>
196 47603 : GetStatement(const nsACString& aQuery) const
197 : {
198 47603 : if (mShuttingDown) {
199 0 : return nsnull;
200 : }
201 47603 : if (NS_IsMainThread()) {
202 34308 : return mMainThreadStatements.GetCachedStatement(aQuery);
203 : }
204 13295 : return mAsyncThreadStatements.GetCachedStatement(aQuery);
205 : }
206 :
207 : /**
208 : * Gets a cached asynchronous statement.
209 : *
210 : * @param aQuery
211 : * SQL query literal.
212 : * @return The cached statement.
213 : * @note Always null check the result.
214 : * @note AsyncStatements are automatically reset on execution.
215 : */
216 : template<int N>
217 : already_AddRefed<mozIStorageAsyncStatement>
218 10763 : GetAsyncStatement(const char (&aQuery)[N]) const
219 : {
220 21526 : nsDependentCString query(aQuery, N - 1);
221 10763 : return GetAsyncStatement(query);
222 : }
223 :
224 : /**
225 : * Gets a cached asynchronous statement.
226 : *
227 : * @param aQuery
228 : * nsCString of SQL query.
229 : * @return The cached statement.
230 : * @note Always null check the result.
231 : * @note AsyncStatements are automatically reset on execution.
232 : */
233 : already_AddRefed<mozIStorageAsyncStatement>
234 11092 : GetAsyncStatement(const nsACString& aQuery) const
235 : {
236 11092 : if (mShuttingDown) {
237 0 : return nsnull;
238 : }
239 11092 : MOZ_ASSERT(NS_IsMainThread());
240 11092 : return mMainThreadAsyncStatements.GetCachedStatement(aQuery);
241 : }
242 :
243 : protected:
244 : /**
245 : * Initializes the database file. If the database does not exist or is
246 : * corrupt, a new one is created. In case of corruption it also creates a
247 : * backup copy of the database.
248 : *
249 : * @param aStorage
250 : * mozStorage service instance.
251 : * @param aNewDatabaseCreated
252 : * whether a new database file has been created.
253 : */
254 : nsresult InitDatabaseFile(nsCOMPtr<mozIStorageService>& aStorage,
255 : bool* aNewDatabaseCreated);
256 :
257 : /**
258 : * Creates a database backup and replaces the original file with a new
259 : * one.
260 : *
261 : * @param aStorage
262 : * mozStorage service instance.
263 : */
264 : nsresult BackupAndReplaceDatabaseFile(nsCOMPtr<mozIStorageService>& aStorage);
265 :
266 : /**
267 : * Initializes the database. This performs any necessary migrations for the
268 : * database. All migration is done inside a transaction that is rolled back
269 : * if any error occurs.
270 : * @param aDatabaseMigrated
271 : * Whether a schema upgrade happened.
272 : */
273 : nsresult InitSchema(bool* aDatabaseMigrated);
274 :
275 : /**
276 : * Creates bookmark roots in a new DB.
277 : */
278 : nsresult CreateBookmarkRoots();
279 :
280 : /**
281 : * Initializes additionale SQLite functions, defined in SQLFunctions.h
282 : */
283 : nsresult InitFunctions();
284 :
285 : /**
286 : * Initializes triggers defined in nsPlacesTriggers.h
287 : */
288 : nsresult InitTempTriggers();
289 :
290 : /**
291 : * Helpers used by schema upgrades.
292 : */
293 : nsresult MigrateV7Up();
294 : nsresult MigrateV8Up();
295 : nsresult MigrateV9Up();
296 : nsresult MigrateV10Up();
297 : nsresult MigrateV11Up();
298 : nsresult MigrateV13Up();
299 : nsresult MigrateV14Up();
300 : nsresult MigrateV15Up();
301 : nsresult MigrateV16Up();
302 : nsresult MigrateV17Up();
303 : nsresult MigrateV18Up();
304 : nsresult MigrateV19Up();
305 :
306 : nsresult UpdateBookmarkRootTitles();
307 : nsresult CheckAndUpdateGUIDs();
308 :
309 : private:
310 : ~Database();
311 :
312 : /**
313 : * Singleton getter, invoked by class instantiation.
314 : *
315 : * Note: does AddRef.
316 : */
317 : static Database* GetSingleton();
318 :
319 : static Database* gDatabase;
320 :
321 : nsCOMPtr<mozIStorageConnection> mMainConn;
322 :
323 : mutable StatementCache mMainThreadStatements;
324 : mutable AsyncStatementCache mMainThreadAsyncStatements;
325 : mutable StatementCache mAsyncThreadStatements;
326 :
327 : PRInt32 mDBPageSize;
328 : enum JournalMode mCurrentJournalMode;
329 : PRUint16 mDatabaseStatus;
330 : bool mShuttingDown;
331 : };
332 :
333 : } // namespace places
334 : } // namespace mozilla
335 :
336 : #endif // mozilla_places_Database_h_
|