1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Mozilla Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 2008
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Shawn Wilsher <me@shawnwilsher.com> (Original Author)
25 : * David Rajchenbach-Teller <dteller@mozilla.com> (added Telemetry)
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #ifndef mozStorageAsyncStatementExecution_h
42 : #define mozStorageAsyncStatementExecution_h
43 :
44 : #include "nscore.h"
45 : #include "nsTArray.h"
46 : #include "nsAutoPtr.h"
47 : #include "nsThreadUtils.h"
48 : #include "mozilla/Mutex.h"
49 : #include "mozilla/TimeStamp.h"
50 :
51 : #include "SQLiteMutex.h"
52 : #include "mozIStoragePendingStatement.h"
53 : #include "mozIStorageStatementCallback.h"
54 :
55 : struct sqlite3_stmt;
56 : class mozStorageTransaction;
57 :
58 : namespace mozilla {
59 : namespace storage {
60 :
61 : class Connection;
62 : class ResultSet;
63 : class StatementData;
64 :
65 : class AsyncExecuteStatements : public nsIRunnable
66 : , public mozIStoragePendingStatement
67 42833 : {
68 : public:
69 : NS_DECL_ISUPPORTS
70 : NS_DECL_NSIRUNNABLE
71 : NS_DECL_MOZISTORAGEPENDINGSTATEMENT
72 :
73 : /**
74 : * Describes the state of execution.
75 : */
76 : enum ExecutionState {
77 : PENDING = -1,
78 : COMPLETED = mozIStorageStatementCallback::REASON_FINISHED,
79 : CANCELED = mozIStorageStatementCallback::REASON_CANCELED,
80 : ERROR = mozIStorageStatementCallback::REASON_ERROR
81 : };
82 :
83 : typedef nsTArray<StatementData> StatementDataArray;
84 :
85 : /**
86 : * Executes a statement in the background, and passes results back to the
87 : * caller.
88 : *
89 : * @param aStatements
90 : * The statements to execute and possibly bind in the background.
91 : * Ownership is transfered from the caller.
92 : * @param aConnection
93 : * The connection that created the statements to execute.
94 : * @param aCallback
95 : * The callback that is notified of results, completion, and errors.
96 : * @param _stmt
97 : * The handle to control the execution of the statements.
98 : */
99 : static nsresult execute(StatementDataArray &aStatements,
100 : Connection *aConnection,
101 : mozIStorageStatementCallback *aCallback,
102 : mozIStoragePendingStatement **_stmt);
103 :
104 : /**
105 : * Indicates when events on the calling thread should run or not. Certain
106 : * events posted back to the calling thread should call this see if they
107 : * should run or not.
108 : *
109 : * @pre mMutex is not held
110 : *
111 : * @returns true if the event should notify still, false otherwise.
112 : */
113 : bool shouldNotify();
114 :
115 : private:
116 : AsyncExecuteStatements(StatementDataArray &aStatements,
117 : Connection *aConnection,
118 : mozIStorageStatementCallback *aCallback);
119 :
120 : /**
121 : * Binds and then executes a given statement until completion, an error
122 : * occurs, or we are canceled. If aLastStatement is true, we should set
123 : * mState accordingly.
124 : *
125 : * @pre mMutex is not held
126 : *
127 : * @param aData
128 : * The StatementData to bind, execute, and then process.
129 : * @param aLastStatement
130 : * Indicates if this is the last statement or not. If it is, we have
131 : * to set the proper state.
132 : * @returns true if we should continue to process statements, false otherwise.
133 : */
134 : bool bindExecuteAndProcessStatement(StatementData &aData,
135 : bool aLastStatement);
136 :
137 : /**
138 : * Executes a given statement until completion, an error occurs, or we are
139 : * canceled. If aLastStatement is true, we should set mState accordingly.
140 : *
141 : * @pre mMutex is not held
142 : *
143 : * @param aStatement
144 : * The statement to execute and then process.
145 : * @param aLastStatement
146 : * Indicates if this is the last statement or not. If it is, we have
147 : * to set the proper state.
148 : * @returns true if we should continue to process statements, false otherwise.
149 : */
150 : bool executeAndProcessStatement(sqlite3_stmt *aStatement,
151 : bool aLastStatement);
152 :
153 : /**
154 : * Executes a statement to completion, properly handling any error conditions.
155 : *
156 : * @pre mMutex is not held
157 : *
158 : * @param aStatement
159 : * The statement to execute to completion.
160 : * @returns true if results were obtained, false otherwise.
161 : */
162 : bool executeStatement(sqlite3_stmt *aStatement);
163 :
164 : /**
165 : * Builds a result set up with a row from a given statement. If we meet the
166 : * right criteria, go ahead and notify about this results too.
167 : *
168 : * @pre mMutex is not held
169 : *
170 : * @param aStatement
171 : * The statement to get the row data from.
172 : */
173 : nsresult buildAndNotifyResults(sqlite3_stmt *aStatement);
174 :
175 : /**
176 : * Notifies callback about completion, and does any necessary cleanup.
177 : *
178 : * @pre mMutex is not held
179 : */
180 : nsresult notifyComplete();
181 :
182 : /**
183 : * Notifies callback about an error.
184 : *
185 : * @pre mMutex is not held
186 : * @pre mDBMutex is not held
187 : *
188 : * @param aErrorCode
189 : * The error code defined in mozIStorageError for the error.
190 : * @param aMessage
191 : * The error string, if any.
192 : * @param aError
193 : * The error object to notify the caller with.
194 : */
195 : nsresult notifyError(PRInt32 aErrorCode, const char *aMessage);
196 : nsresult notifyError(mozIStorageError *aError);
197 :
198 : /**
199 : * Notifies the callback about a result set.
200 : *
201 : * @pre mMutex is not held
202 : */
203 : nsresult notifyResults();
204 :
205 : /**
206 : * Tests whether the current statements should be wrapped in an explicit
207 : * transaction.
208 : *
209 : * @return true if an explicit transaction is needed, false otherwise.
210 : */
211 : bool statementsNeedTransaction();
212 :
213 : StatementDataArray mStatements;
214 : nsRefPtr<Connection> mConnection;
215 : mozStorageTransaction *mTransactionManager;
216 : mozIStorageStatementCallback *mCallback;
217 : nsCOMPtr<nsIThread> mCallingThread;
218 : nsRefPtr<ResultSet> mResultSet;
219 :
220 : /**
221 : * The maximum amount of time we want to wait between results. Defined by
222 : * MAX_MILLISECONDS_BETWEEN_RESULTS and set at construction.
223 : */
224 : const TimeDuration mMaxWait;
225 :
226 : /**
227 : * The start time since our last set of results.
228 : */
229 : TimeStamp mIntervalStart;
230 :
231 : /**
232 : * Indicates our state of execution.
233 : */
234 : ExecutionState mState;
235 :
236 : /**
237 : * Indicates if we should try to cancel at a cancelation point.
238 : */
239 : bool mCancelRequested;
240 :
241 : /**
242 : * This is the mutex that protects our state from changing between threads.
243 : * This includes the following variables:
244 : * - mCancelRequested is only set on the calling thread while the lock is
245 : * held. It is always read from within the lock on the background thread,
246 : * but not on the calling thread (see shouldNotify for why).
247 : */
248 : Mutex &mMutex;
249 :
250 : /**
251 : * The wrapped SQLite recursive connection mutex. We use it whenever we call
252 : * sqlite3_step and care about having reliable error messages. By taking it
253 : * prior to the call and holding it until the point where we no longer care
254 : * about the error message, the user gets reliable error messages.
255 : */
256 : SQLiteMutex &mDBMutex;
257 :
258 : /**
259 : * The instant at which the request was started.
260 : *
261 : * Used by telemetry.
262 : */
263 : TimeStamp mRequestStartDate;
264 : };
265 :
266 : } // namespace storage
267 : } // namespace mozilla
268 :
269 : #endif // mozStorageAsyncStatementExecution_h
|