Modern IDB: autoIncrement support.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Oct 2015 04:55:12 +0000 (04:55 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Oct 2015 04:55:12 +0000 (04:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=150695

Reviewed by Alex Christensen.

Source/WebCore:

Test: storage/indexeddb/modern/autoincrement-abort.html

* Modules/indexeddb/server/IDBBackingStore.h:
* Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp:
(WebCore::IDBServer::MemoryBackingStoreTransaction::addNewObjectStore):
(WebCore::IDBServer::MemoryBackingStoreTransaction::addExistingObjectStore):
(WebCore::IDBServer::MemoryBackingStoreTransaction::abort):
* Modules/indexeddb/server/MemoryBackingStoreTransaction.h:
* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::putRecord):
(WebCore::IDBServer::MemoryIDBBackingStore::generateKeyNumber):
* Modules/indexeddb/server/MemoryIDBBackingStore.h:
* Modules/indexeddb/server/MemoryObjectStore.h:
(WebCore::IDBServer::MemoryObjectStore::currentKeyGeneratorValue):
(WebCore::IDBServer::MemoryObjectStore::setKeyGeneratorValue):
* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):

LayoutTests:

* storage/indexeddb/modern/autoincrement-abort-expected.txt: Added.
* storage/indexeddb/modern/autoincrement-abort.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/modern/autoincrement-abort-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/autoincrement-abort.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp
Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp

index 3a6306576946a19f0c7253d4d335f878896eded4..146b48e70b6ca9f3d57d3b0b2f02b992c121f13c 100644 (file)
@@ -1,3 +1,13 @@
+2015-10-29  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: autoIncrement support.
+        https://bugs.webkit.org/show_bug.cgi?id=150695
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/modern/autoincrement-abort-expected.txt: Added.
+        * storage/indexeddb/modern/autoincrement-abort.html: Added.
+
 2015-10-29  Michael Saboff  <msaboff@apple.com>
 
         Crash making a tail call from a getter to a host function
