Move basic IDBBackingStoreTransaction operations to IDBServerConnection
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Nov 2013 03:59:48 +0000 (03:59 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Nov 2013 03:59:48 +0000 (03:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=124244

Reviewed by Tim Horton (and unofficially Anders Carlsson).

This patch:
- Makes IDBBackingStore the owner of an IDBBackingStoreTransaction.
- Adds the integer transaction ID to IDBBackingStoreTransaction for reference.
- Removes IDBTransactionBackend’s reliance on IDBBackingStoreTransaction by moving
  necessary methods to IDBServerConnection.
- Renames the IDBTransactionBackend::backingStoreTransaction() accessor to
  deprecatedBackingStoreTransaction to make it clear it’s on the way out.

* Modules/indexeddb/IDBBackingStoreInterface.h:

* Modules/indexeddb/IDBDatabaseBackend.cpp:
(WebCore::IDBDatabaseBackend::setIndexKeys):

* Modules/indexeddb/IDBServerConnection.h:

* Modules/indexeddb/IDBTransactionBackend.cpp:
(WebCore::IDBTransactionBackend::IDBTransactionBackend):
(WebCore::IDBTransactionBackend::~IDBTransactionBackend):
(WebCore::IDBTransactionBackend::deprecatedBackingStoreTransaction):
(WebCore::IDBTransactionBackend::scheduleTask):
(WebCore::IDBTransactionBackend::abort):
(WebCore::IDBTransactionBackend::commit):
(WebCore::IDBTransactionBackend::taskTimerFired):
* Modules/indexeddb/IDBTransactionBackend.h:

* Modules/indexeddb/IDBTransactionBackendOperations.cpp:
(WebCore::CreateObjectStoreOperation::perform):
(WebCore::CreateIndexOperation::perform):
(WebCore::DeleteIndexOperation::perform):
(WebCore::GetOperation::perform):
(WebCore::PutOperation::perform):
(WebCore::OpenCursorOperation::perform):
(WebCore::CountOperation::perform):
(WebCore::DeleteRangeOperation::perform):
(WebCore::ClearOperation::perform):
(WebCore::DeleteObjectStoreOperation::perform):
(WebCore::IDBDatabaseBackend::VersionChangeOperation::perform):

* Modules/indexeddb/leveldb/IDBBackingStoreLevelDB.cpp:
(WebCore::IDBBackingStoreLevelDB::makeIndexWriters):
(WebCore::IDBBackingStoreLevelDB::generateKey):
(WebCore::IDBBackingStoreLevelDB::updateKeyGenerator):
(WebCore::IDBBackingStoreLevelDB::establishBackingStoreTransaction):
(WebCore::IDBBackingStoreLevelDB::deprecatedBackingStoreTransaction):
(WebCore::IDBBackingStoreLevelDB::removeBackingStoreTransaction):
* Modules/indexeddb/leveldb/IDBBackingStoreLevelDB.h:

* Modules/indexeddb/leveldb/IDBBackingStoreTransactionLevelDB.cpp:
(WebCore::IDBBackingStoreTransactionLevelDB::IDBBackingStoreTransactionLevelDB):
(WebCore::IDBBackingStoreTransactionLevelDB::~IDBBackingStoreTransactionLevelDB):
(WebCore::IDBBackingStoreTransactionLevelDB::resetTransaction):
* Modules/indexeddb/leveldb/IDBBackingStoreTransactionLevelDB.h:

* Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.cpp:
(WebCore::IDBServerConnectionLevelDB::IDBServerConnectionLevelDB):
(WebCore::IDBServerConnectionLevelDB::deprecatedBackingStoreTransaction):
(WebCore::IDBServerConnectionLevelDB::openTransaction):
(WebCore::IDBServerConnectionLevelDB::beginTransaction):
(WebCore::IDBServerConnectionLevelDB::commitTransaction):
(WebCore::IDBServerConnectionLevelDB::resetTransaction):
(WebCore::IDBServerConnectionLevelDB::rollbackTransaction):
* Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@159177 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBBackingStoreInterface.h
Source/WebCore/Modules/indexeddb/IDBDatabaseBackend.cpp
Source/WebCore/Modules/indexeddb/IDBServerConnection.h
Source/WebCore/Modules/indexeddb/IDBTransactionBackend.cpp
Source/WebCore/Modules/indexeddb/IDBTransactionBackend.h
Source/WebCore/Modules/indexeddb/IDBTransactionBackendOperations.cpp
Source/WebCore/Modules/indexeddb/leveldb/IDBBackingStoreLevelDB.cpp
Source/WebCore/Modules/indexeddb/leveldb/IDBBackingStoreLevelDB.h
Source/WebCore/Modules/indexeddb/leveldb/IDBBackingStoreTransactionLevelDB.cpp
Source/WebCore/Modules/indexeddb/leveldb/IDBBackingStoreTransactionLevelDB.h
Source/WebCore/Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.cpp
Source/WebCore/Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.h

index 6038081..09d0bb7 100644 (file)
@@ -1,3 +1,73 @@
+2013-11-12  Brady Eidson  <beidson@apple.com>
+
+        Move basic IDBBackingStoreTransaction operations to IDBServerConnection
+        https://bugs.webkit.org/show_bug.cgi?id=124244
+
+        Reviewed by Tim Horton (and unofficially Anders Carlsson).
+
+        This patch:
+        - Makes IDBBackingStore the owner of an IDBBackingStoreTransaction.
+        - Adds the integer transaction ID to IDBBackingStoreTransaction for reference.
+        - Removes IDBTransactionBackend’s reliance on IDBBackingStoreTransaction by moving
+          necessary methods to IDBServerConnection.
+        - Renames the IDBTransactionBackend::backingStoreTransaction() accessor to
+          deprecatedBackingStoreTransaction to make it clear it’s on the way out.
+
+        * Modules/indexeddb/IDBBackingStoreInterface.h:
+
+        * Modules/indexeddb/IDBDatabaseBackend.cpp:
+        (WebCore::IDBDatabaseBackend::setIndexKeys):
+
+        * Modules/indexeddb/IDBServerConnection.h:
+
+        * Modules/indexeddb/IDBTransactionBackend.cpp:
+        (WebCore::IDBTransactionBackend::IDBTransactionBackend):
+        (WebCore::IDBTransactionBackend::~IDBTransactionBackend):
+        (WebCore::IDBTransactionBackend::deprecatedBackingStoreTransaction):
+        (WebCore::IDBTransactionBackend::scheduleTask):
+        (WebCore::IDBTransactionBackend::abort):
+        (WebCore::IDBTransactionBackend::commit):
+        (WebCore::IDBTransactionBackend::taskTimerFired):
+        * Modules/indexeddb/IDBTransactionBackend.h:
+
+        * Modules/indexeddb/IDBTransactionBackendOperations.cpp:
+        (WebCore::CreateObjectStoreOperation::perform):
+        (WebCore::CreateIndexOperation::perform):
+        (WebCore::DeleteIndexOperation::perform):
+        (WebCore::GetOperation::perform):
+        (WebCore::PutOperation::perform):
+        (WebCore::OpenCursorOperation::perform):
+        (WebCore::CountOperation::perform):
+        (WebCore::DeleteRangeOperation::perform):
+        (WebCore::ClearOperation::perform):
+        (WebCore::DeleteObjectStoreOperation::perform):
+        (WebCore::IDBDatabaseBackend::VersionChangeOperation::perform):
+
+        * Modules/indexeddb/leveldb/IDBBackingStoreLevelDB.cpp:
+        (WebCore::IDBBackingStoreLevelDB::makeIndexWriters):
+        (WebCore::IDBBackingStoreLevelDB::generateKey):
+        (WebCore::IDBBackingStoreLevelDB::updateKeyGenerator):
+        (WebCore::IDBBackingStoreLevelDB::establishBackingStoreTransaction):
+        (WebCore::IDBBackingStoreLevelDB::deprecatedBackingStoreTransaction):
+        (WebCore::IDBBackingStoreLevelDB::removeBackingStoreTransaction):
+        * Modules/indexeddb/leveldb/IDBBackingStoreLevelDB.h:
+
+        * Modules/indexeddb/leveldb/IDBBackingStoreTransactionLevelDB.cpp:
+        (WebCore::IDBBackingStoreTransactionLevelDB::IDBBackingStoreTransactionLevelDB):
+        (WebCore::IDBBackingStoreTransactionLevelDB::~IDBBackingStoreTransactionLevelDB):
+        (WebCore::IDBBackingStoreTransactionLevelDB::resetTransaction):
+        * Modules/indexeddb/leveldb/IDBBackingStoreTransactionLevelDB.h:
+
+        * Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.cpp:
+        (WebCore::IDBServerConnectionLevelDB::IDBServerConnectionLevelDB):
+        (WebCore::IDBServerConnectionLevelDB::deprecatedBackingStoreTransaction):
+        (WebCore::IDBServerConnectionLevelDB::openTransaction):
+        (WebCore::IDBServerConnectionLevelDB::beginTransaction):
+        (WebCore::IDBServerConnectionLevelDB::commitTransaction):
+        (WebCore::IDBServerConnectionLevelDB::resetTransaction):
+        (WebCore::IDBServerConnectionLevelDB::rollbackTransaction):
+        * Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.h:
+
 2013-11-12  Andy Estes  <aestes@apple.com>
 
         Fix the Mountain Lion build after r159171.
index 3700233..37c873d 100644 (file)
@@ -53,7 +53,7 @@ class IDBBackingStoreInterface : public RefCounted<IDBBackingStoreInterface> {
 public:
     virtual ~IDBBackingStoreInterface() { }
 
-    virtual PassRefPtr<IDBBackingStoreTransactionInterface> createBackingStoreTransaction() = 0;
+    virtual void establishBackingStoreTransaction(int64_t transactionID) = 0;
 
     // New-style asynchronous callbacks
     typedef std::function<void (const IDBDatabaseMetadata&, bool success)> GetIDBDatabaseMetadataFunction;
index 85d805b..ed16b8d 100644 (file)
@@ -255,7 +255,7 @@ void IDBDatabaseBackend::setIndexKeys(int64_t transactionId, int64_t objectStore
     RefPtr<IDBBackingStoreInterface> store = m_serverConnection->deprecatedBackingStore();
     // FIXME: This method could be asynchronous, but we need to evaluate if it's worth the extra complexity.
     RefPtr<IDBRecordIdentifier> recordIdentifier;
-    bool ok = store->keyExistsInObjectStore(transaction->backingStoreTransaction(), m_metadata.id, objectStoreId, *primaryKey, recordIdentifier);
+    bool ok = store->keyExistsInObjectStore(transaction->deprecatedBackingStoreTransaction(), m_metadata.id, objectStoreId, *primaryKey, recordIdentifier);
     if (!ok) {
         transaction->abort(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error setting index keys."));
         return;
@@ -283,7 +283,7 @@ void IDBDatabaseBackend::setIndexKeys(int64_t transactionId, int64_t objectStore
 
     for (size_t i = 0; i < indexWriters.size(); ++i) {
         IDBIndexWriter* indexWriter = indexWriters[i].get();
-        indexWriter->writeIndexKeys(recordIdentifier.get(), *store.get(), transaction->backingStoreTransaction(), id(), objectStoreId);
+        indexWriter->writeIndexKeys(recordIdentifier.get(), *store.get(), transaction->deprecatedBackingStoreTransaction(), id(), objectStoreId);
     }
 }
 
index 795e703..bee6372 100644 (file)
@@ -27,7 +27,9 @@
 #define IDBServerConnection_h
 
 #include "IDBMetadata.h"
+#include "IndexedDB.h"
 #include <functional>
+#include <wtf/HashSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/WTFString.h>
 
@@ -36,6 +38,7 @@
 namespace WebCore {
 
 class IDBBackingStoreInterface;
+class IDBBackingStoreTransactionInterface;
 
 // This interface provides a single asynchronous layer between the web-facing frontend
 // and the I/O performing backend of IndexedDatabase.
@@ -44,9 +47,10 @@ class IDBServerConnection : public RefCounted<IDBServerConnection> {
 public:
     virtual ~IDBServerConnection() { }
 
-    // FIXME: For now, server connection provides a synchronous accessor to the in-process backing store.
+    // FIXME: For now, server connection provides a synchronous accessor to the in-process backing store objects.
     // This is temporary and will be removed soon.
     virtual IDBBackingStoreInterface* deprecatedBackingStore() = 0;
+    virtual IDBBackingStoreTransactionInterface* deprecatedBackingStoreTransaction(int64_t transactionID) = 0;
 
     virtual bool isClosed() = 0;
 
@@ -57,6 +61,13 @@ public:
     virtual void getOrEstablishIDBDatabaseMetadata(const String& name, GetIDBDatabaseMetadataFunction) = 0;
     virtual void deleteDatabase(const String& name, BoolCallbackFunction successCallback) = 0;
     virtual void close() = 0;
+
+    // Transaction-level operations
+    virtual void openTransaction(int64_t transactionID, const HashSet<int64_t>& objectStoreIds, IndexedDB::TransactionMode, BoolCallbackFunction successCallback) = 0;
+    virtual void beginTransaction(int64_t transactionID, std::function<void()> completionCallback) = 0;
+    virtual void commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback) = 0;
+    virtual void resetTransaction(int64_t transactionID, std::function<void()> completionCallback) = 0;
+    virtual void rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback) = 0;
 };
 
 } // namespace WebCore
index 53bbbea..b95aacf 100644 (file)
@@ -53,11 +53,10 @@ PassRefPtr<IDBTransactionBackend> IDBTransactionBackend::create(IDBDatabaseBacke
 IDBTransactionBackend::IDBTransactionBackend(IDBDatabaseBackend* databaseBackend, int64_t id, PassRefPtr<IDBDatabaseCallbacks> callbacks, const HashSet<int64_t>& objectStoreIds, IndexedDB::TransactionMode mode)
     : m_objectStoreIds(objectStoreIds)
     , m_mode(mode)
-    , m_state(Unused)
+    , m_state(Unopened)
     , m_commitPending(false)
     , m_callbacks(callbacks)
     , m_database(databaseBackend)
-    , m_backingStoreTransaction(m_database->serverConnection().deprecatedBackingStore()->createBackingStoreTransaction())
     , m_taskTimer(this, &IDBTransactionBackend::taskTimerFired)
     , m_pendingPreemptiveEvents(0)
     , m_id(id)
@@ -66,12 +65,35 @@ IDBTransactionBackend::IDBTransactionBackend(IDBDatabaseBackend* databaseBackend
     relaxAdoptionRequirement();
 
     m_database->transactionCoordinator()->didCreateTransaction(this);
+
+    RefPtr<IDBTransactionBackend> backend(this);
+    m_database->serverConnection().openTransaction(id, objectStoreIds, mode, [backend](bool success) {
+        if (!success) {
+            callOnMainThread([backend]() {
+                backend->abort();
+            });
+            return;
+        }
+
+        backend->m_state = Unused;
+        if (backend->hasPendingTasks())
+            backend->start();
+    });
 }
 
 IDBTransactionBackend::~IDBTransactionBackend()
 {
     // It shouldn't be possible for this object to get deleted until it's either complete or aborted.
     ASSERT(m_state == Finished);
+    // The backing store transaction should also be gone by now.
+    ASSERT(!m_database->serverConnection().deprecatedBackingStoreTransaction(m_id));
+}
+
+IDBBackingStoreTransactionInterface& IDBTransactionBackend::deprecatedBackingStoreTransaction()
+{
+    IDBBackingStoreTransactionInterface* backingStoreTransaction = m_database->serverConnection().deprecatedBackingStoreTransaction(m_id);
+    ASSERT(backingStoreTransaction);
+    return *backingStoreTransaction;
 }
 
 void IDBTransactionBackend::scheduleTask(IDBDatabaseBackend::TaskType type, PassRefPtr<IDBOperation> task, PassRefPtr<IDBSynchronousOperation> abortTask)
@@ -87,6 +109,9 @@ void IDBTransactionBackend::scheduleTask(IDBDatabaseBackend::TaskType type, Pass
     if (abortTask)
         m_abortTaskQueue.prepend(abortTask);
 
+    if (m_state == Unopened)
+        return;
+
     if (m_state == Unused)
         start();
     else if (m_state == Running && !m_taskTimer.isActive())
@@ -115,7 +140,7 @@ void IDBTransactionBackend::abort(PassRefPtr<IDBDatabaseError> error)
     m_taskTimer.stop();
 
     if (wasRunning)
-        m_backingStoreTransaction->rollback();
+        m_database->serverConnection().rollbackTransaction(m_id, []() { });
 
     // Run the abort tasks, if any.
     while (!m_abortTaskQueue.isEmpty()) {
@@ -127,7 +152,8 @@ void IDBTransactionBackend::abort(PassRefPtr<IDBDatabaseError> error)
     // are fired, as the script callbacks may release references and allow the backing store
     // itself to be released, and order is critical.
     closeOpenCursors();
-    m_backingStoreTransaction->resetTransaction();
+
+    m_database->serverConnection().resetTransaction(m_id, []() { });
 
     // Transactions must also be marked as completed before the front-end is notified, as
     // the transaction completion unblocks operations like closing connections.
@@ -202,34 +228,39 @@ void IDBTransactionBackend::commit()
     // 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.
-    Ref<IDBTransactionBackend> protect(*this);
+    RefPtr<IDBTransactionBackend> backend(this);
 
     bool unused = m_state == Unused;
     m_state = Finished;
 
-    bool committed = unused || m_backingStoreTransaction->commit();
+    bool committed = unused;
 
-    // Backing store resources (held via cursors) must be released before script callbacks
-    // are fired, as the script callbacks may release references and allow the backing store
-    // itself to be released, and order is critical.
-    closeOpenCursors();
-    m_backingStoreTransaction->resetTransaction();
+    m_database->serverConnection().commitTransaction(m_id, [backend, this, committed, unused](bool success) mutable {
+        committed |= success;
 
-    // Transactions must also be marked as completed before the front-end is notified, as
-    // the transaction completion unblocks operations like closing connections.
-    if (!unused)
-        m_database->transactionCoordinator()->didFinishTransaction(this);
-    m_database->transactionFinished(this);
+        // Backing store resources (held via cursors) must be released before script callbacks
+        // are fired, as the script callbacks may release references and allow the backing store
+        // itself to be released, and order is critical.
+        closeOpenCursors();
 
-    if (committed) {
-        m_callbacks->onComplete(id());
-        m_database->transactionFinishedAndCompleteFired(this);
-    } else {
-        m_callbacks->onAbort(id(), IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error committing transaction."));
-        m_database->transactionFinishedAndAbortFired(this);
-    }
+        m_database->serverConnection().resetTransaction(m_id, []() { });
 
-    m_database = 0;
+        // Transactions must also be marked as completed before the front-end is notified, as
+        // the transaction completion unblocks operations like closing connections.
+        if (!unused)
+            m_database->transactionCoordinator()->didFinishTransaction(this);
+        m_database->transactionFinished(this);
+
+        if (committed) {
+            m_callbacks->onComplete(id());
+            m_database->transactionFinishedAndCompleteFired(this);
+        } else {
+            m_callbacks->onAbort(id(), IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error committing transaction."));
+            m_database->transactionFinishedAndAbortFired(this);
+        }
+
+        m_database = 0;
+    });
 }
 
 void IDBTransactionBackend::taskTimerFired(Timer<IDBTransactionBackend>*)
@@ -237,7 +268,7 @@ void IDBTransactionBackend::taskTimerFired(Timer<IDBTransactionBackend>*)
     LOG(StorageAPI, "IDBTransactionBackend::taskTimerFired");
 
     if (m_state == StartPending) {
-        m_backingStoreTransaction->begin();
+        m_database->serverConnection().beginTransaction(m_id, []() { });
         m_state = Running;
     }
 
index 21070f6..3f5eeb7 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     void addPreemptiveEvent()  { m_pendingPreemptiveEvents++; }
     void didCompletePreemptiveEvent()  { m_pendingPreemptiveEvents--; ASSERT(m_pendingPreemptiveEvents >= 0); }
-    IDBBackingStoreTransactionInterface& backingStoreTransaction() { return *m_backingStoreTransaction; }
+    IDBBackingStoreTransactionInterface& deprecatedBackingStoreTransaction();
 
     IDBDatabaseBackend& database() const  { return *m_database; }
 
@@ -89,7 +89,8 @@ private:
     IDBTransactionBackend(IDBDatabaseBackend*, int64_t id, PassRefPtr<IDBDatabaseCallbacks>, const HashSet<int64_t>& objectStoreIds, IndexedDB::TransactionMode);
 
     enum State {
-        Unused, // Created, but no tasks yet.
+        Unopened, // Backing store transaction not yet created.
+        Unused, // Backing store transaction created, but no tasks yet.
         StartPending, // Enqueued tasks, but backing store transaction not yet started.
         Running, // Backing store transaction started but not yet finished.
         Finished, // Either aborted or committed.
@@ -116,8 +117,6 @@ private:
     TaskQueue m_preemptiveTaskQueue;
     Deque<RefPtr<IDBSynchronousOperation>> m_abortTaskQueue;
 
-    RefPtr<IDBBackingStoreTransactionInterface> m_backingStoreTransaction;
-
     // FIXME: delete the timer once we have threads instead.
     Timer<IDBTransactionBackend> m_taskTimer;
     int m_pendingPreemptiveEvents;
index 966b46d..2959efa 100644 (file)
@@ -58,7 +58,7 @@ void CreateObjectStoreOperation::perform(std::function<void()> completionCallbac
     CallOnDestruct callOnDestruct(completionCallback);
 
     LOG(StorageAPI, "CreateObjectStoreOperation");
-    if (!m_transaction->database().serverConnection().deprecatedBackingStore()->createObjectStore(m_transaction->backingStoreTransaction(), m_transaction->database().id(), m_objectStoreMetadata.id, m_objectStoreMetadata.name, m_objectStoreMetadata.keyPath, m_objectStoreMetadata.autoIncrement)) {
+    if (!m_transaction->database().serverConnection().deprecatedBackingStore()->createObjectStore(m_transaction->deprecatedBackingStoreTransaction(), m_transaction->database().id(), m_objectStoreMetadata.id, m_objectStoreMetadata.name, m_objectStoreMetadata.keyPath, m_objectStoreMetadata.autoIncrement)) {
         RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Internal error creating object store '%s'.", m_objectStoreMetadata.name.utf8().data()));
         m_transaction->abort(error.release());
         return;
@@ -70,7 +70,7 @@ void CreateIndexOperation::perform(std::function<void()> completionCallback)
     CallOnDestruct callOnDestruct(completionCallback);
 
     LOG(StorageAPI, "CreateIndexOperation");
-    if (!m_transaction->database().serverConnection().deprecatedBackingStore()->createIndex(m_transaction->backingStoreTransaction(), m_transaction->database().id(), m_objectStoreId, m_indexMetadata.id, m_indexMetadata.name, m_indexMetadata.keyPath, m_indexMetadata.unique, m_indexMetadata.multiEntry)) {
+    if (!m_transaction->database().serverConnection().deprecatedBackingStore()->createIndex(m_transaction->deprecatedBackingStoreTransaction(), m_transaction->database().id(), m_objectStoreId, m_indexMetadata.id, m_indexMetadata.name, m_indexMetadata.keyPath, m_indexMetadata.unique, m_indexMetadata.multiEntry)) {
         m_transaction->abort(IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Internal error when trying to create index '%s'.", m_indexMetadata.name.utf8().data())));
         return;
     }
@@ -87,7 +87,7 @@ void DeleteIndexOperation::perform(std::function<void()> completionCallback)
     CallOnDestruct callOnDestruct(completionCallback);
 
     LOG(StorageAPI, "DeleteIndexOperation");
-    bool ok = m_transaction->database().serverConnection().deprecatedBackingStore()->deleteIndex(m_transaction->backingStoreTransaction(), m_transaction->database().id(), m_objectStoreId, m_indexMetadata.id);
+    bool ok = m_transaction->database().serverConnection().deprecatedBackingStore()->deleteIndex(m_transaction->deprecatedBackingStoreTransaction(), m_transaction->database().id(), m_objectStoreId, m_indexMetadata.id);
     if (!ok) {
         RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Internal error deleting index '%s'.", m_indexMetadata.name.utf8().data()));
         m_transaction->abort(error);
@@ -115,14 +115,14 @@ void GetOperation::perform(std::function<void()> completionCallback)
         if (m_indexId == IDBIndexMetadata::InvalidId) {
             ASSERT(m_cursorType != IndexedDB::CursorKeyOnly);
             // ObjectStore Retrieval Operation
-            backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), IndexedDB::CursorNext);
+            backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), IndexedDB::CursorNext);
         } else {
             if (m_cursorType == IndexedDB::CursorKeyOnly) {
                 // Index Value Retrieval Operation
-                backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexKeyCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), IndexedDB::CursorNext);
+                backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexKeyCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), IndexedDB::CursorNext);
             } else {
                 // Index Referenced Value Retrieval Operation
-                backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), IndexedDB::CursorNext);
+                backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), IndexedDB::CursorNext);
             }
         }
 
@@ -139,7 +139,7 @@ void GetOperation::perform(std::function<void()> completionCallback)
     if (m_indexId == IDBIndexMetadata::InvalidId) {
         // Object Store Retrieval Operation
         Vector<char> value;
-        ok = m_transaction->database().serverConnection().deprecatedBackingStore()->getRecord(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, *key, value);
+        ok = m_transaction->database().serverConnection().deprecatedBackingStore()->getRecord(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, *key, value);
         if (!ok) {
             m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error in getRecord."));
             return;
@@ -161,7 +161,7 @@ void GetOperation::perform(std::function<void()> completionCallback)
     }
 
     // From here we are dealing only with indexes.
-    ok = m_transaction->database().serverConnection().deprecatedBackingStore()->getPrimaryKeyViaIndex(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, *key, primaryKey);
+    ok = m_transaction->database().serverConnection().deprecatedBackingStore()->getPrimaryKeyViaIndex(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, *key, primaryKey);
     if (!ok) {
         m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error in getPrimaryKeyViaIndex."));
         return;
@@ -178,7 +178,7 @@ void GetOperation::perform(std::function<void()> completionCallback)
 
     // Index Referenced Value Retrieval Operation
     Vector<char> value;
-    ok = m_transaction->database().serverConnection().deprecatedBackingStore()->getRecord(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, *primaryKey, value);
+    ok = m_transaction->database().serverConnection().deprecatedBackingStore()->getRecord(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, *primaryKey, value);
     if (!ok) {
         m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error in getRecord."));
         return;
@@ -221,7 +221,7 @@ void PutOperation::perform(std::function<void()> completionCallback)
 
     RefPtr<IDBRecordIdentifier> recordIdentifier;
     if (m_putMode == IDBDatabaseBackend::AddOnly) {
-        bool ok = m_transaction->database().serverConnection().deprecatedBackingStore()->keyExistsInObjectStore(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStore.id, *key, recordIdentifier);
+        bool ok = m_transaction->database().serverConnection().deprecatedBackingStore()->keyExistsInObjectStore(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStore.id, *key, recordIdentifier);
         if (!ok) {
             m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error checking key existence."));
             return;
@@ -246,7 +246,7 @@ void PutOperation::perform(std::function<void()> completionCallback)
     }
 
     // Before this point, don't do any mutation. After this point, rollback the transaction in case of error.
-    backingStoreSuccess = m_transaction->database().serverConnection().deprecatedBackingStore()->putRecord(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStore.id, *key, m_value, recordIdentifier.get());
+    backingStoreSuccess = m_transaction->database().serverConnection().deprecatedBackingStore()->putRecord(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStore.id, *key, m_value, recordIdentifier.get());
     if (!backingStoreSuccess) {
         m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Internal error: backing store error performing put/add."));
         return;
@@ -254,7 +254,7 @@ void PutOperation::perform(std::function<void()> completionCallback)
 
     for (size_t i = 0; i < indexWriters.size(); ++i) {
         IDBIndexWriter* indexWriter = indexWriters[i].get();
-        indexWriter->writeIndexKeys(recordIdentifier.get(), *m_transaction->database().serverConnection().deprecatedBackingStore(), m_transaction->backingStoreTransaction(), m_databaseId, m_objectStore.id);
+        indexWriter->writeIndexKeys(recordIdentifier.get(), *m_transaction->database().serverConnection().deprecatedBackingStore(), m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStore.id);
     }
 
     if (m_objectStore.autoIncrement && m_putMode != IDBDatabaseBackend::CursorUpdate && key->type() == IDBKey::NumberType) {
@@ -293,13 +293,13 @@ void OpenCursorOperation::perform(std::function<void()> completionCallback)
     RefPtr<IDBBackingStoreCursorInterface> backingStoreCursor;
     if (m_indexId == IDBIndexMetadata::InvalidId) {
         ASSERT(m_cursorType != IndexedDB::CursorKeyOnly);
-        backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), m_direction);
+        backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), m_direction);
     } else {
         ASSERT(m_taskType == IDBDatabaseBackend::NormalTask);
         if (m_cursorType == IndexedDB::CursorKeyOnly)
-            backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexKeyCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), m_direction);
+            backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexKeyCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), m_direction);
         else
-            backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), m_direction);
+            backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), m_direction);
     }
 
     if (!backingStoreCursor) {
@@ -322,9 +322,9 @@ void CountOperation::perform(std::function<void()> completionCallback)
     RefPtr<IDBBackingStoreCursorInterface> backingStoreCursor;
 
     if (m_indexId == IDBIndexMetadata::InvalidId)
-        backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreKeyCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), IndexedDB::CursorNext);
+        backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreKeyCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), IndexedDB::CursorNext);
     else
