2 * Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "modules/webdatabase/SQLTransactionBackend.h"
32 #include "platform/Logging.h"
33 #include "modules/webdatabase/sqlite/SQLValue.h"
34 #include "modules/webdatabase/sqlite/SQLiteTransaction.h"
35 #include "modules/webdatabase/AbstractSQLTransaction.h"
36 #include "modules/webdatabase/Database.h" // FIXME: Should only be used in the frontend.
37 #include "modules/webdatabase/DatabaseAuthorizer.h"
38 #include "modules/webdatabase/DatabaseBackend.h"
39 #include "modules/webdatabase/DatabaseContext.h"
40 #include "modules/webdatabase/DatabaseThread.h"
41 #include "modules/webdatabase/DatabaseTracker.h"
42 #include "modules/webdatabase/SQLError.h"
43 #include "modules/webdatabase/SQLStatementBackend.h"
44 #include "modules/webdatabase/SQLTransactionClient.h"
45 #include "modules/webdatabase/SQLTransactionCoordinator.h"
46 #include "wtf/StdLibExtras.h"
49 // How does a SQLTransaction work?
50 // ==============================
51 // The SQLTransaction is a state machine that executes a series of states / steps.
53 // The work of the transaction states are defined in section of 4.3.2 of the
54 // webdatabase spec: http://dev.w3.org/html5/webdatabase/#processing-model
56 // the State Transition Graph at a glance:
57 // ======================================
60 // (works with SQLiteDatabase) . (works with Script)
61 // =========================== . ===================
67 // 3. OpenTransactionAndPreflight ------------------------------------------.
69 // `-------------------------------> 8. DeliverTransactionCallback --. |
71 // ,-------------------------------------' 9. DeliverTransactionErrorCallback +
74 // 4. RunStatements -----------------------------------------------------' | | |
75 // | ^ ^ | ^ | . | | |
76 // |--------' | | | `------------> 10. DeliverStatementCallback +-----' | |
77 // | | | `---------------------------------------------' | |
78 // | | `-----------------> 11. DeliverQuotaIncreaseCallback + | |
79 // | `-----------------------------------------------------' | |
81 // 5. PostflightAndCommit --+--------------------------------------------------' |
82 // |----------> 12. DeliverSuccessCallback + |
83 // ,--------------------' . | |
85 // 6. CleanupAndTerminate <-----------------------------------------' |
89 // 7: CleanupAfterTransactionErrorCallback <----------------------------'
92 // the States and State Transitions:
93 // ================================
94 // 0. SQLTransactionState::End
97 // 1. SQLTransactionState::Idle
98 // - placeholder state while waiting on frontend/backend, etc. See comment on
99 // "State transitions between SQLTransaction and SQLTransactionBackend"
102 // 2. SQLTransactionState::AcquireLock (runs in backend)
103 // - this is the start state.
104 // - acquire the "lock".
105 // - on "lock" acquisition, goto SQLTransactionState::OpenTransactionAndPreflight.
107 // 3. SQLTransactionState::openTransactionAndPreflight (runs in backend)
108 // - Sets up an SQLiteTransaction.
109 // - begin the SQLiteTransaction.
110 // - call the SQLTransactionWrapper preflight if available.
111 // - schedule script callback.
112 // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
113 // - goto SQLTransactionState::DeliverTransactionCallback.
115 // 4. SQLTransactionState::DeliverTransactionCallback (runs in frontend)
116 // - invoke the script function callback() if available.
117 // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
118 // - goto SQLTransactionState::RunStatements.
120 // 5. SQLTransactionState::DeliverTransactionErrorCallback (runs in frontend)
121 // - invoke the script function errorCallback if available.
122 // - goto SQLTransactionState::CleanupAfterTransactionErrorCallback.
124 // 6. SQLTransactionState::RunStatements (runs in backend)
125 // - while there are statements {
126 // - run a statement.
127 // - if statementCallback is available, goto SQLTransactionState::DeliverStatementCallback.
129 // goto SQLTransactionState::DeliverQuotaIncreaseCallback, or
130 // goto SQLTransactionState::DeliverStatementCallback, or
131 // goto SQLTransactionState::deliverTransactionErrorCallback.
133 // - goto SQLTransactionState::PostflightAndCommit.
135 // 7. SQLTransactionState::DeliverStatementCallback (runs in frontend)
136 // - invoke script statement callback (assume available).
137 // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
138 // - goto SQLTransactionState::RunStatements.
140 // 8. SQLTransactionState::DeliverQuotaIncreaseCallback (runs in frontend)
141 // - give client a chance to increase the quota.
142 // - goto SQLTransactionState::RunStatements.
144 // 9. SQLTransactionState::PostflightAndCommit (runs in backend)
145 // - call the SQLTransactionWrapper postflight if available.
146 // - commit the SQLiteTansaction.
147 // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback.
148 // - if successCallback is available, goto SQLTransactionState::DeliverSuccessCallback.
149 // else goto SQLTransactionState::CleanupAndTerminate.
151 // 10. SQLTransactionState::DeliverSuccessCallback (runs in frontend)
152 // - invoke the script function successCallback() if available.
153 // - goto SQLTransactionState::CleanupAndTerminate.
155 // 11. SQLTransactionState::CleanupAndTerminate (runs in backend)
156 // - stop and clear the SQLiteTransaction.
157 // - release the "lock".
158 // - goto SQLTransactionState::End.
160 // 12. SQLTransactionState::CleanupAfterTransactionErrorCallback (runs in backend)
161 // - rollback the SQLiteTransaction.
162 // - goto SQLTransactionState::CleanupAndTerminate.
164 // State transitions between SQLTransaction and SQLTransactionBackend
165 // ==================================================================
166 // As shown above, there are state transitions that crosses the boundary between
167 // the frontend and backend. For example,
169 // OpenTransactionAndPreflight (state 3 in the backend)
170 // transitions to DeliverTransactionCallback (state 8 in the frontend),
171 // which in turn transitions to RunStatements (state 4 in the backend).
173 // This cross boundary transition is done by posting transition requests to the
174 // other side and letting the other side's state machine execute the state
175 // transition in the appropriate thread (i.e. the script thread for the frontend,
176 // and the database thread for the backend).
178 // Logically, the state transitions work as shown in the graph above. But
179 // physically, the transition mechanism uses the Idle state (both in the frontend
180 // and backend) as a waiting state for further activity. For example, taking a
181 // closer look at the 3 state transition example above, what actually happens
186 // In the frontend thread:
187 // - waiting quietly is Idle. Not doing any work.
190 // - is in OpenTransactionAndPreflight, and doing its work.
191 // - when done, it transits to the backend DeliverTransactionCallback.
192 // - the backend DeliverTransactionCallback sends a request to the frontend
193 // to transit to DeliverTransactionCallback, and then itself transits to
198 // In the frontend thread:
199 // - transits to DeliverTransactionCallback and does its work.
200 // - when done, it transits to the frontend RunStatements.
201 // - the frontend RunStatements sends a request to the backend to transit
202 // to RunStatements, and then itself transits to Idle.
205 // - waiting quietly in Idle.
209 // In the frontend thread:
210 // - waiting quietly is Idle. Not doing any work.
213 // - transits to RunStatements, and does its work.
216 // So, when the frontend or backend are not active, they will park themselves in
217 // their Idle states. This means their m_nextState is set to Idle, but they never
218 // actually run the corresponding state function. Note: for both the frontend and
219 // backend, the state function for Idle is unreachableState().
221 // The states that send a request to their peer across the front/back boundary
222 // are implemented with just 2 functions: SQLTransaction::sendToBackendState()
223 // and SQLTransactionBackend::sendToFrontendState(). These state functions do
224 // nothing but sends a request to the other side to transit to the current
225 // state (indicated by m_nextState), and then transits itself to the Idle state
226 // to wait for further action.
229 // The Life-Cycle of a SQLTransaction i.e. Who's keeping the SQLTransaction alive?
230 // ==============================================================================
231 // The RefPtr chain goes something like this:
233 // At birth (in DatabaseBackend::runTransaction()):
234 // ====================================================
235 // DatabaseBackend // Deque<RefPtr<SQLTransactionBackend> > m_transactionQueue points to ...
236 // --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend points to ...
237 // --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ...
238 // --> SQLTransactionBackend // which is a circular reference.
240 // Note: there's a circular reference between the SQLTransaction front-end and
241 // back-end. This circular reference is established in the constructor of the
242 // SQLTransactionBackend. The circular reference will be broken by calling
243 // doCleanup() to nullify m_frontend. This is done at the end of the transaction's
244 // clean up state (i.e. when the transaction should no longer be in use thereafter),
245 // or if the database was interrupted. See comments on "What happens if a transaction
246 // is interrupted?" below for details.
248 // After scheduling the transaction with the DatabaseThread (DatabaseBackend::scheduleTransaction()):
249 // ======================================================================================================
250 // DatabaseThread // MessageQueue<DatabaseTask> m_queue points to ...
251 // --> DatabaseTransactionTask // RefPtr<SQLTransactionBackend> m_transaction points to ...
252 // --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend points to ...
253 // --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ...
254 // --> SQLTransactionBackend // which is a circular reference.
256 // When executing the transaction (in DatabaseThread::databaseThread()):
257 // ====================================================================
258 // OwnPtr<DatabaseTask> task; // points to ...
259 // --> DatabaseTransactionTask // RefPtr<SQLTransactionBackend> m_transaction points to ...
260 // --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend;
261 // --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ...
262 // --> SQLTransactionBackend // which is a circular reference.
264 // At the end of cleanupAndTerminate():
265 // ===================================
266 // At the end of the cleanup state, the SQLTransactionBackend::m_frontend is nullified.
267 // If by then, a JSObject wrapper is referring to the SQLTransaction, then the reference
268 // chain looks like this:
271 // --> SQLTransaction // in RefPtr<SQLTransactionBackend> m_backend points to ...
272 // --> SQLTransactionBackend // which no longer points back to its SQLTransaction.
274 // When the GC collects the corresponding JSObject, the above chain will be cleaned up
277 // If there is no JSObject wrapper referring to the SQLTransaction when the cleanup
278 // states nullify SQLTransactionBackend::m_frontend, the SQLTransaction will deleted then.
279 // However, there will still be a DatabaseTask pointing to the SQLTransactionBackend (see
280 // the "When executing the transaction" chain above). This will keep the
281 // SQLTransactionBackend alive until DatabaseThread::databaseThread() releases its
284 // What happens if a transaction is interrupted?
285 // ============================================
286 // If the transaction is interrupted half way, it won't get to run to state
287 // CleanupAndTerminate, and hence, would not have called SQLTransactionBackend's
288 // doCleanup(). doCleanup() is where we nullify SQLTransactionBackend::m_frontend
289 // to break the reference cycle between the frontend and backend. Hence, we need
290 // to cleanup the transaction by other means.
292 // Note: calling SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown()
293 // is effectively the same as calling SQLTransactionBackend::doClean().
295 // In terms of who needs to call doCleanup(), there are 5 phases in the
296 // SQLTransactionBackend life-cycle. These are the phases and how the clean
299 // Phase 1. After Birth, before scheduling
301 // - To clean up, DatabaseThread::databaseThread() will call
302 // DatabaseBackend::close() during its shutdown.
303 // - DatabaseBackend::close() will iterate
304 // DatabaseBackend::m_transactionQueue and call
305 // notifyDatabaseThreadIsShuttingDown() on each transaction there.
307 // Phase 2. After scheduling, before state AcquireLock
309 // - If the interruption occures before the DatabaseTransactionTask is
310 // scheduled in DatabaseThread::m_queue but hasn't gotten to execute
311 // (i.e. DatabaseTransactionTask::performTask() has not been called),
312 // then the DatabaseTransactionTask may get destructed before it ever
314 // - To clean up, the destructor will check if the task's m_wasExecuted is
315 // set. If not, it will call notifyDatabaseThreadIsShuttingDown() on
316 // the task's transaction.
318 // Phase 3. After state AcquireLock, before "lockAcquired"
320 // - In this phase, the transaction would have been added to the
321 // SQLTransactionCoordinator's CoordinationInfo's pendingTransactions.
322 // - To clean up, during shutdown, DatabaseThread::databaseThread() calls
323 // SQLTransactionCoordinator::shutdown(), which calls
324 // notifyDatabaseThreadIsShuttingDown().
326 // Phase 4: After "lockAcquired", before state CleanupAndTerminate
328 // - In this phase, the transaction would have been added either to the
329 // SQLTransactionCoordinator's CoordinationInfo's activeWriteTransaction
330 // or activeReadTransactions.
331 // - To clean up, during shutdown, DatabaseThread::databaseThread() calls
332 // SQLTransactionCoordinator::shutdown(), which calls
333 // notifyDatabaseThreadIsShuttingDown().
335 // Phase 5: After state CleanupAndTerminate
337 // - This is how a transaction ends normally.
338 // - state CleanupAndTerminate calls doCleanup().
343 PassRefPtrWillBeRawPtr<SQLTransactionBackend> SQLTransactionBackend::create(DatabaseBackend* db,
344 PassRefPtrWillBeRawPtr<AbstractSQLTransaction> frontend,
345 PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper,
348 return adoptRefWillBeNoop(new SQLTransactionBackend(db, frontend, wrapper, readOnly));
351 SQLTransactionBackend::SQLTransactionBackend(DatabaseBackend* db,
352 PassRefPtrWillBeRawPtr<AbstractSQLTransaction> frontend,
353 PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper,
355 : m_frontend(frontend)
358 , m_hasCallback(m_frontend->hasCallback())
359 , m_hasSuccessCallback(m_frontend->hasSuccessCallback())
360 , m_hasErrorCallback(m_frontend->hasErrorCallback())
361 , m_shouldRetryCurrentStatement(false)
362 , m_modifiedDatabase(false)
363 , m_lockAcquired(false)
364 , m_readOnly(readOnly)
365 , m_hasVersionMismatch(false)
368 m_frontend->setBackend(this);
369 m_requestedState = SQLTransactionState::AcquireLock;
372 SQLTransactionBackend::~SQLTransactionBackend()
374 ASSERT(!m_sqliteTransaction);
377 void SQLTransactionBackend::trace(Visitor* visitor)
379 visitor->trace(m_frontend);
380 visitor->trace(m_currentStatementBackend);
381 visitor->trace(m_database);
382 visitor->trace(m_wrapper);
383 visitor->trace(m_statementQueue);
384 AbstractSQLTransactionBackend::trace(visitor);
387 void SQLTransactionBackend::doCleanup()
391 m_frontend = nullptr; // Break the reference cycle. See comment about the life-cycle above.
393 ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread());
395 MutexLocker locker(m_statementMutex);
396 m_statementQueue.clear();
398 if (m_sqliteTransaction) {
399 // In the event we got here because of an interruption or error (i.e. if
400 // the transaction is in progress), we should roll it back here. Clearing
401 // m_sqliteTransaction invokes SQLiteTransaction's destructor which does
402 // just that. We might as well do this unconditionally and free up its
403 // resources because we're already terminating.
404 m_sqliteTransaction.clear();
407 // Release the lock on this database
409 m_database->transactionCoordinator()->releaseLock(this);
411 // Do some aggresive clean up here except for m_database.
413 // We can't clear m_database here because the frontend may asynchronously
414 // invoke SQLTransactionBackend::requestTransitToState(), and that function
415 // uses m_database to schedule a state transition. This may occur because
416 // the frontend (being in another thread) may already be on the way to
417 // requesting our next state before it detects an interruption.
419 // There is no harm in letting it finish making the request. It'll set
420 // m_requestedState, but we won't execute a transition to that state because
421 // we've already shut down the transaction.
423 // We also can't clear m_currentStatementBackend and m_transactionError.
424 // m_currentStatementBackend may be accessed asynchronously by the
425 // frontend's deliverStatementCallback() state. Similarly,
426 // m_transactionError may be accessed by deliverTransactionErrorCallback().
427 // This occurs if requests for transition to those states have already been
428 // registered with the frontend just prior to a clean up request arriving.
430 // So instead, let our destructor handle their clean up since this
431 // SQLTransactionBackend is guaranteed to not destruct until the frontend
432 // is also destructing.
437 AbstractSQLStatement* SQLTransactionBackend::currentStatement()
439 return m_currentStatementBackend->frontend();
442 SQLErrorData* SQLTransactionBackend::transactionError()
444 return m_transactionError.get();
447 void SQLTransactionBackend::setShouldRetryCurrentStatement(bool shouldRetry)
449 ASSERT(!m_shouldRetryCurrentStatement);
450 m_shouldRetryCurrentStatement = shouldRetry;
453 SQLTransactionBackend::StateFunction SQLTransactionBackend::stateFunctionFor(SQLTransactionState state)
455 static const StateFunction stateFunctions[] = {
456 &SQLTransactionBackend::unreachableState, // 0. end
457 &SQLTransactionBackend::unreachableState, // 1. idle
458 &SQLTransactionBackend::acquireLock, // 2.
459 &SQLTransactionBackend::openTransactionAndPreflight, // 3.
460 &SQLTransactionBackend::runStatements, // 4.
461 &SQLTransactionBackend::postflightAndCommit, // 5.
462 &SQLTransactionBackend::cleanupAndTerminate, // 6.
463 &SQLTransactionBackend::cleanupAfterTransactionErrorCallback, // 7.
464 &SQLTransactionBackend::sendToFrontendState, // 8. deliverTransactionCallback
465 &SQLTransactionBackend::sendToFrontendState, // 9. deliverTransactionErrorCallback
466 &SQLTransactionBackend::sendToFrontendState, // 10. deliverStatementCallback
467 &SQLTransactionBackend::sendToFrontendState, // 11. deliverQuotaIncreaseCallback
468 &SQLTransactionBackend::sendToFrontendState // 12. deliverSuccessCallback
471 ASSERT(WTF_ARRAY_LENGTH(stateFunctions) == static_cast<int>(SQLTransactionState::NumberOfStates));
472 ASSERT(state < SQLTransactionState::NumberOfStates);
474 return stateFunctions[static_cast<int>(state)];
477 void SQLTransactionBackend::enqueueStatementBackend(PassRefPtrWillBeRawPtr<SQLStatementBackend> statementBackend)
479 MutexLocker locker(m_statementMutex);
480 m_statementQueue.append(statementBackend);
483 void SQLTransactionBackend::computeNextStateAndCleanupIfNeeded()
485 // Only honor the requested state transition if we're not supposed to be
486 // cleaning up and shutting down:
487 if (m_database->opened() && !m_database->isInterrupted()) {
488 setStateToRequestedState();
489 ASSERT(m_nextState == SQLTransactionState::AcquireLock
490 || m_nextState == SQLTransactionState::OpenTransactionAndPreflight
491 || m_nextState == SQLTransactionState::RunStatements
492 || m_nextState == SQLTransactionState::PostflightAndCommit
493 || m_nextState == SQLTransactionState::CleanupAndTerminate
494 || m_nextState == SQLTransactionState::CleanupAfterTransactionErrorCallback);
496 WTF_LOG(StorageAPI, "State %s\n", nameForSQLTransactionState(m_nextState));
500 // If we get here, then we should be shutting down. Do clean up if needed:
501 if (m_nextState == SQLTransactionState::End)
503 m_nextState = SQLTransactionState::End;
505 // If the database was stopped, don't do anything and cancel queued work
506 WTF_LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction");
508 // The current SQLite transaction should be stopped, as well
509 if (m_sqliteTransaction) {
510 m_sqliteTransaction->stop();
511 m_sqliteTransaction.clear();
514 // Terminate the frontend state machine. This also gets the frontend to
515 // call computeNextStateAndCleanupIfNeeded() and clear its wrappers
517 m_frontend->requestTransitToState(SQLTransactionState::End);
519 // Redirect to the end state to abort, clean up, and end the transaction.
523 void SQLTransactionBackend::performNextStep()
525 computeNextStateAndCleanupIfNeeded();
529 void SQLTransactionBackend::executeSQL(PassOwnPtr<AbstractSQLStatement> statement,
530 const String& sqlStatement, const Vector<SQLValue>& arguments, int permissions)
532 enqueueStatementBackend(SQLStatementBackend::create(statement, sqlStatement, arguments, permissions));
535 void SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown()
537 ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread());
539 // If the transaction is in progress, we should roll it back here, since this
540 // is our last opportunity to do something related to this transaction on the
541 // DB thread. Amongst other work, doCleanup() will clear m_sqliteTransaction
542 // which invokes SQLiteTransaction's destructor, which will do the roll back
547 SQLTransactionState SQLTransactionBackend::acquireLock()
549 m_database->transactionCoordinator()->acquireLock(this);
550 return SQLTransactionState::Idle;
553 void SQLTransactionBackend::lockAcquired()
555 m_lockAcquired = true;
556 requestTransitToState(SQLTransactionState::OpenTransactionAndPreflight);
559 SQLTransactionState SQLTransactionBackend::openTransactionAndPreflight()
561 ASSERT(!m_database->sqliteDatabase().transactionInProgress());
562 ASSERT(m_lockAcquired);
564 WTF_LOG(StorageAPI, "Opening and preflighting transaction %p", this);
566 // Set the maximum usage for this transaction if this transactions is not read-only
568 m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
570 ASSERT(!m_sqliteTransaction);
571 m_sqliteTransaction = adoptPtr(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly));
573 m_database->resetDeletes();
574 m_database->disableAuthorizer();
575 m_sqliteTransaction->begin();
576 m_database->enableAuthorizer();
578 // Spec 4.3.2.1+2: Open a transaction to the database, jumping to the error callback if that fails
579 if (!m_sqliteTransaction->inProgress()) {
580 ASSERT(!m_database->sqliteDatabase().transactionInProgress());
581 m_database->reportStartTransactionResult(2, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
582 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to begin transaction",
583 m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
584 m_sqliteTransaction.clear();
585 return nextStateForTransactionError();
588 // Note: We intentionally retrieve the actual version even with an empty expected version.
589 // In multi-process browsers, we take this opportinutiy to update the cached value for
590 // the actual version. In single-process browsers, this is just a map lookup.
591 String actualVersion;
592 if (!m_database->getActualVersionForTransaction(actualVersion)) {
593 m_database->reportStartTransactionResult(3, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
594 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to read version",
595 m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
596 m_database->disableAuthorizer();
597 m_sqliteTransaction.clear();
598 m_database->enableAuthorizer();
599 return nextStateForTransactionError();
601 m_hasVersionMismatch = !m_database->expectedVersion().isEmpty() && (m_database->expectedVersion() != actualVersion);
603 // Spec 4.3.2.3: Perform preflight steps, jumping to the error callback if they fail
604 if (m_wrapper && !m_wrapper->performPreflight(this)) {
605 m_database->disableAuthorizer();
606 m_sqliteTransaction.clear();
607 m_database->enableAuthorizer();
608 if (m_wrapper->sqlError()) {
609 m_transactionError = SQLErrorData::create(*m_wrapper->sqlError());
611 m_database->reportStartTransactionResult(4, SQLError::UNKNOWN_ERR, 0);
612 m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight");
614 return nextStateForTransactionError();
617 // Spec 4.3.2.4: Invoke the transaction callback with the new SQLTransaction object
619 return SQLTransactionState::DeliverTransactionCallback;
621 // If we have no callback to make, skip pass to the state after:
622 return SQLTransactionState::RunStatements;
625 SQLTransactionState SQLTransactionBackend::runStatements()
627 ASSERT(m_lockAcquired);
628 SQLTransactionState nextState;
630 // If there is a series of statements queued up that are all successful and have no associated
631 // SQLStatementCallback objects, then we can burn through the queue
633 if (m_shouldRetryCurrentStatement && !m_sqliteTransaction->wasRolledBackBySqlite()) {
634 m_shouldRetryCurrentStatement = false;
635 // FIXME - Another place that needs fixing up after <rdar://problem/5628468> is addressed.
636 // See ::openTransactionAndPreflight() for discussion
638 // Reset the maximum size here, as it was increased to allow us to retry this statement.
639 // m_shouldRetryCurrentStatement is set to true only when a statement exceeds
640 // the quota, which can happen only in a read-write transaction. Therefore, there
641 // is no need to check here if the transaction is read-write.
642 m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize());
644 // If the current statement has already been run, failed due to quota constraints, and we're not retrying it,
645 // that means it ended in an error. Handle it now
646 if (m_currentStatementBackend && m_currentStatementBackend->lastExecutionFailedDueToQuota()) {
647 return nextStateForCurrentStatementError();
650 // Otherwise, advance to the next statement
653 nextState = runCurrentStatementAndGetNextState();
654 } while (nextState == SQLTransactionState::RunStatements);
659 void SQLTransactionBackend::getNextStatement()
661 m_currentStatementBackend = nullptr;
663 MutexLocker locker(m_statementMutex);
664 if (!m_statementQueue.isEmpty())
665 m_currentStatementBackend = m_statementQueue.takeFirst();
668 SQLTransactionState SQLTransactionBackend::runCurrentStatementAndGetNextState()
670 if (!m_currentStatementBackend) {
671 // No more statements to run. So move on to the next state.
672 return SQLTransactionState::PostflightAndCommit;
675 m_database->resetAuthorizer();
677 if (m_hasVersionMismatch)
678 m_currentStatementBackend->setVersionMismatchedError(Database::from(m_database.get()));
680 if (m_currentStatementBackend->execute(m_database.get())) {
681 if (m_database->lastActionChangedDatabase()) {
682 // Flag this transaction as having changed the database for later delegate notification
683 m_modifiedDatabase = true;
686 if (m_currentStatementBackend->hasStatementCallback()) {
687 return SQLTransactionState::DeliverStatementCallback;
690 // If we get here, then the statement doesn't have a callback to invoke.
691 // We can move on to the next statement. Hence, stay in this state.
692 return SQLTransactionState::RunStatements;
695 if (m_currentStatementBackend->lastExecutionFailedDueToQuota()) {
696 return SQLTransactionState::DeliverQuotaIncreaseCallback;
699 return nextStateForCurrentStatementError();
702 SQLTransactionState SQLTransactionBackend::nextStateForCurrentStatementError()
704 // Spec 4.3.2.6.6: error - Call the statement's error callback, but if there was no error callback,
705 // or the transaction was rolled back, jump to the transaction error callback
706 if (m_currentStatementBackend->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite())
707 return SQLTransactionState::DeliverStatementCallback;
709 if (m_currentStatementBackend->sqlError()) {
710 m_transactionError = SQLErrorData::create(*m_currentStatementBackend->sqlError());
712 m_database->reportCommitTransactionResult(1, SQLError::DATABASE_ERR, 0);
713 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "the statement failed to execute");
715 return nextStateForTransactionError();
718 SQLTransactionState SQLTransactionBackend::postflightAndCommit()
720 ASSERT(m_lockAcquired);
722 // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail.
723 if (m_wrapper && !m_wrapper->performPostflight(this)) {
724 if (m_wrapper->sqlError()) {
725 m_transactionError = SQLErrorData::create(*m_wrapper->sqlError());
727 m_database->reportCommitTransactionResult(3, SQLError::UNKNOWN_ERR, 0);
728 m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight");
730 return nextStateForTransactionError();
733 // Spec 4.3.2.7: Commit the transaction, jumping to the error callback if that fails.
734 ASSERT(m_sqliteTransaction);
736 m_database->disableAuthorizer();
737 m_sqliteTransaction->commit();
738 m_database->enableAuthorizer();
740 // If the commit failed, the transaction will still be marked as "in progress"
741 if (m_sqliteTransaction->inProgress()) {
743 m_wrapper->handleCommitFailedAfterPostflight(this);
744 m_database->reportCommitTransactionResult(4, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError());
745 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to commit transaction",
746 m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
747 return nextStateForTransactionError();
750 m_database->reportCommitTransactionResult(0, -1, 0); // OK
752 // Vacuum the database if anything was deleted.
753 if (m_database->hadDeletes())
754 m_database->incrementalVacuumIfNeeded();
756 // The commit was successful. If the transaction modified this database, notify the delegates.
757 if (m_modifiedDatabase)
758 m_database->transactionClient()->didCommitWriteTransaction(database());
760 // Spec 4.3.2.8: Deliver success callback, if there is one.
761 return SQLTransactionState::DeliverSuccessCallback;
764 SQLTransactionState SQLTransactionBackend::cleanupAndTerminate()
766 ASSERT(m_lockAcquired);
768 // Spec 4.3.2.9: End transaction steps. There is no next step.
769 WTF_LOG(StorageAPI, "Transaction %p is complete\n", this);
770 ASSERT(!m_database->sqliteDatabase().transactionInProgress());
772 // Phase 5 cleanup. See comment on the SQLTransaction life-cycle above.
774 m_database->inProgressTransactionCompleted();
775 return SQLTransactionState::End;
778 SQLTransactionState SQLTransactionBackend::nextStateForTransactionError()
780 ASSERT(m_transactionError);
781 if (m_hasErrorCallback)
782 return SQLTransactionState::DeliverTransactionErrorCallback;
784 // No error callback, so fast-forward to the next state and rollback the
786 return SQLTransactionState::CleanupAfterTransactionErrorCallback;
789 SQLTransactionState SQLTransactionBackend::cleanupAfterTransactionErrorCallback()
791 ASSERT(m_lockAcquired);
793 WTF_LOG(StorageAPI, "Transaction %p is complete with an error\n", this);
794 m_database->disableAuthorizer();
795 if (m_sqliteTransaction) {
796 // Spec 4.3.2.10: Rollback the transaction.
797 m_sqliteTransaction->rollback();
799 ASSERT(!m_database->sqliteDatabase().transactionInProgress());
800 m_sqliteTransaction.clear();
802 m_database->enableAuthorizer();
804 ASSERT(!m_database->sqliteDatabase().transactionInProgress());
806 return SQLTransactionState::CleanupAndTerminate;
809 // requestTransitToState() can be called from the frontend. Hence, it should
810 // NOT be modifying SQLTransactionBackend in general. The only safe field to
811 // modify is m_requestedState which is meant for this purpose.
812 void SQLTransactionBackend::requestTransitToState(SQLTransactionState nextState)
814 WTF_LOG(StorageAPI, "Scheduling %s for transaction %p\n", nameForSQLTransactionState(nextState), this);
815 m_requestedState = nextState;
816 ASSERT(m_requestedState != SQLTransactionState::End);
817 m_database->scheduleTransactionStep(this);
820 // This state function is used as a stub function to plug unimplemented states
821 // in the state dispatch table. They are unimplemented because they should
822 // never be reached in the course of correct execution.
823 SQLTransactionState SQLTransactionBackend::unreachableState()
825 ASSERT_NOT_REACHED();
826 return SQLTransactionState::End;
829 SQLTransactionState SQLTransactionBackend::sendToFrontendState()
831 ASSERT(m_nextState != SQLTransactionState::Idle);
832 m_frontend->requestTransitToState(m_nextState);
833 return SQLTransactionState::Idle;
836 } // namespace WebCore