diff --git a/LayoutTests/storage/indexeddb/modern/autoincrement-abort-expected.txt b/LayoutTests/storage/indexeddb/modern/autoincrement-abort-expected.txt
new file mode 100644 (file)
index 0000000..64f0f34
--- /dev/null
@@ -0,0 +1,32 @@
+ALERT: Initial upgrade needed: Old version - 0 New version - 1
+ALERT: Initial upgrade versionchange transaction complete
+ALERT: Opening readwrite transaction to bump the key generator, but it will be aborted
+ALERT: Key used for put was 1
+ALERT: Key used for put was 2
+ALERT: Key used for put was 3
+ALERT: Key used for put was 4
+ALERT: Key used for put was 5
+ALERT: Key used for put was 6
+ALERT: readwrite transaction abort
+ALERT: Opening readwrite transaction to make sure the key generator had successfully reverted
+ALERT: Key used for put was 1
+ALERT: Key used for put was 2
+ALERT: Key used for put was 3
+ALERT: Key used for put was 4
+ALERT: Key used for put was 5
+ALERT: Key used for put was 6
+ALERT: readwrite transaction complete
+ALERT: Opening readwrite transaction to make sure the key generator picks up where it should've left off
+ALERT: Key used for put was 7
+ALERT: Key used for put was 8
+ALERT: Key used for put was 9
+ALERT: Key used for put was 10
+ALERT: Key used for put was 11
+ALERT: Key used for put was 12
+ALERT: readwrite transaction complete
+ALERT: Done
+This test creates a new database with an objectstore that autoincrements.
+It then puts some things in that object store, checking the keys that were used.
+But it then aborts that transaction.
+Then it opens a new one and puts something in it, double checking that the key generator was reverted when the above transaction was aborted.
+
diff --git a/LayoutTests/storage/indexeddb/modern/autoincrement-abort.html b/LayoutTests/storage/indexeddb/modern/autoincrement-abort.html
new file mode 100644 (file)
index 0000000..73cb8c2
--- /dev/null
@@ -0,0 +1,159 @@
+This test creates a new database with an objectstore that autoincrements.<br>
+It then puts some things in that object store, checking the keys that were used.<br>
+But it then aborts that transaction.<br>
+Then it opens a new one and puts something in it, double checking that the key generator was reverted when the above transaction was aborted.<br>
+<script>
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert("Done");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open("AutoincrementAbortDatabase", 1);
+var database;
+
+createRequest.onupgradeneeded = function(event) {
+    alert("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    database = event.target.result;
+    var objectStore = database.createObjectStore('TestObjectStore', { autoIncrement: true });
+    
+    versionTransaction.onabort = function(event) {
+        alert("Initial upgrade versionchange transaction unexpected abort");
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert("Initial upgrade versionchange transaction complete");
+        continueTest1();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert("Initial upgrade versionchange transaction unexpected error" + event);
+        done();
+    }
+}
+
+function putChecker(event) {
+    alert("Key used for put was " + event.target.result);
+}
+
+function continueTest1()
+{
+    alert("Opening readwrite transaction to bump the key generator, but it will be aborted");
+    var transaction = database.transaction('TestObjectStore', "readwrite");
+    var objectStore = transaction.objectStore('TestObjectStore');
+    
+    var request = objectStore.put("bar1");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar2");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar3");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar4");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar5");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar6");
+    request.onsuccess = function(event) {
+        putChecker(event);
+        transaction.abort();
+    }
+    
+    transaction.onabort = function(event) {
+        alert("readwrite transaction abort");
+        continueTest2();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert("readwrite transaction unexpected complete");
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert("readwrite transaction unexpected error");
+        done();
+    }
+}
+
+function continueTest2()
+{
+    alert("Opening readwrite transaction to make sure the key generator had successfully reverted");
+    
+    var transaction = database.transaction('TestObjectStore', "readwrite");
+    var objectStore = transaction.objectStore('TestObjectStore');
+
+    var request = objectStore.put("bar1");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar2");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar3");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar4");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar5");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar6");
+    request.onsuccess = putChecker;
+
+    transaction.onabort = function(event) {
+        alert("readwrite transaction unexpected abort");
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert("readwrite transaction complete");
+        continueTest3();
+    }
+
+    transaction.onerror = function(event) {
+        alert("readwrite transaction unexpected error");
+        done();
+    }
+}
+
+function continueTest3()
+{
+    alert("Opening readwrite transaction to make sure the key generator picks up where it should've left off");
+    
+    var transaction = database.transaction('TestObjectStore', "readwrite");
+    var objectStore = transaction.objectStore('TestObjectStore');
+
+    var request = objectStore.put("bar1");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar2");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar3");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar4");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar5");
+    request.onsuccess = putChecker;
+    var request = objectStore.put("bar6");
+    request.onsuccess = putChecker;
+
+    transaction.onabort = function(event) {
+        alert("readwrite transaction unexpected abort");
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert("readwrite transaction complete");
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert("readwrite transaction unexpected error");
+        done();
+    }
+}
+
+</script>
index bfae028fa0073b22433168a0765b40ca43406a92..8588f0e3c9130003846be3837a6cc3ccc7b076ae 100644 (file)
@@ -1,3 +1,28 @@
+2015-10-29  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: autoIncrement support.
+        https://bugs.webkit.org/show_bug.cgi?id=150695
+
+        Reviewed by Alex Christensen.
+
+        Test: storage/indexeddb/modern/autoincrement-abort.html
+
+        * Modules/indexeddb/server/IDBBackingStore.h:
+        * Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp:
+        (WebCore::IDBServer::MemoryBackingStoreTransaction::addNewObjectStore):
+        (WebCore::IDBServer::MemoryBackingStoreTransaction::addExistingObjectStore):
+        (WebCore::IDBServer::MemoryBackingStoreTransaction::abort):
+        * Modules/indexeddb/server/MemoryBackingStoreTransaction.h:
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::putRecord):
+        (WebCore::IDBServer::MemoryIDBBackingStore::generateKeyNumber):
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+        * Modules/indexeddb/server/MemoryObjectStore.h:
+        (WebCore::IDBServer::MemoryObjectStore::currentKeyGeneratorValue):
+        (WebCore::IDBServer::MemoryObjectStore::setKeyGeneratorValue):
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):
+
 2015-10-29  Alex Christensen  <achristensen@webkit.org>
 
         Make WebCore a framework in Mac CMake build
index 830c214e50a6bfebc2f73922f84226db3d31fd8f..7ec58f286b6c00a81c2b50016d94d3531e29c3d9 100644 (file)
@@ -57,6 +57,8 @@ public:
     virtual IDBError deleteRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&) = 0;
     virtual IDBError putRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const ThreadSafeDataBuffer& value) = 0;
     virtual IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, ThreadSafeDataBuffer& outValue) = 0;
+    virtual IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) = 0;
+
 };
 
 } // namespace IDBServer
index dc3b6e9f256efc099e28db9ced4888d55d58382a..feaafa32ad45706725d5d28ced128ec3afb77a01 100644 (file)
@@ -60,12 +60,9 @@ void MemoryBackingStoreTransaction::addNewObjectStore(MemoryObjectStore& objectS
     LOG(IndexedDB, "MemoryBackingStoreTransaction::addNewObjectStore()");
 
     ASSERT(isVersionChange());
-
-    ASSERT(!m_objectStores.contains(&objectStore));
-    m_objectStores.add(&objectStore);
     m_versionChangeAddedObjectStores.add(&objectStore);
 
-    objectStore.writeTransactionStarted(*this);
+    addExistingObjectStore(objectStore);
 }
 
 void MemoryBackingStoreTransaction::addExistingObjectStore(MemoryObjectStore& objectStore)
@@ -78,6 +75,8 @@ void MemoryBackingStoreTransaction::addExistingObjectStore(MemoryObjectStore& ob
     m_objectStores.add(&objectStore);
 
     objectStore.writeTransactionStarted(*this);
+
+    m_originalKeyGenerators.add(&objectStore, objectStore.currentKeyGeneratorValue());
 }
 
 void MemoryBackingStoreTransaction::objectStoreDeleted(std::unique_ptr<MemoryObjectStore> objectStore)