-        backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexKeyCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), IndexedDB::CursorNext);
+        backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openIndexKeyCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_indexId, m_keyRange.get(), IndexedDB::CursorNext);
     if (!backingStoreCursor) {
         m_callbacks->onSuccess(count);
         return;
@@ -342,10 +342,10 @@ void DeleteRangeOperation::perform(std::function<void()> completionCallback)
     CallOnDestruct callOnDestruct(completionCallback);
 
     LOG(StorageAPI, "DeleteRangeOperation");
-    RefPtr<IDBBackingStoreCursorInterface> backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreCursor(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), IndexedDB::CursorNext);
+    RefPtr<IDBBackingStoreCursorInterface> backingStoreCursor = m_transaction->database().serverConnection().deprecatedBackingStore()->openObjectStoreCursor(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, m_keyRange.get(), IndexedDB::CursorNext);
     if (backingStoreCursor) {
         do {
-            if (!m_transaction->database().serverConnection().deprecatedBackingStore()->deleteRecord(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId, backingStoreCursor->recordIdentifier())) {
+            if (!m_transaction->database().serverConnection().deprecatedBackingStore()->deleteRecord(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId, backingStoreCursor->recordIdentifier())) {
                 m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Error deleting data in range"));
                 return;
             }
@@ -360,7 +360,7 @@ void ClearOperation::perform(std::function<void()> completionCallback)
     CallOnDestruct callOnDestruct(completionCallback);
 
     LOG(StorageAPI, "ObjectStoreClearOperation");
-    if (!m_transaction->database().serverConnection().deprecatedBackingStore()->clearObjectStore(m_transaction->backingStoreTransaction(), m_databaseId, m_objectStoreId)) {
+    if (!m_transaction->database().serverConnection().deprecatedBackingStore()->clearObjectStore(m_transaction->deprecatedBackingStoreTransaction(), m_databaseId, m_objectStoreId)) {
         m_callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Error clearing object store"));
         return;
     }
@@ -372,7 +372,7 @@ void DeleteObjectStoreOperation::perform(std::function<void()> completionCallbac
     CallOnDestruct callOnDestruct(completionCallback);
 
     LOG(StorageAPI, "DeleteObjectStoreOperation");
-    bool ok = m_transaction->database().serverConnection().deprecatedBackingStore()->deleteObjectStore(m_transaction->backingStoreTransaction(), m_transaction->database().id(), m_objectStoreMetadata.id);
+    bool ok = m_transaction->database().serverConnection().deprecatedBackingStore()->deleteObjectStore(m_transaction->deprecatedBackingStoreTransaction(), m_transaction->database().id(), m_objectStoreMetadata.id);
     if (!ok) {
         RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Internal error deleting object store '%s'.", m_objectStoreMetadata.name.utf8().data()));
         m_transaction->abort(error);
@@ -391,7 +391,7 @@ void IDBDatabaseBackend::VersionChangeOperation::perform(std::function<void()> c
     // FIXME: Database versions are now of type uint64_t, but this code expected int64_t.
     ASSERT(m_version > (int64_t)oldVersion);
     database.setCurrentVersion(m_version);
-    if (!database.serverConnection().deprecatedBackingStore()->updateIDBDatabaseVersion(m_transaction->backingStoreTransaction(), databaseId, database.metadata().version)) {
+    if (!database.serverConnection().deprecatedBackingStore()->updateIDBDatabaseVersion(m_transaction->deprecatedBackingStoreTransaction(), databaseId, database.metadata().version)) {
         RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Error writing data to stable storage when updating version.");
         m_callbacks->onError(error);
         m_transaction->abort(error);
index b588d69..72c9405 100644 (file)
@@ -1402,7 +1402,8 @@ bool IDBBackingStoreLevelDB::makeIndexWriters(IDBTransactionBackend& transaction
 
         RefPtr<IDBIndexWriter> indexWriter = IDBIndexWriter::create(index, keys);
         bool canAddKeys = false;
-        bool backingStoreSuccess = indexWriter->verifyIndexKeys(*this, transaction.backingStoreTransaction(), databaseId, objectStore.id, index.id, canAddKeys, &primaryKey, errorMessage);
+        ASSERT(m_backingStoreTransactions.contains(transaction.id()));
+        bool backingStoreSuccess = indexWriter->verifyIndexKeys(*this, *m_backingStoreTransactions.get(transaction.id()), databaseId, objectStore.id, index.id, canAddKeys, &primaryKey, errorMessage);
         if (!backingStoreSuccess)
             return false;
         if (!canAddKeys)
@@ -1419,7 +1420,8 @@ PassRefPtr<IDBKey> IDBBackingStoreLevelDB::generateKey(IDBTransactionBackend& tr
 {
     const int64_t maxGeneratorValue = 9007199254740992LL; // Maximum integer storable as ECMAScript number.
     int64_t currentNumber;
-    bool ok = getKeyGeneratorCurrentNumber(transaction.backingStoreTransaction(), databaseId, objectStoreId, currentNumber);
+    ASSERT(m_backingStoreTransactions.contains(transaction.id()));
+    bool ok = getKeyGeneratorCurrentNumber(*m_backingStoreTransactions.get(transaction.id()), databaseId, objectStoreId, currentNumber);
     if (!ok) {
         LOG_ERROR("Failed to getKeyGeneratorCurrentNumber");
         return IDBKey::createInvalid();
@@ -1434,7 +1436,9 @@ PassRefPtr<IDBKey> IDBBackingStoreLevelDB::generateKey(IDBTransactionBackend& tr
 bool IDBBackingStoreLevelDB::updateKeyGenerator(IDBTransactionBackend& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, bool checkCurrent)
 {
     ASSERT(key.type() == IDBKey::NumberType);
-    return maybeUpdateKeyGeneratorCurrentNumber(transaction.backingStoreTransaction(), databaseId, objectStoreId, static_cast<int64_t>(floor(key.number())) + 1, checkCurrent);
+    ASSERT(m_backingStoreTransactions.contains(transaction.id()));
+
+    return maybeUpdateKeyGeneratorCurrentNumber(*m_backingStoreTransactions.get(transaction.id()), databaseId, objectStoreId, static_cast<int64_t>(floor(key.number())) + 1, checkCurrent);
 }
 
 class ObjectStoreKeyCursorImpl : public IDBBackingStoreCursorLevelDB {
@@ -1912,9 +1916,21 @@ PassRefPtr<IDBBackingStoreCursorInterface> IDBBackingStoreLevelDB::openIndexCurs
     return cursor.release();
 }
 
-PassRefPtr<IDBBackingStoreTransactionInterface> IDBBackingStoreLevelDB::createBackingStoreTransaction()
+void IDBBackingStoreLevelDB::establishBackingStoreTransaction(int64_t transactionID)
+{
+    ASSERT(!m_backingStoreTransactions.contains(transactionID));
+    m_backingStoreTransactions.set(transactionID, IDBBackingStoreTransactionLevelDB::create(transactionID, this));
+}
+
+IDBBackingStoreTransactionInterface* IDBBackingStoreLevelDB::deprecatedBackingStoreTransaction(int64_t transactionID)
+{
+    return m_backingStoreTransactions.get(transactionID);
+}
+
+void IDBBackingStoreLevelDB::removeBackingStoreTransaction(IDBBackingStoreTransactionLevelDB* transaction)
 {
-    return IDBBackingStoreTransactionLevelDB::create(this);
+    ASSERT(m_backingStoreTransactions.contains(transaction->transactionID()));
+    m_backingStoreTransactions.remove(transaction->transactionID());
 }
 
 } // namespace WebCore
index a0952a7..5e2fb8d 100644 (file)
@@ -44,6 +44,7 @@ namespace WebCore {
 class LevelDBComparator;
 class LevelDBDatabase;
 class LevelDBTransaction;
+class IDBBackingStoreTransactionLevelDB;
 class IDBKey;
 class IDBKeyRange;
 class SecurityOrigin;
@@ -67,7 +68,7 @@ public:
     static PassRefPtr<IDBBackingStoreLevelDB> openInMemory(const String& identifier, LevelDBFactory*);
     WeakPtr<IDBBackingStoreLevelDB> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
 
-    virtual PassRefPtr<IDBBackingStoreTransactionInterface> createBackingStoreTransaction();
+    virtual void establishBackingStoreTransaction(int64_t transactionID);
 
     virtual Vector<String> getDatabaseNames();
 
@@ -109,6 +110,9 @@ public:
 
     static int compareIndexKeys(const LevelDBSlice&, const LevelDBSlice&);
 
+    IDBBackingStoreTransactionInterface* deprecatedBackingStoreTransaction(int64_t transactionID);
+    void removeBackingStoreTransaction(IDBBackingStoreTransactionLevelDB*);
+
 protected:
     IDBBackingStoreLevelDB(const String& identifier, PassOwnPtr<LevelDBDatabase>, PassOwnPtr<LevelDBComparator>);
 
@@ -128,6 +132,8 @@ private:
     OwnPtr<LevelDBDatabase> m_db;
     OwnPtr<LevelDBComparator> m_comparator;
     WeakPtrFactory<IDBBackingStoreLevelDB> m_weakFactory;
+
+    HashMap<int64_t, RefPtr<IDBBackingStoreTransactionLevelDB>> m_backingStoreTransactions;
 };
 
 } // namespace WebCore
index 6816cb3..a7a5f66 100644 (file)
 
 namespace WebCore {
 
-IDBBackingStoreTransactionLevelDB::IDBBackingStoreTransactionLevelDB(IDBBackingStoreInterface* backingStore)
-    : m_backingStore(backingStore)
+IDBBackingStoreTransactionLevelDB::IDBBackingStoreTransactionLevelDB(int64_t transactionID, IDBBackingStoreLevelDB* backingStore)
+    : m_transactionID(transactionID)
+    , m_backingStore(backingStore)
 {
 }
 
+IDBBackingStoreTransactionLevelDB::~IDBBackingStoreTransactionLevelDB()
+{
+    if (m_backingStore)
+        m_backingStore->removeBackingStoreTransaction(this);
+}
+
 void IDBBackingStoreTransactionLevelDB::begin()
 {
     LOG(StorageAPI, "IDBBackingStoreTransactionLevelDB::begin");
@@ -66,6 +73,14 @@ void IDBBackingStoreTransactionLevelDB::rollback()
     m_transaction.clear();
 }
 
+void IDBBackingStoreTransactionLevelDB::resetTransaction()
+{
+    ASSERT(m_backingStore);
+    m_backingStore->removeBackingStoreTransaction(this);
+    m_backingStore = 0;
+    m_transaction = 0;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE) && USE(LEVELDB)
index ab28597..507dbda 100644 (file)
 
 namespace WebCore {
 
-class IDBBackingStoreInterface;
+class IDBBackingStoreLevelDB;
 
 class IDBBackingStoreTransactionLevelDB FINAL : public IDBBackingStoreTransactionInterface {
 public:
-    static PassRefPtr<IDBBackingStoreTransactionInterface> create(IDBBackingStoreInterface* backingStore)
+    static PassRefPtr<IDBBackingStoreTransactionLevelDB> create(int64_t transactionID, IDBBackingStoreLevelDB* backingStore)
     {
-        return adoptRef(new IDBBackingStoreTransactionLevelDB(backingStore));
+        return adoptRef(new IDBBackingStoreTransactionLevelDB(transactionID, backingStore));
     }
 
+    virtual ~IDBBackingStoreTransactionLevelDB();
+
     virtual void begin() OVERRIDE;
     virtual bool commit() OVERRIDE;
     virtual void rollback() OVERRIDE;
-    virtual void resetTransaction() OVERRIDE
-    {
-        m_backingStore = 0;
-        m_transaction = 0;
-    }
+    virtual void resetTransaction() OVERRIDE;
 
     static LevelDBTransaction* levelDBTransactionFrom(IDBBackingStoreTransactionInterface& transaction)
     {
         return static_cast<IDBBackingStoreTransactionLevelDB&>(transaction).m_transaction.get();
     }
 
+    int64_t transactionID() { return m_transactionID; }
+
 private:
-    IDBBackingStoreTransactionLevelDB(IDBBackingStoreInterface*);
+    IDBBackingStoreTransactionLevelDB(int64_t transactionID, IDBBackingStoreLevelDB*);
 
-    IDBBackingStoreInterface* m_backingStore;
+    int64_t m_transactionID;
+    IDBBackingStoreLevelDB* m_backingStore;
     RefPtr<LevelDBTransaction> m_transaction;
 };
 
index 6bc1496..f60c4e9 100644 (file)
 #if ENABLE(INDEXED_DATABASE)
 #if USE(LEVELDB)
 
-#include "IDBBackingStoreInterface.h"
+#include "IDBBackingStoreLevelDB.h"
+#include "IDBBackingStoreTransactionLevelDB.h"
+#include <wtf/MainThread.h>
 
 namespace WebCore {
 
-IDBServerConnectionLevelDB::IDBServerConnectionLevelDB(IDBBackingStoreInterface* backingStore)
+IDBServerConnectionLevelDB::IDBServerConnectionLevelDB(IDBBackingStoreLevelDB* backingStore)
     : m_backingStore(backingStore)
     , m_closed(false)
 {
@@ -48,6 +50,13 @@ IDBBackingStoreInterface* IDBServerConnectionLevelDB::deprecatedBackingStore()
     return m_backingStore.get();
 }
 
+IDBBackingStoreTransactionInterface* IDBServerConnectionLevelDB::deprecatedBackingStoreTransaction(int64_t transactionID)
+{
+    if (!m_backingStore)
+        return 0;
+    return m_backingStore->deprecatedBackingStoreTransaction(transactionID);
+}
+
 bool IDBServerConnectionLevelDB::isClosed()
 {
     return m_closed;
@@ -75,6 +84,59 @@ void IDBServerConnectionLevelDB::close()
     m_closed = true;
 }
 
+void IDBServerConnectionLevelDB::openTransaction(int64_t transactionID, const HashSet<int64_t>&, IndexedDB::TransactionMode, BoolCallbackFunction successCallback)
+{
+    if (!m_backingStore) {
+        callOnMainThread([successCallback]() {
+            successCallback(false);
+        });
+        return;
+    }
+
+    m_backingStore->establishBackingStoreTransaction(transactionID);
+    callOnMainThread([successCallback]() {
+        successCallback(true);
+    });
+}
+
+void IDBServerConnectionLevelDB::beginTransaction(int64_t transactionID, std::function<void()> completionCallback)
+{
+    RefPtr<IDBBackingStoreTransactionLevelDB> transaction = m_backingStoreTransactions.get(transactionID);
+    ASSERT(transaction);
+
+    transaction->begin();
+    callOnMainThread(completionCallback);
+}
+
+void IDBServerConnectionLevelDB::commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback)
+{
+    RefPtr<IDBBackingStoreTransactionLevelDB> transaction = m_backingStoreTransactions.get(transactionID);
+    ASSERT(transaction);
+
+    bool result = transaction->commit();
+    callOnMainThread([successCallback, result]() {
+        successCallback(result);
+    });
+}
+
+void IDBServerConnectionLevelDB::resetTransaction(int64_t transactionID, std::function<void()> completionCallback)
+{
+    RefPtr<IDBBackingStoreTransactionLevelDB> transaction = m_backingStoreTransactions.get(transactionID);
+    ASSERT(transaction);
+
+    transaction->resetTransaction();
+    callOnMainThread(completionCallback);
+}
+
+void IDBServerConnectionLevelDB::rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback)
+{
+    RefPtr<IDBBackingStoreTransactionLevelDB> transaction = m_backingStoreTransactions.get(transactionID);
+    ASSERT(transaction);
+
+    transaction->rollback();
+    callOnMainThread(completionCallback);
+}
+
 } // namespace WebCore
 
 #endif // USE(LEVELDB)
index 9818bae..df0dfe8 100644 (file)
 
 namespace WebCore {
 
-class IDBBackingStoreInterface;
+class IDBBackingStoreLevelDB;
+class IDBBackingStoreTransactionLevelDB;
 
 class IDBServerConnectionLevelDB FINAL : public IDBServerConnection {
 public:
-    static PassRefPtr<IDBServerConnection> create(IDBBackingStoreInterface* backingStore)
+    static PassRefPtr<IDBServerConnection> create(IDBBackingStoreLevelDB* backingStore)
     {
         return adoptRef(new IDBServerConnectionLevelDB(backingStore));
     }
 
     virtual ~IDBServerConnectionLevelDB();
 
-    // FIXME: For now, server connection provides a synchronous accessor to the in-process backing store.
+    // FIXME: For now, server connection provides a synchronous accessor to the in-process backing store objects.
     // This is temporary and will be removed soon.
     virtual IDBBackingStoreInterface* deprecatedBackingStore() OVERRIDE;
+    virtual IDBBackingStoreTransactionInterface* deprecatedBackingStoreTransaction(int64_t transactionID) OVERRIDE;
 
     virtual bool isClosed() OVERRIDE;
 
@@ -55,10 +57,19 @@ public:
     virtual void deleteDatabase(const String& name, BoolCallbackFunction successCallback) OVERRIDE;
     virtual void close() OVERRIDE;
 
+    // Transaction-level operations
+    virtual void openTransaction(int64_t transactionID, const HashSet<int64_t>& objectStoreIds, IndexedDB::TransactionMode, BoolCallbackFunction successCallback) OVERRIDE;
+    virtual void beginTransaction(int64_t transactionID, std::function<void()> completionCallback) OVERRIDE;
+    virtual void commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback) OVERRIDE;
+    virtual void resetTransaction(int64_t transactionID, std::function<void()> completionCallback) OVERRIDE;
+    virtual void rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback) OVERRIDE;
+
 private:
-    IDBServerConnectionLevelDB(IDBBackingStoreInterface*);
+    IDBServerConnectionLevelDB(IDBBackingStoreLevelDB*);
+
+    RefPtr<IDBBackingStoreLevelDB> m_backingStore;
+    HashMap<int64_t, RefPtr<IDBBackingStoreTransactionLevelDB>> m_backingStoreTransactions;
 
-    RefPtr<IDBBackingStoreInterface> m_backingStore;
     bool m_closed;
 };