Title: [89948] trunk
Revision
89948
Author
[email protected]
Date
2011-06-28 12:19:33 -0700 (Tue, 28 Jun 2011)

Log Message

2011-06-28  Greg Simon  <[email protected]>

        Reviewed by Dimitri Glazkov.

        Update migration LayoutTest to include indexes and successful migration.
        https://bugs.webkit.org/show_bug.cgi?id=62780

        * storage/indexeddb/migrate-basics-expected.txt:
        * storage/indexeddb/migrate-basics.html:
2011-06-28  Greg Simon  <[email protected]>

        Reviewed by Dimitri Glazkov.

        Migrate SQLite backing store to LevelDB backing store for Indexeddb.
        https://bugs.webkit.org/show_bug.cgi?id=62780

        * storage/IDBFactoryBackendImpl.cpp:
        (WebCore::computeFileIdentifier):
        (WebCore::computeUniqueIdentifier):
        (WebCore::IDBFactoryBackendImpl::open):
        (WebCore::migrateObjectStores):
        (WebCore::IDBFactoryBackendImpl::migrateFromSQLiteToLevelDB):
        * storage/IDBLevelDBBackingStore.cpp:
        (WebCore::IDBLevelDBBackingStore::backingStoreExists):
        * storage/IDBLevelDBBackingStore.h:
        * storage/IDBObjectStoreBackendImpl.cpp:
        (WebCore::IDBObjectStoreBackendImpl::populateIndex):
        * storage/IDBObjectStoreBackendImpl.h:
        * storage/IDBSQLiteBackingStore.cpp:
        (WebCore::IDBSQLiteBackingStore::backingStoreExists):
        * storage/IDBSQLiteBackingStore.h:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (89947 => 89948)


--- trunk/LayoutTests/ChangeLog	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/LayoutTests/ChangeLog	2011-06-28 19:19:33 UTC (rev 89948)
@@ -1,3 +1,13 @@
+2011-06-28  Greg Simon  <[email protected]>
+
+        Reviewed by Dimitri Glazkov.
+
+        Update migration LayoutTest to include indexes and successful migration.
+        https://bugs.webkit.org/show_bug.cgi?id=62780
+
+        * storage/indexeddb/migrate-basics-expected.txt:
+        * storage/indexeddb/migrate-basics.html:
+
 2011-06-28  Gavin Barraclough  <[email protected]>
 
         Reviewed by Oliver Hunt.

Modified: trunk/LayoutTests/storage/indexeddb/migrate-basics-expected.txt (89947 => 89948)


--- trunk/LayoutTests/storage/indexeddb/migrate-basics-expected.txt	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/LayoutTests/storage/indexeddb/migrate-basics-expected.txt	2011-06-28 19:19:33 UTC (rev 89948)
@@ -27,9 +27,24 @@
 trans = db.transaction([], webkitIDBTransaction.READ_WRITE, 0)
 leveldbCheckPlainOldStore():
 store = trans.objectStore('MigrationPlainOldStore')
-FAIL store = trans.objectStore('MigrationPlainOldStore') threw exception Error: NOT_FOUND_ERR: DOM IDBDatabase Exception 3
 request = store.openCursor(keyRange)
-FAIL request = store.openCursor(keyRange) threw exception TypeError: Cannot call method 'openCursor' of undefined
+leveldbCheckPlainOldStoreCursorNext():
+PASS cursor.value.name == 'George' is true
+leveldbCheckPlainOldStoreCursorNext():
+leveldbCheckStoreWithKeyPath():
+store = trans.objectStore('MigrationStoreWithKeyPath')
+leveldbCheckStoreWithKeyPathCursorNext():
+PASS ((window.index = window.store.index('ExampleIndex')) != undefined) is true
+PASS (window.keyIndexCursor.key == 3) is true
+PASS cursor.value.name == 'Thomas' is true
+PASS cursor.value.id == '3' is true
+leveldbCheckStoreWithKeyPathCursorNext():
+leveldbCheckStoreWithAutoIncrement():
+store = trans.objectStore('MigrationStoreWithAutoIncrement')
+leveldbCheckStoreWithAutoIncrementCursorNext():
+PASS cursor.value.name == 'Lincoln' is true
+PASS cursor.value.number == '7012' is true
+leveldbCheckStoreWithAutoIncrementCursorNext():
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/storage/indexeddb/migrate-basics.html (89947 => 89948)