@@ -136,6 +135,9 @@ void MemoryBackingStoreTransaction::abort()
     }
 
     for (auto objectStore : m_objectStores) {
+        ASSERT(m_originalKeyGenerators.contains(objectStore));
+        objectStore->setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
+
         auto keyValueMap = m_originalValues.get(objectStore);
         if (!keyValueMap)
             continue;
@@ -148,7 +150,6 @@ void MemoryBackingStoreTransaction::abort()
         m_originalValues.remove(objectStore);
     }
 
-
     finish();
 
     for (auto objectStore : m_versionChangeAddedObjectStores)
index b7977cd8516ec2778305b6a845004463e6b37d99..58ca5de213a179a717877190c93a32baccb467b4 100644 (file)
@@ -79,6 +79,7 @@ private:
     HashSet<MemoryObjectStore*> m_objectStores;
     HashSet<MemoryObjectStore*> m_versionChangeAddedObjectStores;
 
+    HashMap<MemoryObjectStore*, uint64_t> m_originalKeyGenerators;
     HashMap<String, std::unique_ptr<MemoryObjectStore>> m_deletedObjectStores;
     HashMap<MemoryObjectStore*, std::unique_ptr<KeyValueMap>> m_originalValues;
 
index 19131e7779b14cfb14916f769c037423c36cedfc..5b1f5dc94aa61fa1d097c8a4c37628841e3b26af 100644 (file)
@@ -211,7 +211,7 @@ IDBError MemoryIDBBackingStore::putRecord(const IDBResourceIdentifier& transacti
 
     auto transaction = m_transactions.get(transactionIdentifier);
     if (!transaction)
-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to get record"));
+        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to put record"));
 
     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
     if (!objectStore)
@@ -238,6 +238,22 @@ IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transacti
     return IDBError();
 }
 
+IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber)
+{
+    LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber");
+    ASSERT(objectStoreIdentifier);
+    ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
+    ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
+
+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
+    RELEASE_ASSERT(objectStore);
+
+    keyNumber = objectStore->currentKeyGeneratorValue();
+    objectStore->setKeyGeneratorValue(keyNumber + 1);
+
+    return IDBError();
+}
+
 void MemoryIDBBackingStore::registerObjectStore(std::unique_ptr<MemoryObjectStore>&& objectStore)
 {
     ASSERT(objectStore);
index 9d692f5a42ccd34358d4862d8e3dad6292b25ea3..eee839739d8653030893b038e2f6d751f3ab25ca 100644 (file)
@@ -58,6 +58,7 @@ public:
     virtual IDBError deleteRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&) override final;
     virtual IDBError putRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const ThreadSafeDataBuffer& value) override final;
     virtual IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, ThreadSafeDataBuffer& outValue) override final;
+    virtual IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) override final;
 
     void removeObjectStoreForVersionChangeAbort(MemoryObjectStore&);
     void restoreObjectStoreForVersionChangeAbort(std::unique_ptr<MemoryObjectStore>&&);
index c246ab4f0062a7508d511c6119c9c26e91e6014f..6be196ef9655d89a5d6ffc2a92d9ac4918f3c741 100644 (file)
@@ -60,6 +60,9 @@ public:
 
     void setKeyValue(const IDBKeyData&, const ThreadSafeDataBuffer& value);
 
+    uint64_t currentKeyGeneratorValue() const { return m_keyGeneratorValue; }
+    void setKeyGeneratorValue(uint64_t value) { m_keyGeneratorValue = value; }
+
     ThreadSafeDataBuffer valueForKey(const IDBKeyData&) const;
 
     const IDBObjectStoreInfo& info() const { return m_info; }
@@ -70,6 +73,7 @@ private:
     IDBObjectStoreInfo m_info;
 
     MemoryBackingStoreTransaction* m_writeTransaction { nullptr };
+    uint64_t m_keyGeneratorValue { 1 };
 
     std::unique_ptr<KeyValueMap> m_keyValueStore;
     std::unique_ptr<std::set<IDBKeyData>> m_orderedKeys;
index 37b2253b77be954205c011de192d95f16d1b0f2a..e1523bdad4c227f6f04aac557c0d6cea2fd60156 100644 (file)
@@ -313,6 +313,7 @@ void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBRe
     ASSERT(m_backingStore);
     ASSERT(objectStoreIdentifier);
 
+    bool keyWasGenerated = false;
     IDBKeyData usedKey;
     IDBError error;
 
@@ -324,13 +325,17 @@ void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBRe
     }
 
     if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
-        // FIXME: This is where generated key support goes
-        error = IDBError(IDBExceptionCode::Unknown, ASCIILiteral("Key generators not supported yet"));
-        m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
-        return;
-    }
-
-    usedKey = keyData;
+        uint64_t keyNumber;
+        error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
+        if (!error.isNull()) {
+            m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
+            return;
+        }
+        
+        usedKey.setNumberValue(keyNumber);
+        keyWasGenerated = true;
+    } else
+        usedKey = keyData;
 
     if (overwriteMode == IndexedDB::ObjectStoreOverwriteMode::NoOverwrite) {
         bool keyExists;