• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 #include "modules/webdatabase/SQLTransactionBackend.h"
31 
32 #include "modules/webdatabase/Database.h"
33 #include "modules/webdatabase/DatabaseAuthorizer.h"
34 #include "modules/webdatabase/DatabaseContext.h"
35 #include "modules/webdatabase/DatabaseThread.h"
36 #include "modules/webdatabase/DatabaseTracker.h"
37 #include "modules/webdatabase/SQLError.h"
38 #include "modules/webdatabase/SQLStatementBackend.h"
39 #include "modules/webdatabase/SQLTransaction.h"
40 #include "modules/webdatabase/SQLTransactionClient.h"
41 #include "modules/webdatabase/SQLTransactionCoordinator.h"
42 #include "modules/webdatabase/sqlite/SQLValue.h"
43 #include "modules/webdatabase/sqlite/SQLiteTransaction.h"
44 #include "platform/Logging.h"
45 #include "wtf/StdLibExtras.h"
46 
47 
48 // How does a SQLTransaction work?
49 // ==============================
50 // The SQLTransaction is a state machine that executes a series of states / steps.
51 //
52 // The work of the transaction states are defined in section of 4.3.2 of the
53 // webdatabase spec: http://dev.w3.org/html5/webdatabase/#processing-model
54 //
55 // the State Transition Graph at a glance:
56 // ======================================
57 //
58 //     Backend                          .   Frontend
59 //     (works with SQLiteDatabase)      .   (works with Script)
60 //     ===========================      .   ===================
61 //                                      .
62 //     1. Idle                          .
63 //         v                            .
64 //     2. AcquireLock                   .
65 //         v                            .
66 //     3. OpenTransactionAndPreflight ------------------------------------------.
67 //         |                            .                                       |
68 //         `-------------------------------> 8. DeliverTransactionCallback --.  |
69 //                                      .        |                           v  v
70 //         ,-------------------------------------'   9. DeliverTransactionErrorCallback +
71 //         |                            .                                    ^  ^  ^    |
72 //         v                            .                                    |  |  |    |
73 //     4. RunStatements -----------------------------------------------------'  |  |    |
74 //         |        ^  ^ |  ^ |         .                                       |  |    |
75 //         |--------'  | |  | `------------> 10. DeliverStatementCallback +-----'  |    |
76 //         |           | |  `---------------------------------------------'        |    |
77 //         |           | `-----------------> 11. DeliverQuotaIncreaseCallback +    |    |
78 //         |            `-----------------------------------------------------'    |    |
79 //         v                            .                                          |    |
80 //     5. PostflightAndCommit --+--------------------------------------------------'    |
81 //                              |----------> 12. DeliverSuccessCallback +               |
82 //         ,--------------------'       .                               |               |
83 //         v                            .                               |               |
84 //     6. CleanupAndTerminate <-----------------------------------------'               |
85 //         v           ^                .                                               |
86 //     0. End          |                .                                               |
87 //                     |                .                                               |
88 //                7: CleanupAfterTransactionErrorCallback <----------------------------'
89 //                                      .
90 //
91 // the States and State Transitions:
92 // ================================
93 //     0. SQLTransactionState::End
94 //         - the end state.
95 //
96 //     1. SQLTransactionState::Idle
97 //         - placeholder state while waiting on frontend/backend, etc. See comment on
98 //           "State transitions between SQLTransaction and SQLTransactionBackend"
99 //           below.
100 //
101 //     2. SQLTransactionState::AcquireLock (runs in backend)
102 //         - this is the start state.
103 //         - acquire the "lock".
104 //         - on "lock" acquisition, goto SQLTransactionState::OpenTransactionAndPreflight.
105 //
106 //     3. SQLTransactionState::openTransactionAndPreflight (runs in backend)
107 //         - Sets up an SQLiteTransaction.
108 //         - begin the SQLiteTransaction.
109 //         - call the SQLTransactionWrapper preflight if available.
110 //         - schedule script callback.
111 //         - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
112 //         - goto SQLTransactionState::DeliverTransactionCallback.
113 //
114 //     4. SQLTransactionState::DeliverTransactionCallback (runs in frontend)
115 //         - invoke the script function callback() if available.
116 //         - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
117 //         - goto SQLTransactionState::RunStatements.
118 //
119 //     5. SQLTransactionState::DeliverTransactionErrorCallback (runs in frontend)
120 //         - invoke the script function errorCallback if available.
121 //         - goto SQLTransactionState::CleanupAfterTransactionErrorCallback.
122 //
123 //     6. SQLTransactionState::RunStatements (runs in backend)
124 //         - while there are statements {
125 //             - run a statement.
126 //             - if statementCallback is available, goto SQLTransactionState::DeliverStatementCallback.
127 //             - on error,
128 //               goto SQLTransactionState::DeliverQuotaIncreaseCallback, or
129 //               goto SQLTransactionState::DeliverStatementCallback, or
130 //               goto SQLTransactionState::deliverTransactionErrorCallback.
131 //           }
132 //         - goto SQLTransactionState::PostflightAndCommit.
133 //
134 //     7. SQLTransactionState::DeliverStatementCallback (runs in frontend)
135 //         - invoke script statement callback (assume available).
136 //         - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
137 //         - goto SQLTransactionState::RunStatements.
138 //
139 //     8. SQLTransactionState::DeliverQuotaIncreaseCallback (runs in frontend)
140 //         - give client a chance to increase the quota.
141 //         - goto SQLTransactionState::RunStatements.
142 //
143 //     9. SQLTransactionState::PostflightAndCommit (runs in backend)
144 //         - call the SQLTransactionWrapper postflight if available.
145 //         - commit the SQLiteTansaction.
146 //         - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
147 //         - if successCallback is available, goto SQLTransactionState::DeliverSuccessCallback.
148 //           else goto SQLTransactionState::CleanupAndTerminate.
149 //
150 //     10. SQLTransactionState::DeliverSuccessCallback (runs in frontend)
151 //         - invoke the script function successCallback() if available.
152 //         - goto SQLTransactionState::CleanupAndTerminate.
153 //
154 //     11. SQLTransactionState::CleanupAndTerminate (runs in backend)
155 //         - stop and clear the SQLiteTransaction.
156 //         - release the "lock".
157 //         - goto SQLTransactionState::End.
158 //
159 //     12. SQLTransactionState::CleanupAfterTransactionErrorCallback (runs in backend)
160 //         - rollback the SQLiteTransaction.
161 //         - goto SQLTransactionState::CleanupAndTerminate.
162 //
163 // State transitions between SQLTransaction and SQLTransactionBackend
164 // ==================================================================
165 // As shown above, there are state transitions that crosses the boundary between
166 // the frontend and backend. For example,
167 //
168 //     OpenTransactionAndPreflight (state 3 in the backend)
169 //     transitions to DeliverTransactionCallback (state 8 in the frontend),
170 //     which in turn transitions to RunStatements (state 4 in the backend).
171 //
172 // This cross boundary transition is done by posting transition requests to the
173 // other side and letting the other side's state machine execute the state
174 // transition in the appropriate thread (i.e. the script thread for the frontend,
175 // and the database thread for the backend).
176 //
177 // Logically, the state transitions work as shown in the graph above. But
178 // physically, the transition mechanism uses the Idle state (both in the frontend
179 // and backend) as a waiting state for further activity. For example, taking a
180 // closer look at the 3 state transition example above, what actually happens
181 // is as follows:
182 //
183 //     Step 1:
184 //     ======
185 //     In the frontend thread:
186 //     - waiting quietly is Idle. Not doing any work.
187 //
188 //     In the backend:
189 //     - is in OpenTransactionAndPreflight, and doing its work.
190 //     - when done, it transits to the backend DeliverTransactionCallback.
191 //     - the backend DeliverTransactionCallback sends a request to the frontend
192 //       to transit to DeliverTransactionCallback, and then itself transits to
193 //       Idle.
194 //
195 //     Step 2:
196 //     ======
197 //     In the frontend thread:
198 //     - transits to DeliverTransactionCallback and does its work.
199 //     - when done, it transits to the frontend RunStatements.
200 //     - the frontend RunStatements sends a request to the backend to transit
201 //       to RunStatements, and then itself transits to Idle.
202 //
203 //     In the backend:
204 //     - waiting quietly in Idle.
205 //
206 //     Step 3:
207 //     ======
208 //     In the frontend thread:
209 //     - waiting quietly is Idle. Not doing any work.
210 //
211 //     In the backend:
212 //     - transits to RunStatements, and does its work.
213 //        ...
214 //
215 // So, when the frontend or backend are not active, they will park themselves in
216 // their Idle states. This means their m_nextState is set to Idle, but they never
217 // actually run the corresponding state function. Note: for both the frontend and
218 // backend, the state function for Idle is unreachableState().
219 //
220 // The states that send a request to their peer across the front/back boundary
221 // are implemented with just 2 functions: SQLTransaction::sendToBackendState()
222 // and SQLTransactionBackend::sendToFrontendState(). These state functions do
223 // nothing but sends a request to the other side to transit to the current
224 // state (indicated by m_nextState), and then transits itself to the Idle state
225 // to wait for further action.
226 
227 
228 // The Life-Cycle of a SQLTransaction i.e. Who's keeping the SQLTransaction alive?
229 // ==============================================================================
230 // The RefPtr chain goes something like this:
231 //
232 //     At birth (in Database::runTransaction()):
233 //     ====================================================
234 //     Database                           // Deque<RefPtr<SQLTransactionBackend> > m_transactionQueue points to ...
235 //     --> SQLTransactionBackend          // RefPtr<SQLTransaction> m_frontend points to ...
236 //         --> SQLTransaction             // RefPtr<SQLTransactionBackend> m_backend points to ...
237 //             --> SQLTransactionBackend  // which is a circular reference.
238 //
239 //     Note: there's a circular reference between the SQLTransaction front-end and
240 //     back-end. This circular reference is established in the constructor of the
241 //     SQLTransactionBackend. The circular reference will be broken by calling
242 //     doCleanup() to nullify m_frontend. This is done at the end of the transaction's
243 //     clean up state (i.e. when the transaction should no longer be in use thereafter),
244 //     or if the database was interrupted. See comments on "What happens if a transaction
245 //     is interrupted?" below for details.
246 //
247 //     After scheduling the transaction with the DatabaseThread (Database::scheduleTransaction()):
248 //     ======================================================================================================
249 //     DatabaseThread                         // MessageQueue<DatabaseTask> m_queue points to ...
250 //     --> DatabaseTransactionTask            // RefPtr<SQLTransactionBackend> m_transaction points to ...
251 //         --> SQLTransactionBackend          // RefPtr<SQLTransaction> m_frontend points to ...
252 //             --> SQLTransaction             // RefPtr<SQLTransactionBackend> m_backend points to ...
253 //                 --> SQLTransactionBackend  // which is a circular reference.
254 //
255 //     When executing the transaction (in DatabaseThread::databaseThread()):
256 //     ====================================================================
257 //     OwnPtr<DatabaseTask> task;             // points to ...
258 //     --> DatabaseTransactionTask            // RefPtr<SQLTransactionBackend> m_transaction points to ...
259 //         --> SQLTransactionBackend          // RefPtr<SQLTransaction> m_frontend;
260 //             --> SQLTransaction             // RefPtr<SQLTransactionBackend> m_backend points to ...
261 //                 --> SQLTransactionBackend  // which is a circular reference.
262 //
263 //     At the end of cleanupAndTerminate():
264 //     ===================================
265 //     At the end of the cleanup state, the SQLTransactionBackend::m_frontend is nullified.
266 //     If by then, a JSObject wrapper is referring to the SQLTransaction, then the reference
267 //     chain looks like this:
268 //
269 //     JSObjectWrapper
270 //     --> SQLTransaction             // in RefPtr<SQLTransactionBackend> m_backend points to ...
271 //         --> SQLTransactionBackend  // which no longer points back to its SQLTransaction.
272 //
273 //     When the GC collects the corresponding JSObject, the above chain will be cleaned up
274 //     and deleted.
275 //
276 //     If there is no JSObject wrapper referring to the SQLTransaction when the cleanup
277 //     states nullify SQLTransactionBackend::m_frontend, the SQLTransaction will deleted then.
278 //     However, there will still be a DatabaseTask pointing to the SQLTransactionBackend (see
279 //     the "When executing the transaction" chain above). This will keep the
280 //     SQLTransactionBackend alive until DatabaseThread::databaseThread() releases its
281 //     task OwnPtr.
282 //
283 //     What happens if a transaction is interrupted?
284 //     ============================================
285 //     If the transaction is interrupted half way, it won't get to run to state
286 //     CleanupAndTerminate, and hence, would not have called SQLTransactionBackend's
287 //     doCleanup(). doCleanup() is where we nullify SQLTransactionBackend::m_frontend
288 //     to break the reference cycle between the frontend and backend. Hence, we need
289 //     to cleanup the transaction by other means.
290 //
291 //     Note: calling SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown()
292 //     is effectively the same as calling SQLTransactionBackend::doClean().
293 //
294 //     In terms of who needs to call doCleanup(), there are 5 phases in the
295 //     SQLTransactionBackend life-cycle. These are the phases and how the clean
296 //     up is done:
297 //
298 //     Phase 1. After Birth, before scheduling
299 //
300 //     - To clean up, DatabaseThread::databaseThread() will call
301 //       Database::close() during its shutdown.
302 //     - Database::close() will iterate
303 //       Database::m_transactionQueue and call
304 //       notifyDatabaseThreadIsShuttingDown() on each transaction there.
305 //
306 //     Phase 2. After scheduling, before state AcquireLock
307 //
308 //     - If the interruption occures before the DatabaseTransactionTask is
309 //       scheduled in DatabaseThread::m_queue but hasn't gotten to execute
310 //       (i.e. DatabaseTransactionTask::performTask() has not been called),
311 //       then the DatabaseTransactionTask may get destructed before it ever
312 //       gets to execute.
313 //     - To clean up, the destructor will check if the task's m_wasExecuted is
314 //       set. If not, it will call notifyDatabaseThreadIsShuttingDown() on
315 //       the task's transaction.
316 //
317 //     Phase 3. After state AcquireLock, before "lockAcquired"
318 //
319 //     - In this phase, the transaction would have been added to the
320 //       SQLTransactionCoordinator's CoordinationInfo's pendingTransactions.
321 //     - To clean up, during shutdown, DatabaseThread::databaseThread() calls
322 //       SQLTransactionCoordinator::shutdown(), which calls
323 //       notifyDatabaseThreadIsShuttingDown().
324 //
325 //     Phase 4: After "lockAcquired", before state CleanupAndTerminate
326 //
327 //     - In this phase, the transaction would have been added either to the
328 //       SQLTransactionCoordinator's CoordinationInfo's activeWriteTransaction
329 //       or activeReadTransactions.
330 //     - To clean up, during shutdown, DatabaseThread::databaseThread() calls
331 //       SQLTransactionCoordinator::shutdown(), which calls
332 //       notifyDatabaseThreadIsShuttingDown().
333 //
334 //     Phase 5: After state CleanupAndTerminate
335 //
336 //     - This is how a transaction ends normally.
337 //     - state CleanupAndTerminate calls doCleanup().
338 
339 
340 namespace blink {
341 
create(Database * db,PassRefPtrWillBeRawPtr<SQLTransaction> frontend,PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper,bool readOnly)342 PassRefPtrWillBeRawPtr<SQLTransactionBackend> SQLTransactionBackend::create(Database* db,
343     PassRefPtrWillBeRawPtr<SQLTransaction> frontend,
344     PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper,
345     bool readOnly)
346 {
347     return adoptRefWillBeNoop(new SQLTransactionBackend(db, frontend, wrapper, readOnly));
348 }
349 
SQLTransactionBackend(Database * db,PassRefPtrWillBeRawPtr<SQLTransaction> frontend,PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper,bool readOnly)350 SQLTransactionBackend::SQLTransactionBackend(Database* db,
351     PassRefPtrWillBeRawPtr<SQLTransaction> frontend,
352     PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper,
353     bool readOnly)
354     : m_frontend(frontend)
355     , m_database(db)
356     , m_wrapper(wrapper)
357     , m_hasCallback(m_frontend->hasCallback())
358     , m_hasSuccessCallback(m_frontend->hasSuccessCallback())
359     , m_hasErrorCallback(m_frontend->hasErrorCallback())
360     , m_shouldRetryCurrentStatement(false)
361     , m_modifiedDatabase(false)
362     , m_lockAcquired(false)
363     , m_readOnly(readOnly)
364     , m_hasVersionMismatch(false)
365 {
366     ASSERT(m_database);
367     m_frontend->setBackend(this);
368     m_requestedState = SQLTransactionState::AcquireLock;
369 }
370 
~SQLTransactionBackend()371 SQLTransactionBackend::~SQLTransactionBackend()
372 {
373     ASSERT(!m_sqliteTransaction);
374 }
375 
trace(Visitor * visitor)376 void SQLTransactionBackend::trace(Visitor* visitor)
377 {
378     visitor->trace(m_frontend);
379     visitor->trace(m_currentStatementBackend);
380     visitor->trace(m_database);
381     visitor->trace(m_wrapper);
382     visitor->trace(m_statementQueue);
383 }
384 
doCleanup()385 void SQLTransactionBackend::doCleanup()
386 {
387     if (!m_frontend)
388         return;
389     m_frontend = nullptr; // Break the reference cycle. See comment about the life-cycle above.
390 
391     ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread());
392 
393     MutexLocker locker(m_statementMutex);
394     m_statementQueue.clear();
395 
396     if (m_sqliteTransaction) {
397         // In the event we got here because of an interruption or error (i.e. if
398         // the transaction is in progress), we should roll it back here. Clearing
399         // m_sqliteTransaction invokes SQLiteTransaction's destructor which does
400         // just that. We might as well do this unconditionally and free up its
401         // resources because we're already terminating.
402         m_sqliteTransaction.clear();
403     }
404 
405     // Release the lock on this database
406     if (m_lockAcquired)
407         m_database->transactionCoordinator()->releaseLock(this);
408 
409     // Do some aggresive clean up here except for m_database.
410     //
411     // We can't clear m_database here because the frontend may asynchronously
412     // invoke SQLTransactionBackend::requestTransitToState(), and that function
413     // uses m_database to schedule a state transition. This may occur because
414     // the frontend (being in another thread) may already be on the way to
415     // requesting our next state before it detects an interruption.
416     //
417     // There is no harm in letting it finish making the request. It'll set
418     // m_requestedState, but we won't execute a transition to that state because
419     // we've already shut down the transaction.
420     //
421     // We also can't clear m_currentStatementBackend and m_transactionError.
422     // m_currentStatementBackend may be accessed asynchronously by the
423     // frontend's deliverStatementCallback() state. Similarly,
424     // m_transactionError may be accessed by deliverTransactionErrorCallback().
425     // This occurs if requests for transition to those states have already been
426     // registered with the frontend just prior to a clean up request arriving.
427     //
428     // So instead, let our destructor handle their clean up since this
429     // SQLTransactionBackend is guaranteed to not destruct until the frontend
430     // is also destructing.
431 
432     m_wrapper = nullptr;
433 }
434 
currentStatement()435 SQLStatement* SQLTransactionBackend::currentStatement()
436 {
437     return m_currentStatementBackend->frontend();
438 }
439 
transactionError()440 SQLErrorData* SQLTransactionBackend::transactionError()
441 {
442     return m_transactionError.get();
443 }
444 
setShouldRetryCurrentStatement(bool shouldRetry)445 void SQLTransactionBackend::setShouldRetryCurrentStatement(bool shouldRetry)
446 {
447     ASSERT(!m_shouldRetryCurrentStatement);
448     m_shouldRetryCurrentStatement = shouldRetry;
449 }
450 
stateFunctionFor(SQLTransactionState state)451 SQLTransactionBackend::StateFunction SQLTransactionBackend::stateFunctionFor(SQLTransactionState state)
452 {
453     static const StateFunction stateFunctions[] = {
454         &SQLTransactionBackend::unreachableState,            // 0. end
455         &SQLTransactionBackend::unreachableState,            // 1. idle
456         &SQLTransactionBackend::acquireLock,                 // 2.
457         &SQLTransactionBackend::openTransactionAndPreflight, // 3.
458         &SQLTransactionBackend::runStatements,               // 4.
459         &SQLTransactionBackend::postflightAndCommit,         // 5.
460         &SQLTransactionBackend::cleanupAndTerminate,         // 6.
461         &SQLTransactionBackend::cleanupAfterTransactionErrorCallback, // 7.
462         &SQLTransactionBackend::sendToFrontendState,         // 8. deliverTransactionCallback
463         &SQLTransactionBackend::sendToFrontendState,         // 9. deliverTransactionErrorCallback
464         &SQLTransactionBackend::sendToFrontendState,         // 10. deliverStatementCallback
465         &SQLTransactionBackend::sendToFrontendState,         // 11. deliverQuotaIncreaseCallback
466         &SQLTransactionBackend::sendToFrontendState          // 12. deliverSuccessCallback
467     };
468 
469     ASSERT(WTF_ARRAY_LENGTH(stateFunctions) == static_cast<int>(SQLTransactionState::NumberOfStates));
470     ASSERT(state < SQLTransactionState::NumberOfStates);
471 
472     return stateFunctions[static_cast<int>(state)];
473 }
474 
enqueueStatementBackend(PassRefPtrWillBeRawPtr<SQLStatementBackend> statementBackend)475 void SQLTransactionBackend::enqueueStatementBackend(PassRefPtrWillBeRawPtr<SQLStatementBackend> statementBackend)
476 {
477     MutexLocker locker(m_statementMutex);
478     m_statementQueue.append(statementBackend);
479 }
480 
computeNextStateAndCleanupIfNeeded()481 void SQLTransactionBackend::computeNextStateAndCleanupIfNeeded()
482 {
483     // Only honor the requested state transition if we're not supposed to be
484     // cleaning up and shutting down:
485     if (m_database->opened()) {
486         setStateToRequestedState();
487         ASSERT(m_nextState == SQLTransactionState::AcquireLock
488             || m_nextState == SQLTransactionState::OpenTransactionAndPreflight
489             || m_nextState == SQLTransactionState::RunStatements
490             || m_nextState == SQLTransactionState::PostflightAndCommit
491             || m_nextState == SQLTransactionState::CleanupAndTerminate
492             || m_nextState == SQLTransactionState::CleanupAfterTransactionErrorCallback);
493 
494         WTF_LOG(StorageAPI, "State %s\n", nameForSQLTransactionState(m_nextState));
495         return;
496     }
497 
498     // If we get here, then we should be shutting down. Do clean up if needed:
499     if (m_nextState == SQLTransactionState::End)
500         return;
501     m_nextState = SQLTransactionState::End;
502 
503     // If the database was stopped, don't do anything and cancel queued work
504     WTF_LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction");
505 
506     // The current SQLite transaction should be stopped, as well
507     if (m_sqliteTransaction) {
508         m_sqliteTransaction->stop();
509         m_sqliteTransaction.clear();
510     }
511 
512     // Terminate the frontend state machine. This also gets the frontend to
513     // call computeNextStateAndCleanupIfNeeded() and clear its wrappers
514     // if needed.
515     m_frontend->requestTransitToState(SQLTransactionState::End);
516 
517     // Redirect to the end state to abort, clean up, and end the transaction.
518     doCleanup();
519 }
520 
performNextStep()521 void SQLTransactionBackend::performNextStep()
522 {
523     computeNextStateAndCleanupIfNeeded();
524     runStateMachine();
525 }
526 
executeSQL(PassOwnPtrWillBeRawPtr<SQLStatement> statement,const String & sqlStatement,const Vector<SQLValue> & arguments,int permissions)527 void SQLTransactionBackend::executeSQL(PassOwnPtrWillBeRawPtr<SQLStatement> statement,
528     const String& sqlStatement, const Vector<SQLValue>& arguments, int permissions)
529 {
530     enqueueStatementBackend(SQLStatementBackend::create(statement, sqlStatement, arguments, permissions));
531 }
532 
notifyDatabaseThreadIsShuttingDown()533 void SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown()
534 {
535     ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread());
536 
537     // If the transaction is in progress, we should roll it back here, since this
538     // is our last opportunity to do something related to this transaction on the
539     // DB thread. Amongst other work, doCleanup() will clear m_sqliteTransaction
540     // which invokes SQLiteTransaction's destructor, which will do the roll back
541     // if necessary.
542     doCleanup();
543 }
544 
acquireLock()545 SQLTransactionState SQLTransactionBackend::acquireLock()
546 {
547     m_database->transactionCoordinator()->acquireLock(this);
548     return SQLTransactionState::Idle;
549 }
550 
lockAcquired()551 void SQLTransactionBackend::lockAcquired()
552 {
553     m_lockAcquired = true;
554     requestTransitToState(SQLTransactionState::OpenTransactionAndPreflight);
555 }
556 
openTransactionAndPreflight()557 SQLTransactionState SQLTransactionBackend::openTransactionAndPreflight()
558 {
559     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
560     ASSERT(m_lockAcquired);
561 
562     WTF_LOG(StorageAPI, "Opening and preflighting transaction %p", this);
563 
564     // Set the maximum usage for this transaction if this transactions is not read-only
565     if (!m_readOnly)
566         m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
567 
568     ASSERT(!m_sqliteTransaction);
569     m_sqliteTransaction = adoptPtr(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly));
570 
571     m_database->resetDeletes();
572     m_database->disableAuthorizer();
573     m_sqliteTransaction->begin();
574     m_database->enableAuthorizer();
575 
576     // Spec 4.3.2.1+2: Open a transaction to the database, jumping to the error callback if that fails
577     if (!m_sqliteTransaction->inProgress()) {
578         ASSERT(!m_database->sqliteDatabase().transactionInProgress());
579         m_database->reportStartTransactionResult(2, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
580         m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to begin transaction",
581             m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
582         m_sqliteTransaction.clear();
583         return nextStateForTransactionError();
584     }
585 
586     // Note: We intentionally retrieve the actual version even with an empty expected version.
587     // In multi-process browsers, we take this opportinutiy to update the cached value for
588     // the actual version. In single-process browsers, this is just a map lookup.
589     String actualVersion;
590     if (!m_database->getActualVersionForTransaction(actualVersion)) {
591         m_database->reportStartTransactionResult(3, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
592         m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to read version",
593             m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
594         m_database->disableAuthorizer();
595         m_sqliteTransaction.clear();
596         m_database->enableAuthorizer();
597         return nextStateForTransactionError();
598     }
599     m_hasVersionMismatch = !m_database->expectedVersion().isEmpty() && (m_database->expectedVersion() != actualVersion);
600 
601     // Spec 4.3.2.3: Perform preflight steps, jumping to the error callback if they fail
602     if (m_wrapper && !m_wrapper->performPreflight(this)) {
603         m_database->disableAuthorizer();
604         m_sqliteTransaction.clear();
605         m_database->enableAuthorizer();
606         if (m_wrapper->sqlError()) {
607             m_transactionError = SQLErrorData::create(*m_wrapper->sqlError());
608         } else {
609             m_database->reportStartTransactionResult(4, SQLError::UNKNOWN_ERR, 0);
610             m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight");
611         }
612         return nextStateForTransactionError();
613     }
614 
615     // Spec 4.3.2.4: Invoke the transaction callback with the new SQLTransaction object
616     if (m_hasCallback)
617         return SQLTransactionState::DeliverTransactionCallback;
618 
619     // If we have no callback to make, skip pass to the state after:
620     return SQLTransactionState::RunStatements;
621 }
622 
runStatements()623 SQLTransactionState SQLTransactionBackend::runStatements()
624 {
625     ASSERT(m_lockAcquired);
626     SQLTransactionState nextState;
627 
628     // If there is a series of statements queued up that are all successful and have no associated
629     // SQLStatementCallback objects, then we can burn through the queue
630     do {
631         if (m_shouldRetryCurrentStatement && !m_sqliteTransaction->wasRolledBackBySqlite()) {
632             m_shouldRetryCurrentStatement = false;
633             // FIXME - Another place that needs fixing up after <rdar://problem/5628468> is addressed.
634             // See ::openTransactionAndPreflight() for discussion
635 
636             // Reset the maximum size here, as it was increased to allow us to retry this statement.
637             // m_shouldRetryCurrentStatement is set to true only when a statement exceeds
638             // the quota, which can happen only in a read-write transaction. Therefore, there
639             // is no need to check here if the transaction is read-write.
640             m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
641         } else {
642             // If the current statement has already been run, failed due to quota constraints, and we're not retrying it,
643             // that means it ended in an error. Handle it now
644             if (m_currentStatementBackend && m_currentStatementBackend->lastExecutionFailedDueToQuota()) {
645                 return nextStateForCurrentStatementError();
646             }
647 
648             // Otherwise, advance to the next statement
649             getNextStatement();
650         }
651         nextState = runCurrentStatementAndGetNextState();
652     } while (nextState == SQLTransactionState::RunStatements);
653 
654     return nextState;
655 }
656 
getNextStatement()657 void SQLTransactionBackend::getNextStatement()
658 {
659     m_currentStatementBackend = nullptr;
660 
661     MutexLocker locker(m_statementMutex);
662     if (!m_statementQueue.isEmpty())
663         m_currentStatementBackend = m_statementQueue.takeFirst();
664 }
665 
runCurrentStatementAndGetNextState()666 SQLTransactionState SQLTransactionBackend::runCurrentStatementAndGetNextState()
667 {
668     if (!m_currentStatementBackend) {
669         // No more statements to run. So move on to the next state.
670         return SQLTransactionState::PostflightAndCommit;
671     }
672 
673     m_database->resetAuthorizer();
674 
675     if (m_hasVersionMismatch)
676         m_currentStatementBackend->setVersionMismatchedError(m_database.get());
677 
678     if (m_currentStatementBackend->execute(m_database.get())) {
679         if (m_database->lastActionChangedDatabase()) {
680             // Flag this transaction as having changed the database for later delegate notification
681             m_modifiedDatabase = true;
682         }
683 
684         if (m_currentStatementBackend->hasStatementCallback()) {
685             return SQLTransactionState::DeliverStatementCallback;
686         }
687 
688         // If we get here, then the statement doesn't have a callback to invoke.
689         // We can move on to the next statement. Hence, stay in this state.
690         return SQLTransactionState::RunStatements;
691     }
692 
693     if (m_currentStatementBackend->lastExecutionFailedDueToQuota()) {
694         return SQLTransactionState::DeliverQuotaIncreaseCallback;
695     }
696 
697     return nextStateForCurrentStatementError();
698 }
699 
nextStateForCurrentStatementError()700 SQLTransactionState SQLTransactionBackend::nextStateForCurrentStatementError()
701 {
702     // Spec 4.3.2.6.6: error - Call the statement's error callback, but if there was no error callback,
703     // or the transaction was rolled back, jump to the transaction error callback
704     if (m_currentStatementBackend->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite())
705         return SQLTransactionState::DeliverStatementCallback;
706 
707     if (m_currentStatementBackend->sqlError()) {
708         m_transactionError = SQLErrorData::create(*m_currentStatementBackend->sqlError());
709     } else {
710         m_database->reportCommitTransactionResult(1, SQLError::DATABASE_ERR, 0);
711         m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "the statement failed to execute");
712     }
713     return nextStateForTransactionError();
714 }
715 
postflightAndCommit()716 SQLTransactionState SQLTransactionBackend::postflightAndCommit()
717 {
718     ASSERT(m_lockAcquired);
719 
720     // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail.
721     if (m_wrapper && !m_wrapper->performPostflight(this)) {
722         if (m_wrapper->sqlError()) {
723             m_transactionError = SQLErrorData::create(*m_wrapper->sqlError());
724         } else {
725             m_database->reportCommitTransactionResult(3, SQLError::UNKNOWN_ERR, 0);
726             m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight");
727         }
728         return nextStateForTransactionError();
729     }
730 
731     // Spec 4.3.2.7: Commit the transaction, jumping to the error callback if that fails.
732     ASSERT(m_sqliteTransaction);
733 
734     m_database->disableAuthorizer();
735     m_sqliteTransaction->commit();
736     m_database->enableAuthorizer();
737 
738     // If the commit failed, the transaction will still be marked as "in progress"
739     if (m_sqliteTransaction->inProgress()) {
740         if (m_wrapper)
741             m_wrapper->handleCommitFailedAfterPostflight(this);
742         m_database->reportCommitTransactionResult(4, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
743         m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to commit transaction",
744             m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
745         return nextStateForTransactionError();
746     }
747 
748     m_database->reportCommitTransactionResult(0, -1, 0); // OK
749 
750     // Vacuum the database if anything was deleted.
751     if (m_database->hadDeletes())
752         m_database->incrementalVacuumIfNeeded();
753 
754     // The commit was successful. If the transaction modified this database, notify the delegates.
755     if (m_modifiedDatabase)
756         m_database->transactionClient()->didCommitWriteTransaction(database());
757 
758     // Spec 4.3.2.8: Deliver success callback, if there is one.
759     return SQLTransactionState::DeliverSuccessCallback;
760 }
761 
cleanupAndTerminate()762 SQLTransactionState SQLTransactionBackend::cleanupAndTerminate()
763 {
764     ASSERT(m_lockAcquired);
765 
766     // Spec 4.3.2.9: End transaction steps. There is no next step.
767     WTF_LOG(StorageAPI, "Transaction %p is complete\n", this);
768     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
769 
770     // Phase 5 cleanup. See comment on the SQLTransaction life-cycle above.
771     doCleanup();
772     m_database->inProgressTransactionCompleted();
773     return SQLTransactionState::End;
774 }
775 
nextStateForTransactionError()776 SQLTransactionState SQLTransactionBackend::nextStateForTransactionError()
777 {
778     ASSERT(m_transactionError);
779     if (m_hasErrorCallback)
780         return SQLTransactionState::DeliverTransactionErrorCallback;
781 
782     // No error callback, so fast-forward to the next state and rollback the
783     // transaction.
784     return SQLTransactionState::CleanupAfterTransactionErrorCallback;
785 }
786 
cleanupAfterTransactionErrorCallback()787 SQLTransactionState SQLTransactionBackend::cleanupAfterTransactionErrorCallback()
788 {
789     ASSERT(m_lockAcquired);
790 
791     WTF_LOG(StorageAPI, "Transaction %p is complete with an error\n", this);
792     m_database->disableAuthorizer();
793     if (m_sqliteTransaction) {
794         // Spec 4.3.2.10: Rollback the transaction.
795         m_sqliteTransaction->rollback();
796 
797         ASSERT(!m_database->sqliteDatabase().transactionInProgress());
798         m_sqliteTransaction.clear();
799     }
800     m_database->enableAuthorizer();
801 
802     ASSERT(!m_database->sqliteDatabase().transactionInProgress());
803 
804     return SQLTransactionState::CleanupAndTerminate;
805 }
806 
807 // requestTransitToState() can be called from the frontend. Hence, it should
808 // NOT be modifying SQLTransactionBackend in general. The only safe field to
809 // modify is m_requestedState which is meant for this purpose.
requestTransitToState(SQLTransactionState nextState)810 void SQLTransactionBackend::requestTransitToState(SQLTransactionState nextState)
811 {
812     WTF_LOG(StorageAPI, "Scheduling %s for transaction %p\n", nameForSQLTransactionState(nextState), this);
813     m_requestedState = nextState;
814     ASSERT(m_requestedState != SQLTransactionState::End);
815     m_database->scheduleTransactionStep(this);
816 }
817 
818 // This state function is used as a stub function to plug unimplemented states
819 // in the state dispatch table. They are unimplemented because they should
820 // never be reached in the course of correct execution.
unreachableState()821 SQLTransactionState SQLTransactionBackend::unreachableState()
822 {
823     ASSERT_NOT_REACHED();
824     return SQLTransactionState::End;
825 }
826 
sendToFrontendState()827 SQLTransactionState SQLTransactionBackend::sendToFrontendState()
828 {
829     ASSERT(m_nextState != SQLTransactionState::Idle);
830     m_frontend->requestTransitToState(m_nextState);
831     return SQLTransactionState::Idle;
832 }
833 
834 } // namespace blink
835