--- trunk/LayoutTests/storage/indexeddb/migrate-basics.html	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/LayoutTests/storage/indexeddb/migrate-basics.html	2011-06-28 19:19:33 UTC (rev 89948)
@@ -45,7 +45,6 @@
     window.trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
     window.index = evalAndLog("index = store.createIndex('ExampleIndex','id', false)");
 
-
     sqliteTestAddRecords1();
 }
 
@@ -151,6 +150,16 @@
         return;
     }
 
+    shouldBeTrue("((window.index = window.store.index('ExampleIndex')) != undefined)");
+    openKeyCursor = window.index.openKeyCursor();
+    openKeyCursor._onsuccess_ = leveldbCheckStoreWithKeyPathCursorNext2;
+    openKeyCursor._onerror_ = unexpectedErrorCallback;
+}
+
+function leveldbCheckStoreWithKeyPathCursorNext2()
+{
+    window.keyIndexCursor = event.target.result;
+    shouldBeTrue("(window.keyIndexCursor.key == 3)");
     shouldBeTrue("cursor.value.name == 'Thomas'");
     shouldBeTrue("cursor.value.id == '3'");
     cursor.continue();

Modified: trunk/Source/WebCore/ChangeLog (89947 => 89948)


--- trunk/Source/WebCore/ChangeLog	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/ChangeLog	2011-06-28 19:19:33 UTC (rev 89948)
@@ -1,3 +1,26 @@
+2011-06-28  Greg Simon  <[email protected]>
+
+        Reviewed by Dimitri Glazkov.
+
+        Migrate SQLite backing store to LevelDB backing store for Indexeddb.
+        https://bugs.webkit.org/show_bug.cgi?id=62780
+
+        * storage/IDBFactoryBackendImpl.cpp:
+        (WebCore::computeFileIdentifier):
+        (WebCore::computeUniqueIdentifier):
+        (WebCore::IDBFactoryBackendImpl::open):
+        (WebCore::migrateObjectStores):
+        (WebCore::IDBFactoryBackendImpl::migrateFromSQLiteToLevelDB):
+        * storage/IDBLevelDBBackingStore.cpp:
+        (WebCore::IDBLevelDBBackingStore::backingStoreExists):
+        * storage/IDBLevelDBBackingStore.h:
+        * storage/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::IDBObjectStoreBackendImpl::populateIndex):
+        * storage/IDBObjectStoreBackendImpl.h:
+        * storage/IDBSQLiteBackingStore.cpp:
+        (WebCore::IDBSQLiteBackingStore::backingStoreExists):
+        * storage/IDBSQLiteBackingStore.h:
+
 2011-06-28  Levi Weintraub  <[email protected]>
 
         Reviewed by Darin Adler.

