- Revision
- 135332
- Author
- jsb...@chromium.org
- Date
- 2012-11-20 16:35:09 -0800 (Tue, 20 Nov 2012)
Log Message
IndexedDB: Move control of transaction completion to front end
https://bugs.webkit.org/show_bug.cgi?id=100903
Reviewed by Tony Chang.
"When a transaction can no longer become active, the implementation must attempt to
commit it" - that is, all requests have dispatched success/error events and no further
requests have been made. Previously, this was done by the back end waiting for events
from the front end, but the front end can more efficiently make the decision.
There should be no detectable behavior change.
Tests: storage/indexeddb/transaction-*.html
* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::IDBTransaction):
(WebCore::IDBTransaction::setActive):
(WebCore::IDBTransaction::registerRequest):
* Modules/indexeddb/IDBTransaction.h:
* Modules/indexeddb/IDBTransactionBackendImpl.cpp:
(WebCore::IDBTransactionBackendImpl::hasPendingTasks): Added.
(WebCore::IDBTransactionBackendImpl::didCompleteTaskEvents):
(WebCore::IDBTransactionBackendImpl::run):
(WebCore::IDBTransactionBackendImpl::taskEventTimerFired):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (135331 => 135332)
--- trunk/Source/WebCore/ChangeLog 2012-11-21 00:27:00 UTC (rev 135331)
+++ trunk/Source/WebCore/ChangeLog 2012-11-21 00:35:09 UTC (rev 135332)
@@ -1,3 +1,30 @@
+2012-11-20 Joshua Bell <jsb...@chromium.org>
+
+ IndexedDB: Move control of transaction completion to front end
+ https://bugs.webkit.org/show_bug.cgi?id=100903
+
+ Reviewed by Tony Chang.
+
+ "When a transaction can no longer become active, the implementation must attempt to
+ commit it" - that is, all requests have dispatched success/error events and no further
+ requests have been made. Previously, this was done by the back end waiting for events
+ from the front end, but the front end can more efficiently make the decision.
+
+ There should be no detectable behavior change.
+
+ Tests: storage/indexeddb/transaction-*.html
+
+ * Modules/indexeddb/IDBTransaction.cpp:
+ (WebCore::IDBTransaction::IDBTransaction):
+ (WebCore::IDBTransaction::setActive):
+ (WebCore::IDBTransaction::registerRequest):
+ * Modules/indexeddb/IDBTransaction.h:
+ * Modules/indexeddb/IDBTransactionBackendImpl.cpp:
+ (WebCore::IDBTransactionBackendImpl::hasPendingTasks): Added.
+ (WebCore::IDBTransactionBackendImpl::didCompleteTaskEvents):
+ (WebCore::IDBTransactionBackendImpl::run):
+ (WebCore::IDBTransactionBackendImpl::taskEventTimerFired):
+
2012-11-20 Kentaro Hara <hara...@chromium.org>
Unreviewed. Rebaselined run-bindings-tests results.
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (135331 => 135332)
--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp 2012-11-21 00:27:00 UTC (rev 135331)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp 2012-11-21 00:35:09 UTC (rev 135332)
@@ -500,6 +500,11 @@
m_transaction->setActive(true);
bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets);
+
+ if (m_transaction && m_readyState == DONE)
+ m_transaction->unregisterRequest(this);
+
+ // If this was the last request in the transaction's list, it may commit here.
if (setTransactionActive)
m_transaction->setActive(false);
@@ -518,9 +523,6 @@
if (event->type() != eventNames().blockedEvent)
m_transaction->backend()->didCompleteTaskEvents();
-
- if (m_readyState == DONE)
- m_transaction->unregisterRequest(this);
}
return dontPreventDefault;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (135331 => 135332)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp 2012-11-21 00:27:00 UTC (rev 135331)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp 2012-11-21 00:35:09 UTC (rev 135332)
@@ -95,8 +95,7 @@
, m_objectStoreNames(objectStoreNames)
, m_openDBRequest(openDBRequest)
, m_mode(mode)
- , m_active(true)
- , m_state(Unused)
+ , m_state(Active)
, m_hasPendingActivity(true)
, m_contextStopped(false)
{
@@ -104,14 +103,12 @@
if (mode == VERSION_CHANGE) {
// Not active until the callback.
- m_active = false;
- // Implicitly used by the version change itself.
- m_state = Used;
+ m_state = Inactive;
}
// We pass a reference of this object before it can be adopted.
relaxAdoptionRequirement();
- if (m_active)
+ if (m_state == Active)
IDBPendingTransactionMonitor::addNewTransaction(this);
m_database->transactionCreated(this);
}
@@ -206,11 +203,10 @@
ASSERT_WITH_MESSAGE(m_state != Finished, "A finished transaction tried to setActive(%s)", active ? "true" : "false");
if (m_state == Finishing)
return;
- ASSERT(m_state == Unused || m_state == Used);
- ASSERT(active != m_active);
- m_active = active;
+ ASSERT(active != (m_state == Active));
+ m_state = active ? Active : Inactive;
- if (!active && m_state == Unused)
+ if (!active && m_requestList.isEmpty())
m_backend->commit();
}
@@ -222,7 +218,6 @@
}
m_state = Finishing;
- m_active = false;
while (!m_requestList.isEmpty()) {
IDBRequest* request = *m_requestList.begin();
@@ -278,10 +273,8 @@
void IDBTransaction::registerRequest(IDBRequest* request)
{
ASSERT(request);
- ASSERT(m_state == Unused || m_state == Used);
- ASSERT(m_active);
+ ASSERT(m_state == Active);
m_requestList.add(request);
- m_state = Used;
}
void IDBTransaction::unregisterRequest(IDBRequest* request)
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h (135331 => 135332)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h 2012-11-21 00:27:00 UTC (rev 135331)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h 2012-11-21 00:35:09 UTC (rev 135332)
@@ -70,7 +70,7 @@
static const AtomicString& modeToString(Mode, ExceptionCode&);
IDBTransactionBackendInterface* backend() const;
- bool isActive() const { return m_active; }
+ bool isActive() const { return m_state == Active; }
bool isFinished() const { return m_state == Finished; }
bool isReadOnly() const { return m_mode == READ_ONLY; }
bool isVersionChange() const { return m_mode == VERSION_CHANGE; }
@@ -137,8 +137,8 @@
virtual EventTargetData* ensureEventTargetData();
enum State {
- Unused, // No requests have been made.
- Used, // At least one request has been made.
+ Inactive, // Created or started, but not in an event callback
+ Active, // Created or started, in creation scope or an event callback
Finishing, // In the process of aborting or completing.
Finished, // No more events will fire and no new requests may be filed.
};
@@ -148,7 +148,6 @@
const Vector<String> m_objectStoreNames;
IDBOpenDBRequest* m_openDBRequest;
const Mode m_mode;
- bool m_active;
State m_state;
bool m_hasPendingActivity;
bool m_contextStopped;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp (135331 => 135332)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp 2012-11-21 00:27:00 UTC (rev 135331)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp 2012-11-21 00:35:09 UTC (rev 135332)
@@ -151,6 +151,11 @@
return m_preemptiveTaskQueue.isEmpty() && m_taskQueue.isEmpty();
}
+bool IDBTransactionBackendImpl::hasPendingTasks() const
+{
+ return m_pendingEvents || m_pendingPreemptiveEvents || !isTaskQueueEmpty();
+}
+
void IDBTransactionBackendImpl::registerOpenCursor(IDBCursorBackendImpl* cursor)
{
m_openCursors.add(cursor);
@@ -176,12 +181,16 @@
ASSERT(m_pendingEvents);
m_pendingEvents--;
+ // A single task has completed and error/success events fired. Schedule
+ // timer to process another.
if (!m_taskEventTimer.isActive())
m_taskEventTimer.startOneShot(0);
}
void IDBTransactionBackendImpl::run()
{
+ // TransactionCoordinator has started this transaction. Schedule a timer
+ // to process the first task.
ASSERT(m_state == StartPending || m_state == Running);
ASSERT(!m_taskTimer.isActive());
@@ -200,12 +209,18 @@
void IDBTransactionBackendImpl::commit()
{
IDB_TRACE("IDBTransactionBackendImpl::commit");
+
+ ASSERT(m_state == Unused || m_state == Running);
+
+ // Front-end has requested a commit, but there may be tasks like createIndex which
+ // are considered synchronous by the front-end but are processed asynchronously.
+ if (hasPendingTasks())
+ return;
+
// The last reference to this object may be released while performing the
// commit steps below. We therefore take a self reference to keep ourselves
// alive while executing this method.
RefPtr<IDBTransactionBackendImpl> protect(this);
- ASSERT(m_state == Unused || m_state == Running);
- ASSERT(isTaskQueueEmpty());
bool unused = m_state == Unused;
m_state = Finished;
@@ -267,7 +282,7 @@
IDB_TRACE("IDBTransactionBackendImpl::taskEventTimerFired");
ASSERT(m_state == Running);
- if (!m_pendingEvents && !m_pendingPreemptiveEvents && isTaskQueueEmpty()) {
+ if (!hasPendingTasks()) {
// The last task event has completed and the task
// queue is empty. Commit the transaction.
commit();
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h (135331 => 135332)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h 2012-11-21 00:27:00 UTC (rev 135331)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h 2012-11-21 00:35:09 UTC (rev 135332)
@@ -74,8 +74,8 @@
enum State {
Unused, // Created, but no tasks yet.
- StartPending, // Enqueued tasks, but SQLite transaction not yet started.
- Running, // SQLite transaction started but not yet finished.
+ StartPending, // Enqueued tasks, but backing store transaction not yet started.
+ Running, // Backing store transaction started but not yet finished.
Finished, // Either aborted or committed.
};
@@ -83,6 +83,7 @@
void commit();
bool isTaskQueueEmpty() const;
+ bool hasPendingTasks() const;
void taskTimerFired(Timer<IDBTransactionBackendImpl>*);
void taskEventTimerFired(Timer<IDBTransactionBackendImpl>*);