Changeset 92468 in webkit


Ignore:
Timestamp:
Aug 5, 2011 1:42:56 AM (13 years ago)
Author:
hans@chromium.org
Message:

IndexedDB: Stop using free-lists for database/object store/index ids.
https://bugs.webkit.org/show_bug.cgi?id=65678

Reviewed by Tony Chang.

Don't use free-lists for database/object store/index ids,
just assign increasing numbers.

It turns out that deleting an object store and creating a new one with
the same id would cause the delete markers from the old object store to
slow down lookups into the new one. Therefore we should generate
a new id every time. Running out of ids (64 bits for databases and
object stores, 32 bits for indices) is not realistic.

Also make functions that generate new ids report errors, and make the
callers of those functions check the return values.

We must still delete free-lists when deleting an object store, and we
must keep the code for encoding/decoding/comparison of free-list keys
since users might have them in their databases.

This is just a performance optimization, so no new tests.

  • storage/IDBLevelDBBackingStore.cpp:

(WebCore::getNewDatabaseId):
(WebCore::IDBLevelDBBackingStore::setIDBDatabaseMetaData):
(WebCore::getNewObjectStoreId):
(WebCore::IDBLevelDBBackingStore::createObjectStore):
(WebCore::IDBLevelDBBackingStore::deleteObjectStore):
(WebCore::getNewIndexId):
(WebCore::IDBLevelDBBackingStore::createIndex):
(WebCore::IDBLevelDBBackingStore::deleteIndex):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r92463 r92468  
     12011-08-04  Hans Wennborg  <hans@chromium.org>
     2
     3        IndexedDB: Stop using free-lists for database/object store/index ids.
     4        https://bugs.webkit.org/show_bug.cgi?id=65678
     5
     6        Reviewed by Tony Chang.
     7
     8        Don't use free-lists for database/object store/index ids,
     9        just assign increasing numbers.
     10
     11        It turns out that deleting an object store and creating a new one with
     12        the same id would cause the delete markers from the old object store to
     13        slow down lookups into the new one. Therefore we should generate
     14        a new id every time. Running out of ids (64 bits for databases and
     15        object stores, 32 bits for indices) is not realistic.
     16
     17        Also make functions that generate new ids report errors, and make the
     18        callers of those functions check the return values.
     19
     20        We must still delete free-lists when deleting an object store, and we
     21        must keep the code for encoding/decoding/comparison of free-list keys
     22        since users might have them in their databases.
     23
     24        This is just a performance optimization, so no new tests.
     25
     26        * storage/IDBLevelDBBackingStore.cpp:
     27        (WebCore::getNewDatabaseId):
     28        (WebCore::IDBLevelDBBackingStore::setIDBDatabaseMetaData):
     29        (WebCore::getNewObjectStoreId):
     30        (WebCore::IDBLevelDBBackingStore::createObjectStore):
     31        (WebCore::IDBLevelDBBackingStore::deleteObjectStore):
     32        (WebCore::getNewIndexId):
     33        (WebCore::IDBLevelDBBackingStore::createIndex):
     34        (WebCore::IDBLevelDBBackingStore::deleteIndex):
     35
    1362011-08-05  Roland Steiner  <rolandsteiner@chromium.org>
    237
  • trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp

    r92364 r92468  
    182182static int64_t getNewDatabaseId(LevelDBDatabase* db)
    183183{
    184     const Vector<char> freeListStartKey = DatabaseFreeListKey::encode(0);
    185     const Vector<char> freeListStopKey = DatabaseFreeListKey::encodeMaxKey();
    186 
    187     OwnPtr<LevelDBIterator> it = db->createIterator();
    188     for (it->seek(freeListStartKey); it->isValid() && compareKeys(it->key(), freeListStopKey) < 0; it->next()) {
    189         const char *p = it->key().begin();
    190         const char *limit = it->key().end();
    191 
    192         DatabaseFreeListKey freeListKey;
    193         p = DatabaseFreeListKey::decode(p, limit, &freeListKey);
    194         ASSERT(p);
    195 
    196         bool ok = db->remove(it->key());
    197         ASSERT_UNUSED(ok, ok);
    198 
    199         return freeListKey.databaseId();
    200     }
    201 
    202     // If we got here, there was no free-list.
    203184    int64_t maxDatabaseId = -1;
    204185    if (!getInt(db, MaxDatabaseIdKey::encode(), maxDatabaseId))
     
    208189
    209190    int64_t databaseId = maxDatabaseId + 1;
    210     bool ok = putInt(db, MaxDatabaseIdKey::encode(), databaseId);
    211     ASSERT_UNUSED(ok, ok);
     191    if (!putInt(db, MaxDatabaseIdKey::encode(), databaseId))
     192        return -1;
    212193
    213194    return databaseId;
    214 
    215195}
    216196
     
    219199    if (invalidRowId) {
    220200        rowId = getNewDatabaseId(m_db.get());
     201        if (rowId < 0)
     202            return false;
    221203
    222204        const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
     
    290272static int64_t getNewObjectStoreId(LevelDBTransaction* transaction, int64_t databaseId)
    291273{
    292     const Vector<char> freeListStartKey = ObjectStoreFreeListKey::encode(databaseId, 0);
    293     const Vector<char> freeListStopKey = ObjectStoreFreeListKey::encodeMaxKey(databaseId);
    294 
    295     OwnPtr<LevelDBIterator> it = transaction->createIterator();
    296     for (it->seek(freeListStartKey); it->isValid() && compareKeys(it->key(), freeListStopKey) < 0; it->next()) {
    297         const char* p = it->key().begin();
    298         const char* limit = it->key().end();
    299 
    300         ObjectStoreFreeListKey freeListKey;
    301         p = ObjectStoreFreeListKey::decode(p, limit, &freeListKey);
    302         ASSERT(p);
    303 
    304         bool ok = transaction->remove(it->key());
    305         ASSERT_UNUSED(ok, ok);
    306 
    307         return freeListKey.objectStoreId();
    308     }
    309 
    310274    int64_t maxObjectStoreId = -1;
    311275    const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::kMaxObjectStoreId);
     
    316280
    317281    int64_t objectStoreId = maxObjectStoreId + 1;
    318     bool ok = putInt(transaction, maxObjectStoreIdKey, objectStoreId);
    319     ASSERT_UNUSED(ok, ok);
     282    if (!putInt(transaction, maxObjectStoreIdKey, objectStoreId))
     283        return -1;
    320284
    321285    return objectStoreId;
     
    326290    ASSERT(m_currentTransaction);
    327291    int64_t objectStoreId = getNewObjectStoreId(m_currentTransaction.get(), databaseId);
     292    if (objectStoreId < 0)
     293        return false;
    328294
    329295    const Vector<char> nameKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0);
     
    403369        return; // FIXME: Report error.
    404370
    405     putString(m_currentTransaction.get(), ObjectStoreFreeListKey::encode(databaseId, objectStoreId), "");
    406371    m_currentTransaction->remove(ObjectStoreNamesKey::encode(databaseId, objectStoreName));
    407372
     
    642607static int64_t getNewIndexId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
    643608{
    644     const Vector<char> startKey = IndexFreeListKey::encode(databaseId, objectStoreId, 0);
    645     const Vector<char> stopKey = IndexFreeListKey::encodeMaxKey(databaseId, objectStoreId);
    646 
    647     OwnPtr<LevelDBIterator> it = transaction->createIterator();
    648     for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
    649         const char* p = it->key().begin();
    650         const char* limit = it->key().end();
    651 
    652         IndexFreeListKey freeListKey;
    653         p = IndexFreeListKey::decode(p, limit, &freeListKey);
    654         ASSERT(p);
    655 
    656         bool ok = transaction->remove(it->key());
    657         ASSERT_UNUSED(ok, ok);
    658 
    659         ASSERT(freeListKey.indexId() >= kMinimumIndexId);
    660         return freeListKey.indexId();
    661     }
    662 
    663609    int64_t maxIndexId = -1;
    664610    const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 5);
     
    669615
    670616    int64_t indexId = maxIndexId + 1;
    671     bool ok = putInt(transaction, maxIndexIdKey, indexId);
    672     if (!ok)
    673         return false;
     617    if (!putInt(transaction, maxIndexIdKey, indexId))
     618        return -1;
    674619
    675620    return indexId;
     
    680625    ASSERT(m_currentTransaction);
    681626    indexId = getNewIndexId(m_currentTransaction.get(), databaseId, objectStoreId);
     627    if (indexId < 0)
     628        return false;
    682629
    683630    const Vector<char> nameKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 0);
     
    731678
    732679    if (!deleteRange(m_currentTransaction.get(), indexDataStart, indexDataEnd)) {
    733         LOG_ERROR("Internal Indexed DB error.");
    734         return;
    735     }
    736 
    737     const Vector<char> freeListKey = IndexFreeListKey::encode(databaseId, objectStoreId, indexId);
    738     if (!putInt(m_currentTransaction.get(), freeListKey, 0)) {
    739680        LOG_ERROR("Internal Indexed DB error.");
    740681        return;
Note: See TracChangeset for help on using the changeset viewer.