Modified: trunk/Source/WebCore/storage/IDBFactoryBackendImpl.cpp (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBFactoryBackendImpl.cpp	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBFactoryBackendImpl.cpp	2011-06-28 19:19:33 UTC (rev 89948)
@@ -33,6 +33,7 @@
 #include "IDBDatabaseBackendImpl.h"
 #include "IDBDatabaseException.h"
 #include "IDBLevelDBBackingStore.h"
+#include "IDBObjectStoreBackendImpl.h"
 #include "IDBSQLiteBackingStore.h"
 #include "IDBTransactionCoordinator.h"
 #include "SecurityOrigin.h"
@@ -43,6 +44,16 @@
 
 namespace WebCore {
 
+static String computeFileIdentifier(SecurityOrigin* securityOrigin, IDBFactoryBackendInterface::BackingStoreType type)
+{
+    return securityOrigin->databaseIdentifier() + String::format("@%d", type);
+}
+
+static String computeUniqueIdentifier(const String& name, SecurityOrigin* securityOrigin, IDBFactoryBackendInterface::BackingStoreType type)
+{
+    return computeFileIdentifier(securityOrigin, type) + name;
+}
+
 IDBFactoryBackendImpl::IDBFactoryBackendImpl()
     : m_transactionCoordinator(IDBTransactionCoordinator::create())
 {
@@ -75,8 +86,8 @@
     if (backingStoreType == DefaultBackingStore)
         backingStoreType = SQLiteBackingStore; // FIXME: DefaultBackingStore is confusing; get rid of it.
 
-    const String fileIdentifier = securityOrigin->databaseIdentifier() + String::format("@%d", static_cast<int>(backingStoreType));
-    const String uniqueIdentifier = fileIdentifier + "@" + name;
+    const String fileIdentifier = computeFileIdentifier(securityOrigin.get(), backingStoreType);
+    const String uniqueIdentifier = computeUniqueIdentifier(name, securityOrigin.get(), backingStoreType);
 
     IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier);
     if (it != m_databaseBackendMap.end()) {
@@ -94,8 +105,13 @@
 
 #if ENABLE(LEVELDB)
         if (backingStoreType == LevelDBBackingStore) {
-            const bool hasSQLBackingStore = IDBSQLiteBackingStore::backingStoreExists(securityOrigin.get(), dataDir);
+            bool hasSQLBackingStore = IDBSQLiteBackingStore::backingStoreExists(securityOrigin.get(), name, dataDir);
 
+            // LayoutTests: SQLite backing store may not exist on disk but may exist in cache.
+            String cachedSqliteBackingStoreIdentifier = computeFileIdentifier(securityOrigin.get(), SQLiteBackingStore);
+            if (!hasSQLBackingStore && (m_backingStoreMap.end() != m_backingStoreMap.find(cachedSqliteBackingStoreIdentifier)))
+                hasSQLBackingStore = true;
+
             if (hasSQLBackingStore) {
                 bool migrationSucceeded = migrateFromSQLiteToLevelDB(name, securityOrigin.get(), dataDir, maximumSize);
                 (void)migrationSucceeded; // FIXME: When migration is actually implemented, we need error handling here.
@@ -120,9 +136,127 @@
     m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
 }
 
+#if ENABLE(LEVELDB)
+
+static bool migrateObjectStores(PassRefPtr<IDBBackingStore> fromBackingStore, int64_t fromDatabaseId, PassRefPtr<IDBBackingStore> toBackingStore, int64_t toDatabaseId)
+{
+    Vector<int64_t> fromObjStoreIds, toObjStoreIds;
+    Vector<String> fromObjStoreNames, toObjStoreNames;
+    Vector<String> fromKeyPaths, toKeyPaths;
+    Vector<bool> fromAutoIncrement, toAutoIncrement;
+
+    // Migrate objectStores. Check to see if the object store already exists in the target.
+    fromBackingStore->getObjectStores(fromDatabaseId, fromObjStoreIds, fromObjStoreNames, fromKeyPaths, fromAutoIncrement);
+
+    toBackingStore->getObjectStores(toDatabaseId, toObjStoreIds, toObjStoreNames, toKeyPaths, toAutoIncrement);
+
+    for (unsigned i = 0; i < fromObjStoreIds.size(); i++) {
+        if (toObjStoreNames.contains(fromObjStoreNames[i]))
+            continue;
+
+        int64_t assignedObjectStoreId = -1;
+
+        RefPtr<IDBBackingStore::Transaction> trans = toBackingStore->createTransaction();
+        trans->begin();
+
+        if (!toBackingStore->createObjectStore(toDatabaseId, fromObjStoreNames[i], fromKeyPaths[i], fromAutoIncrement[i], assignedObjectStoreId))
+            return false;
+
+        RefPtr<IDBBackingStore::Cursor> cursor = fromBackingStore->openObjectStoreCursor(fromDatabaseId, fromObjStoreIds[i], 0, IDBCursor::NEXT);
+        if (cursor) {
+            do {
+                RefPtr<IDBKey> key = cursor->key();
+                RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = toBackingStore->createInvalidRecordIdentifier();
+
+                if (!toBackingStore->putObjectStoreRecord(toDatabaseId, assignedObjectStoreId, *(key.get()), cursor->value(), recordIdentifier.get()))
+                    return false;
+
+            } while (cursor->continueFunction());
+        }
+
+        // Populate any/all indexes for this objectstore.
+        Vector<int64_t> idxIds;
+        Vector<String> idxNames;
+        Vector<String> idxKeyPaths;
+        Vector<bool> idxUnique;
+        fromBackingStore->getIndexes(fromDatabaseId, fromObjStoreIds[i], idxIds, idxNames, idxKeyPaths, idxUnique);
+        for (unsigned j = 0; j < idxIds.size(); j++) {
+            int64_t indexId = -1;
+
+            if (!toBackingStore->createIndex(toDatabaseId, assignedObjectStoreId, idxNames[j], idxKeyPaths[j], idxUnique[j], indexId))
+                return false;
+
+            if (!IDBObjectStoreBackendImpl::populateIndex(*toBackingStore, toDatabaseId, assignedObjectStoreId, indexId, fromKeyPaths[i]))
+                return false;
+        }
+
+        trans->commit();
+    }
+
+    return true;
+}
+#endif // #if ENABLE(LEVELDB)
+
 bool IDBFactoryBackendImpl::migrateFromSQLiteToLevelDB(const String& name, SecurityOrigin* securityOrigin, const String& dataDir, int64_t maximumSize)
 {
-    return false; // FIXME: To be implemented.
+#if ENABLE(LEVELDB)
+    String fromUniqueIdentifier = computeUniqueIdentifier(name, securityOrigin, SQLiteBackingStore);
+    String fromFileIdentifier = computeFileIdentifier(securityOrigin, SQLiteBackingStore);
+    String toUniqueIdentifier = computeUniqueIdentifier(name, securityOrigin, LevelDBBackingStore);
+    String toFileIdentifier = computeFileIdentifier(securityOrigin, LevelDBBackingStore);
+    RefPtr<IDBTransactionCoordinator> transactionCoordinator = IDBTransactionCoordinator::create();
+    RefPtr<IDBBackingStore> fromBackingStore;
+    RefPtr<IDBDatabaseBackendImpl> fromDatabaseBackend;
+    RefPtr<IDBBackingStore> toBackingStore;
+
+
+    // Open "From" backing store and backend. When running LayoutTests, the
+    // "from" database may be cached in this class instance, so look for it there first.
+    IDBBackingStoreMap::iterator it = m_backingStoreMap.find(fromFileIdentifier);
+    if (it != m_backingStoreMap.end())
+        fromBackingStore = it->second;
+    else
+        fromBackingStore = IDBSQLiteBackingStore::open(securityOrigin, dataDir, maximumSize, fromFileIdentifier, this);
+
+    if (!fromBackingStore)
+        return false;
+
+    IDBDatabaseBackendMap::iterator it2 = m_databaseBackendMap.find(fromUniqueIdentifier);
+    if (it2 != m_databaseBackendMap.end())
+        fromDatabaseBackend = it2->second;
+    else {
+        fromDatabaseBackend = IDBDatabaseBackendImpl::create(name, fromBackingStore.get(), transactionCoordinator.get(), this, fromUniqueIdentifier);
+        m_databaseBackendMap.set(fromUniqueIdentifier, fromDatabaseBackend.get());
+    }
+
+    if (!fromDatabaseBackend)
+        return false;
+
+    // Open "To" database. First find out if it already exists -- this will determine if
+    // it is safe to call IDBLevelDBBackingStore::extractIDBDatabaseMetaData.
+    it = m_backingStoreMap.find(toFileIdentifier);
+    if (it != m_backingStoreMap.end())
+        toBackingStore = it->second;
+    else
+        toBackingStore = IDBLevelDBBackingStore::open(securityOrigin, dataDir, maximumSize, toFileIdentifier, this);
+
+    if (!toBackingStore)
+        return false;
+
+
+    String toDatabaseName = fromDatabaseBackend->name();
+    String toDatabaseVersion = fromDatabaseBackend->version();
+    int64_t toDatabaseId = -1;
+
+    if (!toBackingStore->extractIDBDatabaseMetaData(toDatabaseName, toDatabaseVersion, toDatabaseId)) {
+        if (!toBackingStore->setIDBDatabaseMetaData(toDatabaseName, toDatabaseVersion, toDatabaseId, true))
+            return false;
+    }
+
+    return migrateObjectStores(fromBackingStore, fromDatabaseBackend->id(), toBackingStore, toDatabaseId);
+
+#endif // ENABLE(LEVELDB)
+    return false;
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp	2011-06-28 19:19:33 UTC (rev 89948)
@@ -1304,7 +1304,7 @@
     m_backingStore->m_currentTransaction.clear();
 }
 
-bool IDBLevelDBBackingStore::backingStoreExists(SecurityOrigin* securityOrigin, const String& pathBaseArg)
+bool IDBLevelDBBackingStore::backingStoreExists(SecurityOrigin* securityOrigin, const String&, const String& pathBaseArg)
 {
     String pathBase = pathBaseArg;
 
@@ -1314,11 +1314,8 @@
     // FIXME: We should eventually use the same LevelDB database for all origins.
     String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
 
-    // FIXME: It would be more thorough to open the database here but also more expensive.
-    if (fileExists(path+"/CURRENT"))
-        return true;
-
-    return false;
+    // FIXME: this is checking for presence of the domain, not the database itself
+    return fileExists(path+"/CURRENT");
 }
 
 // FIXME: deleteDatabase should be part of IDBBackingStore.

Modified: trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h	2011-06-28 19:19:33 UTC (rev 89948)
@@ -76,7 +76,7 @@
     virtual PassRefPtr<Transaction> createTransaction();
     virtual IDBFactoryBackendInterface::BackingStoreType backingStoreType() const { return IDBFactoryBackendInterface::LevelDBBackingStore; }
 
-    static bool backingStoreExists(SecurityOrigin*, const String& pathBase);
+    static bool backingStoreExists(SecurityOrigin*, const String& name, const String& pathBase);
 
 private:
     IDBLevelDBBackingStore(const String& identifier, IDBFactoryBackendImpl*, PassOwnPtr<LevelDBDatabase>);

Modified: trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp	2011-06-28 19:19:33 UTC (rev 89948)
@@ -375,7 +375,7 @@
 };
 }
 
-static bool populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
+bool IDBObjectStoreBackendImpl::populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
 {
     PopulateIndexCallback callback(backingStore, indexKeyPath, databaseId, objectStoreId, indexId);
     if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))

Modified: trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.h (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.h	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.h	2011-06-28 19:19:33 UTC (rev 89948)
@@ -77,6 +77,8 @@
 
     virtual void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&);
 
+    static bool populateIndex(IDBBackingStore&, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath);
+
 private:
     IDBObjectStoreBackendImpl(IDBBackingStore*, int64_t databaseId, int64_t id, const String& name, const String& keyPath, bool autoIncrement);
     IDBObjectStoreBackendImpl(IDBBackingStore*, int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement);

Modified: trunk/Source/WebCore/storage/IDBSQLiteBackingStore.cpp (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBSQLiteBackingStore.cpp	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBSQLiteBackingStore.cpp	2011-06-28 19:19:33 UTC (rev 89948)
@@ -991,18 +991,19 @@
     return cursor.release();
 }
 
-bool IDBSQLiteBackingStore::backingStoreExists(SecurityOrigin* securityOrigin, const String& pathBase)
+bool IDBSQLiteBackingStore::backingStoreExists(SecurityOrigin* securityOrigin, const String& name, const String& pathBase)
 {
     String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb");
-    if (!fileExists(path))
-        return false;
-
     SQLiteDatabase db;
     if (!db.open(path))
         return false;
 
-    db.close();
-    return true;
+    SQLiteStatement databaseQuery(db, "SELECT id, version FROM Databases WHERE name = ?");
+    if (databaseQuery.prepare() != SQLResultOk)
+        return false;
+
+    databaseQuery.bindText(1, name);
+    return (databaseQuery.step() == SQLResultRow);
 }
 
 namespace {

Modified: trunk/Source/WebCore/storage/IDBSQLiteBackingStore.h (89947 => 89948)


--- trunk/Source/WebCore/storage/IDBSQLiteBackingStore.h	2011-06-28 19:01:29 UTC (rev 89947)
+++ trunk/Source/WebCore/storage/IDBSQLiteBackingStore.h	2011-06-28 19:19:33 UTC (rev 89948)
@@ -71,7 +71,7 @@
     virtual PassRefPtr<Transaction> createTransaction();
     virtual IDBFactoryBackendInterface::BackingStoreType backingStoreType() const { return IDBFactoryBackendInterface::SQLiteBackingStore; }
 
-    static bool backingStoreExists(SecurityOrigin*, const String& pathBase);
+    static bool backingStoreExists(SecurityOrigin*, const String& name, const String& pathBase);
 
 private:
     IDBSQLiteBackingStore(const String& identifier, IDBFactoryBackendImpl*);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to