<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[204356] trunk/Source/WebCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/204356">204356</a></dd>
<dt>Author</dt> <dd>andersca@apple.com</dd>
<dt>Date</dt> <dd>2016-08-10 14:31:07 -0700 (Wed, 10 Aug 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Begin moving member functions from SQLTransactionBackend to SQLTransaction
https://bugs.webkit.org/show_bug.cgi?id=160747
Reviewed by Tim Horton.
* Modules/webdatabase/Database.cpp:
(WebCore::Database::performClose):
* Modules/webdatabase/DatabaseTask.cpp:
(WebCore::DatabaseTransactionTask::~DatabaseTransactionTask):
(WebCore::DatabaseTransactionTask::doPerformTask):
* Modules/webdatabase/SQLTransaction.cpp:
(WebCore::SQLTransaction::executeSQL):
(WebCore::SQLTransaction::lockAcquired):
(WebCore::SQLTransaction::performNextStep):
(WebCore::SQLTransaction::performPendingCallback):
(WebCore::SQLTransaction::notifyDatabaseThreadIsShuttingDown):
(WebCore::SQLTransaction::enqueueStatement):
(WebCore::SQLTransaction::getNextStatement):
(WebCore::SQLTransaction::runCurrentStatement):
(WebCore::SQLTransaction::handleCurrentStatementError):
(WebCore::SQLTransaction::handleTransactionError):
(WebCore::SQLTransaction::postflightAndCommit):
(WebCore::SQLTransaction::acquireOriginLock):
(WebCore::SQLTransaction::releaseOriginLockIfNeeded):
* Modules/webdatabase/SQLTransaction.h:
(WebCore::SQLTransaction::backend): Deleted.
* Modules/webdatabase/SQLTransactionBackend.cpp:
(WebCore::SQLTransactionBackend::doCleanup):
(WebCore::SQLTransactionBackend::openTransactionAndPreflight):
(WebCore::SQLTransactionBackend::runStatements):
(WebCore::SQLTransactionBackend::cleanupAfterTransactionErrorCallback):
(WebCore::SQLTransactionBackend::enqueueStatement): Deleted.
(WebCore::SQLTransactionBackend::performNextStep): Deleted.
(WebCore::SQLTransactionBackend::executeSQL): Deleted.
(WebCore::SQLTransactionBackend::lockAcquired): Deleted.
(WebCore::SQLTransactionBackend::getNextStatement): Deleted.
(WebCore::SQLTransactionBackend::runCurrentStatement): Deleted.
(WebCore::SQLTransactionBackend::handleCurrentStatementError): Deleted.
(WebCore::SQLTransactionBackend::handleTransactionError): Deleted.
(WebCore::SQLTransactionBackend::postflightAndCommit): Deleted.
(WebCore::SQLTransactionBackend::acquireOriginLock): Deleted.
(WebCore::SQLTransactionBackend::releaseOriginLockIfNeeded): Deleted.
* Modules/webdatabase/SQLTransactionBackend.h:
* Modules/webdatabase/SQLTransactionCoordinator.cpp:
(WebCore::SQLTransactionCoordinator::processPendingTransactions):
(WebCore::SQLTransactionCoordinator::shutdown):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseDatabasecpp">trunk/Source/WebCore/Modules/webdatabase/Database.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseDatabaseTaskcpp">trunk/Source/WebCore/Modules/webdatabase/DatabaseTask.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseSQLTransactioncpp">trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseSQLTransactionh">trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseSQLTransactionBackendcpp">trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseSQLTransactionBackendh">trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebdatabaseSQLTransactionCoordinatorcpp">trunk/Source/WebCore/Modules/webdatabase/SQLTransactionCoordinator.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/ChangeLog        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -1,5 +1,54 @@
</span><span class="cx"> 2016-08-10 Anders Carlsson <andersca@apple.com>
</span><span class="cx">
</span><ins>+ Begin moving member functions from SQLTransactionBackend to SQLTransaction
+ https://bugs.webkit.org/show_bug.cgi?id=160747
+
+ Reviewed by Tim Horton.
+
+ * Modules/webdatabase/Database.cpp:
+ (WebCore::Database::performClose):
+ * Modules/webdatabase/DatabaseTask.cpp:
+ (WebCore::DatabaseTransactionTask::~DatabaseTransactionTask):
+ (WebCore::DatabaseTransactionTask::doPerformTask):
+ * Modules/webdatabase/SQLTransaction.cpp:
+ (WebCore::SQLTransaction::executeSQL):
+ (WebCore::SQLTransaction::lockAcquired):
+ (WebCore::SQLTransaction::performNextStep):
+ (WebCore::SQLTransaction::performPendingCallback):
+ (WebCore::SQLTransaction::notifyDatabaseThreadIsShuttingDown):
+ (WebCore::SQLTransaction::enqueueStatement):
+ (WebCore::SQLTransaction::getNextStatement):
+ (WebCore::SQLTransaction::runCurrentStatement):
+ (WebCore::SQLTransaction::handleCurrentStatementError):
+ (WebCore::SQLTransaction::handleTransactionError):
+ (WebCore::SQLTransaction::postflightAndCommit):
+ (WebCore::SQLTransaction::acquireOriginLock):
+ (WebCore::SQLTransaction::releaseOriginLockIfNeeded):
+ * Modules/webdatabase/SQLTransaction.h:
+ (WebCore::SQLTransaction::backend): Deleted.
+ * Modules/webdatabase/SQLTransactionBackend.cpp:
+ (WebCore::SQLTransactionBackend::doCleanup):
+ (WebCore::SQLTransactionBackend::openTransactionAndPreflight):
+ (WebCore::SQLTransactionBackend::runStatements):
+ (WebCore::SQLTransactionBackend::cleanupAfterTransactionErrorCallback):
+ (WebCore::SQLTransactionBackend::enqueueStatement): Deleted.
+ (WebCore::SQLTransactionBackend::performNextStep): Deleted.
+ (WebCore::SQLTransactionBackend::executeSQL): Deleted.
+ (WebCore::SQLTransactionBackend::lockAcquired): Deleted.
+ (WebCore::SQLTransactionBackend::getNextStatement): Deleted.
+ (WebCore::SQLTransactionBackend::runCurrentStatement): Deleted.
+ (WebCore::SQLTransactionBackend::handleCurrentStatementError): Deleted.
+ (WebCore::SQLTransactionBackend::handleTransactionError): Deleted.
+ (WebCore::SQLTransactionBackend::postflightAndCommit): Deleted.
+ (WebCore::SQLTransactionBackend::acquireOriginLock): Deleted.
+ (WebCore::SQLTransactionBackend::releaseOriginLockIfNeeded): Deleted.
+ * Modules/webdatabase/SQLTransactionBackend.h:
+ * Modules/webdatabase/SQLTransactionCoordinator.cpp:
+ (WebCore::SQLTransactionCoordinator::processPendingTransactions):
+ (WebCore::SQLTransactionCoordinator::shutdown):
+
+2016-08-10 Anders Carlsson <andersca@apple.com>
+
</ins><span class="cx"> Move all SQLTransactionBackend member variables to SQLTransaction
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=160745
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseDatabasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/Database.cpp (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/Database.cpp        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/Database.cpp        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -314,7 +314,7 @@
</span><span class="cx"> // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
</span><span class="cx"> while (!m_transactionQueue.isEmpty()) {
</span><span class="cx"> auto transaction = m_transactionQueue.takeFirst();
</span><del>- transaction->backend().notifyDatabaseThreadIsShuttingDown();
</del><ins>+ transaction->notifyDatabaseThreadIsShuttingDown();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> m_isTransactionQueueEnabled = false;
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseDatabaseTaskcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/DatabaseTask.cpp (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/DatabaseTask.cpp        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/DatabaseTask.cpp        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -163,12 +163,12 @@
</span><span class="cx"> // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
</span><span class="cx">
</span><span class="cx"> if (!m_didPerformTask)
</span><del>- m_transaction->backend().notifyDatabaseThreadIsShuttingDown();
</del><ins>+ m_transaction->notifyDatabaseThreadIsShuttingDown();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void DatabaseTransactionTask::doPerformTask()
</span><span class="cx"> {
</span><del>- m_transaction->backend().performNextStep();
</del><ins>+ m_transaction->performNextStep();
</ins><span class="cx"> m_didPerformTask = true;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseSQLTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include "Database.h"
</span><span class="cx"> #include "DatabaseAuthorizer.h"
</span><span class="cx"> #include "DatabaseContext.h"
</span><ins>+#include "DatabaseTracker.h"
</ins><span class="cx"> #include "ExceptionCode.h"
</span><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "OriginLock.h"
</span><span class="lines">@@ -75,6 +76,58 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, RefPtr<SQLStatementCallback>&& callback, RefPtr<SQLStatementErrorCallback>&& callbackError, ExceptionCode& ec)
+{
+ if (!m_executeSqlAllowed || !m_database->opened()) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ int permissions = DatabaseAuthorizer::ReadWriteMask;
+ if (!m_database->databaseContext()->allowDatabaseAccess())
+ permissions |= DatabaseAuthorizer::NoAccessMask;
+ else if (m_readOnly)
+ permissions |= DatabaseAuthorizer::ReadOnlyMask;
+
+ auto statement = std::make_unique<SQLStatement>(m_database, sqlStatement, arguments, WTFMove(callback), WTFMove(callbackError), permissions);
+
+ if (m_database->deleted())
+ statement->setDatabaseDeletedError();
+
+ enqueueStatement(WTFMove(statement));
+}
+
+void SQLTransaction::lockAcquired()
+{
+ m_lockAcquired = true;
+
+ m_backend.m_requestedState = SQLTransactionState::OpenTransactionAndPreflight;
+ m_database->scheduleTransactionStep(*this);
+}
+
+void SQLTransaction::performNextStep()
+{
+ m_backend.computeNextStateAndCleanupIfNeeded();
+ m_backend.runStateMachine();
+}
+
+void SQLTransaction::performPendingCallback()
+{
+ computeNextStateAndCleanupIfNeeded();
+ runStateMachine();
+}
+
+void SQLTransaction::notifyDatabaseThreadIsShuttingDown()
+{
+ m_backend.notifyDatabaseThreadIsShuttingDown();
+}
+
+void SQLTransaction::enqueueStatement(std::unique_ptr<SQLStatement> statement)
+{
+ LockHolder locker(m_statementMutex);
+ m_statementQueue.append(WTFMove(statement));
+}
+
</ins><span class="cx"> SQLTransaction::StateFunction SQLTransaction::stateFunctionFor(SQLTransactionState state)
</span><span class="cx"> {
</span><span class="cx"> static const StateFunction stateFunctions[] = {
</span><span class="lines">@@ -203,29 +256,6 @@
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SQLTransaction::performPendingCallback()
-{
- computeNextStateAndCleanupIfNeeded();
- runStateMachine();
-}
-
-void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, RefPtr<SQLStatementCallback>&& callback, RefPtr<SQLStatementErrorCallback>&& callbackError, ExceptionCode& ec)
-{
- if (!m_executeSqlAllowed || !m_database->opened()) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- int permissions = DatabaseAuthorizer::ReadWriteMask;
- if (!m_database->databaseContext()->allowDatabaseAccess())
- permissions |= DatabaseAuthorizer::NoAccessMask;
- else if (m_readOnly)
- permissions |= DatabaseAuthorizer::ReadOnlyMask;
-
- auto statement = std::make_unique<SQLStatement>(m_database, sqlStatement, arguments, WTFMove(callback), WTFMove(callbackError), permissions);
- m_backend.executeSQL(WTFMove(statement));
-}
-
</del><span class="cx"> void SQLTransaction::computeNextStateAndCleanupIfNeeded()
</span><span class="cx"> {
</span><span class="cx"> // Only honor the requested state transition if we're not supposed to be
</span><span class="lines">@@ -255,4 +285,139 @@
</span><span class="cx"> m_errorCallbackWrapper.clear();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void SQLTransaction::getNextStatement()
+{
+ m_currentStatement = nullptr;
+
+ LockHolder locker(m_statementMutex);
+ if (!m_statementQueue.isEmpty())
+ m_currentStatement = m_statementQueue.takeFirst();
+}
+
+bool SQLTransaction::runCurrentStatement()
+{
+ if (!m_currentStatement) {
+ // No more statements to run. So move on to the next state.
+ return false;
+ }
+
+ m_database->resetAuthorizer();
+
+ if (m_hasVersionMismatch)
+ m_currentStatement->setVersionMismatchedError();
+
+ if (m_currentStatement->execute(m_database)) {
+ if (m_database->lastActionChangedDatabase()) {
+ // Flag this transaction as having changed the database for later delegate notification
+ m_modifiedDatabase = true;
+ }
+
+ if (m_currentStatement->hasStatementCallback()) {
+ requestTransitToState(SQLTransactionState::DeliverStatementCallback);
+ return false;
+ }
+
+ // If we get here, then the statement doesn't have a callback to invoke.
+ // We can move on to the next statement. Hence, stay in this state.
+ return true;
+ }
+
+ if (m_currentStatement->lastExecutionFailedDueToQuota()) {
+ requestTransitToState(SQLTransactionState::DeliverQuotaIncreaseCallback);
+ return false;
+ }
+
+ handleCurrentStatementError();
+ return false;
+}
+
+void SQLTransaction::handleCurrentStatementError()
+{
+ // Spec 4.3.2.6.6: error - Call the statement's error callback, but if there was no error callback,
+ // or the transaction was rolled back, jump to the transaction error callback
+ if (m_currentStatement->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite()) {
+ requestTransitToState(SQLTransactionState::DeliverStatementCallback);
+ return;
+ }
+
+ m_transactionError = m_currentStatement->sqlError();
+ if (!m_transactionError)
+ m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "the statement failed to execute");
+
+ handleTransactionError();
+}
+
+void SQLTransaction::handleTransactionError()
+{
+ ASSERT(m_transactionError);
+ if (m_errorCallbackWrapper.hasCallback()) {
+ requestTransitToState(SQLTransactionState::DeliverTransactionErrorCallback);
+ return;
+ }
+
+ // No error callback, so fast-forward to the next state and rollback the
+ // transaction.
+ m_backend.cleanupAfterTransactionErrorCallback();
+}
+
+void SQLTransaction::postflightAndCommit()
+{
+ ASSERT(m_lockAcquired);
+
+ // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail.
+ if (m_wrapper && !m_wrapper->performPostflight(*this)) {
+ m_transactionError = m_wrapper->sqlError();
+ if (!m_transactionError)
+ m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight");
+
+ handleTransactionError();
+ return;
+ }
+
+ // Spec 4.3.2.7: Commit the transaction, jumping to the error callback if that fails.
+ ASSERT(m_sqliteTransaction);
+
+ m_database->disableAuthorizer();
+ m_sqliteTransaction->commit();
+ m_database->enableAuthorizer();
+
+ releaseOriginLockIfNeeded();
+
+ // If the commit failed, the transaction will still be marked as "in progress"
+ if (m_sqliteTransaction->inProgress()) {
+ if (m_wrapper)
+ m_wrapper->handleCommitFailedAfterPostflight(*this);
+ m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to commit transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg());
+
+ handleTransactionError();
+ return;
+ }
+
+ // Vacuum the database if anything was deleted.
+ if (m_database->hadDeletes())
+ m_database->incrementalVacuumIfNeeded();
+
+ // The commit was successful. If the transaction modified this database, notify the delegates.
+ if (m_modifiedDatabase)
+ m_database->transactionClient()->didCommitWriteTransaction(m_database.ptr());
+
+ // Spec 4.3.2.8: Deliver success callback, if there is one.
+ requestTransitToState(SQLTransactionState::DeliverSuccessCallback);
+}
+
+void SQLTransaction::acquireOriginLock()
+{
+ ASSERT(!m_originLock);
+ m_originLock = DatabaseTracker::tracker().originLockFor(m_database->securityOrigin());
+ m_originLock->lock();
+}
+
+void SQLTransaction::releaseOriginLockIfNeeded()
+{
+ if (m_originLock) {
+ m_originLock->unlock();
+ m_originLock = nullptr;
+ }
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseSQLTransactionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.h (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.h        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.h        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -64,11 +64,13 @@
</span><span class="cx">
</span><span class="cx"> void executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, RefPtr<SQLStatementCallback>&&, RefPtr<SQLStatementErrorCallback>&&, ExceptionCode&);
</span><span class="cx">
</span><ins>+ void lockAcquired();
+ void performNextStep();
</ins><span class="cx"> void performPendingCallback();
</span><span class="cx">
</span><span class="cx"> Database& database() { return m_database; }
</span><span class="cx"> bool isReadOnly() const { return m_readOnly; }
</span><del>- SQLTransactionBackend& backend() { return m_backend; }
</del><ins>+ void notifyDatabaseThreadIsShuttingDown();
</ins><span class="cx">
</span><span class="cx"> // APIs called from the backend published via SQLTransaction:
</span><span class="cx"> void requestTransitToState(SQLTransactionState);
</span><span class="lines">@@ -78,6 +80,8 @@
</span><span class="cx">
</span><span class="cx"> SQLTransaction(Ref<Database>&&, RefPtr<SQLTransactionCallback>&&, RefPtr<VoidCallback>&& successCallback, RefPtr<SQLTransactionErrorCallback>&&, RefPtr<SQLTransactionWrapper>&&, bool readOnly);
</span><span class="cx">
</span><ins>+ void enqueueStatement(std::unique_ptr<SQLStatement>);
+
</ins><span class="cx"> void clearCallbackWrappers();
</span><span class="cx">
</span><span class="cx"> // State Machine functions:
</span><span class="lines">@@ -93,6 +97,15 @@
</span><span class="cx">
</span><span class="cx"> NO_RETURN_DUE_TO_ASSERT void unreachableState();
</span><span class="cx">
</span><ins>+ void getNextStatement();
+ bool runCurrentStatement();
+ void handleCurrentStatementError();
+ void handleTransactionError();
+ void postflightAndCommit();
+
+ void acquireOriginLock();
+ void releaseOriginLockIfNeeded();
+
</ins><span class="cx"> Ref<Database> m_database;
</span><span class="cx"> SQLCallbackWrapper<SQLTransactionCallback> m_callbackWrapper;
</span><span class="cx"> SQLCallbackWrapper<VoidCallback> m_successCallbackWrapper;
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseSQLTransactionBackendcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.cpp (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.cpp        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.cpp        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -358,7 +358,7 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(currentThread() == m_frontend.database().databaseContext()->databaseThread()->getThreadID());
</span><span class="cx">
</span><del>- releaseOriginLockIfNeeded();
</del><ins>+ m_frontend.releaseOriginLockIfNeeded();
</ins><span class="cx">
</span><span class="cx"> LockHolder locker(m_frontend.m_statementMutex);
</span><span class="cx"> m_frontend.m_statementQueue.clear();
</span><span class="lines">@@ -426,12 +426,6 @@
</span><span class="cx"> return stateFunctions[static_cast<int>(state)];
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SQLTransactionBackend::enqueueStatement(std::unique_ptr<SQLStatement> statement)
-{
- LockHolder locker(m_frontend.m_statementMutex);
- m_frontend.m_statementQueue.append(WTFMove(statement));
-}
-
</del><span class="cx"> void SQLTransactionBackend::computeNextStateAndCleanupIfNeeded()
</span><span class="cx"> {
</span><span class="cx"> // Only honor the requested state transition if we're not supposed to be
</span><span class="lines">@@ -472,20 +466,6 @@
</span><span class="cx"> doCleanup();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SQLTransactionBackend::performNextStep()
-{
- computeNextStateAndCleanupIfNeeded();
- runStateMachine();
-}
-
-void SQLTransactionBackend::executeSQL(std::unique_ptr<SQLStatement> statement)
-{
- if (m_frontend.m_database->deleted())
- statement->setDatabaseDeletedError();
-
- enqueueStatement(WTFMove(statement));
-}
-
</del><span class="cx"> void SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown()
</span><span class="cx"> {
</span><span class="cx"> ASSERT(currentThread() == m_frontend.m_database->databaseContext()->databaseThread()->getThreadID());
</span><span class="lines">@@ -503,15 +483,6 @@
</span><span class="cx"> m_frontend.m_database->transactionCoordinator()->acquireLock(m_frontend);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SQLTransactionBackend::lockAcquired()
-{
- m_frontend.m_lockAcquired = true;
-
- m_requestedState = SQLTransactionState::OpenTransactionAndPreflight;
- ASSERT(m_requestedState != SQLTransactionState::End);
- m_frontend.m_database->scheduleTransactionStep(m_frontend);
-}
-
</del><span class="cx"> void SQLTransactionBackend::openTransactionAndPreflight()
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!m_frontend.m_database->sqliteDatabase().transactionInProgress());
</span><span class="lines">@@ -523,13 +494,13 @@
</span><span class="cx"> if (m_frontend.m_database->deleted()) {
</span><span class="cx"> m_frontend.m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unable to open a transaction, because the user deleted the database");
</span><span class="cx">
</span><del>- handleTransactionError();
</del><ins>+ m_frontend.handleTransactionError();
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Set the maximum usage for this transaction if this transactions is not read-only
</span><span class="cx"> if (!m_frontend.m_readOnly) {
</span><del>- acquireOriginLock();
</del><ins>+ m_frontend.acquireOriginLock();
</ins><span class="cx"> m_frontend.m_database->sqliteDatabase().setMaximumSize(m_frontend.m_database->maximumSize());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -547,7 +518,7 @@
</span><span class="cx"> m_frontend.m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to begin transaction", m_frontend.m_database->sqliteDatabase().lastError(), m_frontend.m_database->sqliteDatabase().lastErrorMsg());
</span><span class="cx"> m_frontend.m_sqliteTransaction = nullptr;
</span><span class="cx">
</span><del>- handleTransactionError();
</del><ins>+ m_frontend.handleTransactionError();
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -561,7 +532,7 @@
</span><span class="cx"> m_frontend.m_sqliteTransaction = nullptr;
</span><span class="cx"> m_frontend.m_database->enableAuthorizer();
</span><span class="cx">
</span><del>- handleTransactionError();
</del><ins>+ m_frontend.handleTransactionError();
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -576,7 +547,7 @@
</span><span class="cx"> if (!m_frontend.m_transactionError)
</span><span class="cx"> m_frontend.m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight");
</span><span class="cx">
</span><del>- handleTransactionError();
</del><ins>+ m_frontend.handleTransactionError();
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -611,142 +582,22 @@
</span><span class="cx"> // If the current statement has already been run, failed due to quota constraints, and we're not retrying it,
</span><span class="cx"> // that means it ended in an error. Handle it now
</span><span class="cx"> if (m_frontend.m_currentStatement && m_frontend.m_currentStatement->lastExecutionFailedDueToQuota()) {
</span><del>- handleCurrentStatementError();
</del><ins>+ m_frontend.handleCurrentStatementError();
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Otherwise, advance to the next statement
</span><del>- getNextStatement();
</del><ins>+ m_frontend.getNextStatement();
</ins><span class="cx"> }
</span><del>- } while (runCurrentStatement());
</del><ins>+ } while (m_frontend.runCurrentStatement());
</ins><span class="cx">
</span><span class="cx"> // If runCurrentStatement() returned false, that means either there was no current statement to run,
</span><span class="cx"> // or the current statement requires a callback to complete. In the later case, it also scheduled
</span><span class="cx"> // the callback or performed any other additional work so we can return.
</span><span class="cx"> if (!m_frontend.m_currentStatement)
</span><del>- postflightAndCommit();
</del><ins>+ m_frontend.postflightAndCommit();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SQLTransactionBackend::getNextStatement()
-{
- m_frontend.m_currentStatement = nullptr;
-
- LockHolder locker(m_frontend.m_statementMutex);
- if (!m_frontend.m_statementQueue.isEmpty())
- m_frontend.m_currentStatement = m_frontend.m_statementQueue.takeFirst();
-}
-
-bool SQLTransactionBackend::runCurrentStatement()
-{
- if (!m_frontend.m_currentStatement) {
- // No more statements to run. So move on to the next state.
- return false;
- }
-
- m_frontend.m_database->resetAuthorizer();
-
- if (m_frontend.m_hasVersionMismatch)
- m_frontend.m_currentStatement->setVersionMismatchedError();
-
- if (m_frontend.m_currentStatement->execute(m_frontend.m_database)) {
- if (m_frontend.m_database->lastActionChangedDatabase()) {
- // Flag this transaction as having changed the database for later delegate notification
- m_frontend.m_modifiedDatabase = true;
- }
-
- if (m_frontend.m_currentStatement->hasStatementCallback()) {
- m_frontend.requestTransitToState(SQLTransactionState::DeliverStatementCallback);
- return false;
- }
-
- // If we get here, then the statement doesn't have a callback to invoke.
- // We can move on to the next statement. Hence, stay in this state.
- return true;
- }
-
- if (m_frontend.m_currentStatement->lastExecutionFailedDueToQuota()) {
- m_frontend.requestTransitToState(SQLTransactionState::DeliverQuotaIncreaseCallback);
- return false;
- }
-
- handleCurrentStatementError();
- return false;
-}
-
-void SQLTransactionBackend::handleCurrentStatementError()
-{
- // Spec 4.3.2.6.6: error - Call the statement's error callback, but if there was no error callback,
- // or the transaction was rolled back, jump to the transaction error callback
- if (m_frontend.m_currentStatement->hasStatementErrorCallback() && !m_frontend.m_sqliteTransaction->wasRolledBackBySqlite()) {
- m_frontend.requestTransitToState(SQLTransactionState::DeliverStatementCallback);
- return;
- }
-
- m_frontend.m_transactionError = m_frontend.m_currentStatement->sqlError();
- if (!m_frontend.m_transactionError)
- m_frontend.m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "the statement failed to execute");
-
- handleTransactionError();
-}
-
-void SQLTransactionBackend::handleTransactionError()
-{
- ASSERT(m_frontend.m_transactionError);
- if (m_frontend.m_errorCallbackWrapper.hasCallback()) {
- m_frontend.requestTransitToState(SQLTransactionState::DeliverTransactionErrorCallback);
- return;
- }
-
- // No error callback, so fast-forward to the next state and rollback the
- // transaction.
- cleanupAfterTransactionErrorCallback();
-}
-
-void SQLTransactionBackend::postflightAndCommit()
-{
- ASSERT(m_frontend.m_lockAcquired);
-
- // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail.
- if (m_frontend.m_wrapper && !m_frontend.m_wrapper->performPostflight(m_frontend)) {
- m_frontend.m_transactionError = m_frontend.m_wrapper->sqlError();
- if (!m_frontend.m_transactionError)
- m_frontend.m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight");
-
- handleTransactionError();
- return;
- }
-
- // Spec 4.3.2.7: Commit the transaction, jumping to the error callback if that fails.
- ASSERT(m_frontend.m_sqliteTransaction);
-
- m_frontend.m_database->disableAuthorizer();
- m_frontend.m_sqliteTransaction->commit();
- m_frontend.m_database->enableAuthorizer();
-
- releaseOriginLockIfNeeded();
-
- // If the commit failed, the transaction will still be marked as "in progress"
- if (m_frontend.m_sqliteTransaction->inProgress()) {
- if (m_frontend.m_wrapper)
- m_frontend.m_wrapper->handleCommitFailedAfterPostflight(m_frontend);
- m_frontend.m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to commit transaction", m_frontend.m_database->sqliteDatabase().lastError(), m_frontend.m_database->sqliteDatabase().lastErrorMsg());
-
- handleTransactionError();
- return;
- }
-
- // Vacuum the database if anything was deleted.
- if (m_frontend.m_database->hadDeletes())
- m_frontend.m_database->incrementalVacuumIfNeeded();
-
- // The commit was successful. If the transaction modified this database, notify the delegates.
- if (m_frontend.m_modifiedDatabase)
- m_frontend.m_database->transactionClient()->didCommitWriteTransaction(m_frontend.m_database.ptr());
-
- // Spec 4.3.2.8: Deliver success callback, if there is one.
- m_frontend.requestTransitToState(SQLTransactionState::DeliverSuccessCallback);
-}
-
</del><span class="cx"> void SQLTransactionBackend::cleanupAndTerminate()
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_frontend.m_lockAcquired);
</span><span class="lines">@@ -775,7 +626,7 @@
</span><span class="cx"> }
</span><span class="cx"> m_frontend.m_database->enableAuthorizer();
</span><span class="cx">
</span><del>- releaseOriginLockIfNeeded();
</del><ins>+ m_frontend.releaseOriginLockIfNeeded();
</ins><span class="cx">
</span><span class="cx"> ASSERT(!m_frontend.m_database->sqliteDatabase().transactionInProgress());
</span><span class="cx">
</span><span class="lines">@@ -801,19 +652,4 @@
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SQLTransactionBackend::acquireOriginLock()
-{
- ASSERT(!m_frontend.m_originLock);
- m_frontend.m_originLock = DatabaseTracker::tracker().originLockFor(m_frontend.m_database->securityOrigin());
- m_frontend.m_originLock->lock();
-}
-
-void SQLTransactionBackend::releaseOriginLockIfNeeded()
-{
- if (m_frontend.m_originLock) {
- m_frontend.m_originLock->unlock();
- m_frontend.m_originLock = nullptr;
- }
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseSQLTransactionBackendh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -52,21 +52,16 @@
</span><span class="cx"> explicit SQLTransactionBackend(SQLTransaction&);
</span><span class="cx"> ~SQLTransactionBackend();
</span><span class="cx">
</span><del>- void lockAcquired();
- void performNextStep();
-
</del><span class="cx"> void notifyDatabaseThreadIsShuttingDown();
</span><span class="cx">
</span><del>- // APIs called from the frontend published via SQLTransactionBackend:
</del><ins>+ // API called from the frontend published via SQLTransactionBackend:
</ins><span class="cx"> void requestTransitToState(SQLTransactionState);
</span><del>- void executeSQL(std::unique_ptr<SQLStatement>);
-
</del><ins>+
</ins><span class="cx"> private:
</span><ins>+ friend class SQLTransaction;
</ins><span class="cx">
</span><span class="cx"> void doCleanup();
</span><span class="cx">
</span><del>- void enqueueStatement(std::unique_ptr<SQLStatement>);
-
</del><span class="cx"> // State Machine functions:
</span><span class="cx"> StateFunction stateFunctionFor(SQLTransactionState) override;
</span><span class="cx"> void computeNextStateAndCleanupIfNeeded();
</span><span class="lines">@@ -80,15 +75,6 @@
</span><span class="cx">
</span><span class="cx"> NO_RETURN_DUE_TO_ASSERT void unreachableState();
</span><span class="cx">
</span><del>- void getNextStatement();
- bool runCurrentStatement();
- void handleCurrentStatementError();
- void handleTransactionError();
- void postflightAndCommit();
-
- void acquireOriginLock();
- void releaseOriginLockIfNeeded();
-
</del><span class="cx"> SQLTransaction& m_frontend;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebdatabaseSQLTransactionCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webdatabase/SQLTransactionCoordinator.cpp (204355 => 204356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webdatabase/SQLTransactionCoordinator.cpp        2016-08-10 21:25:28 UTC (rev 204355)
+++ trunk/Source/WebCore/Modules/webdatabase/SQLTransactionCoordinator.cpp        2016-08-10 21:31:07 UTC (rev 204356)
</span><span class="lines">@@ -62,12 +62,12 @@
</span><span class="cx"> do {
</span><span class="cx"> firstPendingTransaction = info.pendingTransactions.takeFirst();
</span><span class="cx"> info.activeReadTransactions.add(firstPendingTransaction);
</span><del>- firstPendingTransaction->backend().lockAcquired();
</del><ins>+ firstPendingTransaction->lockAcquired();
</ins><span class="cx"> } while (!info.pendingTransactions.isEmpty() && info.pendingTransactions.first()->isReadOnly());
</span><span class="cx"> } else if (info.activeReadTransactions.isEmpty()) {
</span><span class="cx"> info.pendingTransactions.removeFirst();
</span><span class="cx"> info.activeWriteTransaction = firstPendingTransaction;
</span><del>- firstPendingTransaction->backend().lockAcquired();
</del><ins>+ firstPendingTransaction->lockAcquired();
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -122,9 +122,9 @@
</span><span class="cx"> // Transaction phase 4 cleanup. See comment on "What happens if a
</span><span class="cx"> // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
</span><span class="cx"> if (info.activeWriteTransaction)
</span><del>- info.activeWriteTransaction->backend().notifyDatabaseThreadIsShuttingDown();
</del><ins>+ info.activeWriteTransaction->notifyDatabaseThreadIsShuttingDown();
</ins><span class="cx"> for (auto& transaction : info.activeReadTransactions)
</span><del>- transaction->backend().notifyDatabaseThreadIsShuttingDown();
</del><ins>+ transaction->notifyDatabaseThreadIsShuttingDown();
</ins><span class="cx">
</span><span class="cx"> // Clean up transactions that have NOT reached "lockAcquired":
</span><span class="cx"> // Transaction phase 3 cleanup. See comment on "What happens if a
</span><span class="lines">@@ -131,7 +131,7 @@
</span><span class="cx"> // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
</span><span class="cx"> while (!info.pendingTransactions.isEmpty()) {
</span><span class="cx"> RefPtr<SQLTransaction> transaction = info.pendingTransactions.first();
</span><del>- transaction->backend().notifyDatabaseThreadIsShuttingDown();
</del><ins>+ transaction->notifyDatabaseThreadIsShuttingDown();
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>