Changeset 120131 in webkit


Ignore:
Timestamp:
Jun 12, 2012 3:36:54 PM (12 years ago)
Author:
jsbell@chromium.org
Message:

IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
https://bugs.webkit.org/show_bug.cgi?id=83074

Reviewed by Tony Chang.

Source/WebCore:

We should be able to collect and close the leveldb backing store as soon as the database
connection is closed, but the IDBObjectStoreBackendImpl and IDBIndexBackendImpl were
holding RefPtrs, and those objects are kept alive by script references.

Replaced RefPtrs to the IDBBackingStore with pointers to the IDBDatabase. On the back end,
IDBDatabaseBackendImpl maintains a RefPtr to the IDBObjectStoreBackendImpl object, so
a raw pointer back is safe. On the front end, the IDBObjectStore maintains a RefPtr to
the IDBDatabase so script can navigate upwards. Ditto on both ends for the ObjectStore/Index
relationship. The frontend objects maintain RefPtrs to the backend objects, so the backend
objects and their owners are maintained as long as there's a script reference. To ensure
that all LevelDB objects are destructed in the right order, transactions indirectly track all
open cursors and ensure they are closed when the transaction finishes, and database closing
is explicitly prevented from occurring until transactions are complete.

Also made IDBDatabaseBackendImpl handle a null IDBFactoryBackendImpl pointer, for testing.

Tests: storage/indexeddb/database-close.html

storage/indexeddb/persistence.html
[Chromium] webkit_unit_tests --gtest_filter=IDBDatabaseBackendTest.BackingStoreRetention

  • Modules/indexeddb/IDBCursorBackendImpl.cpp:

(WebCore::IDBCursorBackendImpl::close): Release LevelDB resources when closed to allow backing store to close.

  • Modules/indexeddb/IDBCursorBackendImpl.h:

(WebCore):

  • Modules/indexeddb/IDBDatabase.cpp: Ensure connection close deferred until all transactions are finished.

(WebCore::IDBDatabase::transactionCreated): Accounting.
(WebCore::IDBDatabase::transactionFinished): Accounting.
(WebCore::IDBDatabase::close):
(WebCore):
(WebCore::IDBDatabase::closeConnection):

  • Modules/indexeddb/IDBDatabase.h:

(IDBDatabase):

  • Modules/indexeddb/IDBDatabaseBackendImpl.cpp: Track outstanding transactions for forced-close scenarios.

(WebCore::IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl):
(WebCore::IDBDatabaseBackendImpl::createObjectStore): Don't pass in backing store reference.
(WebCore::IDBDatabaseBackendImpl::setVersion): Use transaction() for consistent accounting.
(WebCore::IDBDatabaseBackendImpl::transactionFinished): Accounting.
(WebCore::IDBDatabaseBackendImpl::transaction): Accounting.
(WebCore::IDBDatabaseBackendImpl::close): Unregister from factory when last connection is closed.
(WebCore::IDBDatabaseBackendImpl::loadObjectStores): Don't pass in backing store reference.
(WebCore::IDBDatabaseBackendImpl::removeObjectStoreFromMap):

  • Modules/indexeddb/IDBDatabaseBackendImpl.h:

(WebCore):
(IDBDatabaseBackendImpl):

  • Modules/indexeddb/IDBFactoryBackendImpl.cpp:

(WebCore::IDBFactoryBackendImpl::deleteDatabase): Don't hang on to deleted databases eternally.

  • Modules/indexeddb/IDBFactoryBackendImpl.h: Backend map controls IDBDatabaseBackend lifetimes.

(IDBFactoryBackendImpl):

  • Modules/indexeddb/IDBIndexBackendImpl.cpp: Don't hold backing store references.

(WebCore::IDBIndexBackendImpl::IDBIndexBackendImpl):

  • Modules/indexeddb/IDBIndexBackendImpl.h:

(WebCore::IDBIndexBackendImpl::create):
(IDBIndexBackendImpl):
(WebCore::IDBIndexBackendImpl::backingStore):
(WebCore::IDBIndexBackendImpl::databaseId):

  • Modules/indexeddb/IDBObjectStoreBackendImpl.cpp: Don't hold backing store references.

(WebCore::IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl):
(WebCore::IDBObjectStoreBackendImpl::createIndex):
(WebCore::IDBObjectStoreBackendImpl::loadIndexes):

  • Modules/indexeddb/IDBObjectStoreBackendImpl.h:

(WebCore::IDBObjectStoreBackendImpl::create):
(IDBObjectStoreBackendImpl):
(WebCore::IDBObjectStoreBackendImpl::backingStore):
(WebCore::IDBObjectStoreBackendImpl::databaseId):

  • Modules/indexeddb/IDBRequest.cpp:

(WebCore::IDBRequest::onSuccess):

  • Modules/indexeddb/IDBTransaction.cpp:

(WebCore::IDBTransaction::IDBTransaction): For IDBDatabase accounting, allow ref during ctor.
(WebCore::IDBTransaction::onAbort): Accounting.
(WebCore::IDBTransaction::onComplete): Accounting.

  • Modules/indexeddb/IDBTransaction.h:

(WebCore::IDBTransaction::isVersionChange): Convenience function.
(IDBTransaction):

  • Modules/indexeddb/IDBTransactionBackendImpl.cpp:

(WebCore::IDBTransactionBackendImpl::abort): Cleanup ordering to allow backing store to close.
(WebCore::IDBTransactionBackendImpl::commit): Cleanup ordering to allow backing store to close.

Source/WebKit/chromium:

  • WebKit.gypi:
  • tests/IDBDatabaseBackendTest.cpp: Added.

(WebCore):
(WebCore::TEST):

LayoutTests:

The storage/indexeddb/persistence.html test verifies http://webkit.org/b/88788 which
was revealed by this patch set. The storage/indexeddb/database-close.html test verifies
the precise database connection closing semantics defined in the IDB spec.

  • storage/indexeddb/database-close-expected.txt: Added.
  • storage/indexeddb/database-close.html: Added.
  • storage/indexeddb/persistence-expected.txt: Added.
  • storage/indexeddb/persistence.html: Added.
  • storage/indexeddb/resources/database-close.js: Added.

(test):
(openConnection.request.onsuccess.request.onsuccess):
(openConnection.request.onsuccess):
(openConnection):
(openVersionChangeConnection.request2.onsuccess):
(openVersionChangeConnection):
(testClose.transactionCompleted):
(testClose.request.onsuccess):
(testClose):

  • storage/indexeddb/resources/persistence.js: Added.

(test):
(openAndChangeVersion.request.onsuccess.request.onsuccess.trans.oncomplete):
(openAndChangeVersion.request.onsuccess.request.onsuccess):
(openAndChangeVersion.request.onsuccess):

Location:
trunk
Files:
7 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r120126 r120131  
     12012-06-12  Joshua Bell  <jsbell@chromium.org>
     2
     3        IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
     4        https://bugs.webkit.org/show_bug.cgi?id=83074
     5
     6        Reviewed by Tony Chang.
     7
     8        The storage/indexeddb/persistence.html test verifies http://webkit.org/b/88788 which
     9        was revealed by this patch set. The storage/indexeddb/database-close.html test verifies
     10        the precise database connection closing semantics defined in the IDB spec.
     11
     12        * storage/indexeddb/database-close-expected.txt: Added.
     13        * storage/indexeddb/database-close.html: Added.
     14        * storage/indexeddb/persistence-expected.txt: Added.
     15        * storage/indexeddb/persistence.html: Added.
     16        * storage/indexeddb/resources/database-close.js: Added.
     17        (test):
     18        (openConnection.request.onsuccess.request.onsuccess):
     19        (openConnection.request.onsuccess):
     20        (openConnection):
     21        (openVersionChangeConnection.request2.onsuccess):
     22        (openVersionChangeConnection):
     23        (testClose.transactionCompleted):
     24        (testClose.request.onsuccess):
     25        (testClose):
     26        * storage/indexeddb/resources/persistence.js: Added.
     27        (test):
     28        (openAndChangeVersion.request.onsuccess.request.onsuccess.trans.oncomplete):
     29        (openAndChangeVersion.request.onsuccess.request.onsuccess):
     30        (openAndChangeVersion.request.onsuccess):
     31
    1322012-06-12  Csaba Osztrogonác  <ossy@webkit.org>
    233
  • trunk/Source/WebCore/ChangeLog

    r120129 r120131  
     12012-06-12  Joshua Bell  <jsbell@chromium.org>
     2
     3        IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
     4        https://bugs.webkit.org/show_bug.cgi?id=83074
     5
     6        Reviewed by Tony Chang.
     7
     8        We should be able to collect and close the leveldb backing store as soon as the database
     9        connection is closed, but the IDBObjectStoreBackendImpl and IDBIndexBackendImpl were
     10        holding RefPtrs, and those objects are kept alive by script references.
     11
     12        Replaced RefPtrs to the IDBBackingStore with pointers to the IDBDatabase. On the back end,
     13        IDBDatabaseBackendImpl maintains a RefPtr to the IDBObjectStoreBackendImpl object, so
     14        a raw pointer back is safe. On the front end, the IDBObjectStore maintains a RefPtr to
     15        the IDBDatabase so script can navigate upwards. Ditto on both ends for the ObjectStore/Index
     16        relationship. The frontend objects maintain RefPtrs to the backend objects, so the backend
     17        objects and their owners are maintained as long as there's a script reference. To ensure
     18        that all LevelDB objects are destructed in the right order, transactions indirectly track all
     19        open cursors and ensure they are closed when the transaction finishes, and database closing
     20        is explicitly prevented from occurring until transactions are complete.
     21
     22        Also made IDBDatabaseBackendImpl handle a null IDBFactoryBackendImpl pointer, for testing.
     23
     24        Tests: storage/indexeddb/database-close.html
     25               storage/indexeddb/persistence.html
     26               [Chromium] webkit_unit_tests --gtest_filter=IDBDatabaseBackendTest.BackingStoreRetention
     27
     28        * Modules/indexeddb/IDBCursorBackendImpl.cpp:
     29        (WebCore::IDBCursorBackendImpl::close): Release LevelDB resources when closed to allow backing store to close.
     30        * Modules/indexeddb/IDBCursorBackendImpl.h:
     31        (WebCore):
     32        * Modules/indexeddb/IDBDatabase.cpp: Ensure connection close deferred until all transactions are finished.
     33        (WebCore::IDBDatabase::transactionCreated): Accounting.
     34        (WebCore::IDBDatabase::transactionFinished): Accounting.
     35        (WebCore::IDBDatabase::close):
     36        (WebCore):
     37        (WebCore::IDBDatabase::closeConnection):
     38        * Modules/indexeddb/IDBDatabase.h:
     39        (IDBDatabase):
     40        * Modules/indexeddb/IDBDatabaseBackendImpl.cpp: Track outstanding transactions for forced-close scenarios.
     41        (WebCore::IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl):
     42        (WebCore::IDBDatabaseBackendImpl::createObjectStore): Don't pass in backing store reference.
     43        (WebCore::IDBDatabaseBackendImpl::setVersion): Use transaction() for consistent accounting.
     44        (WebCore::IDBDatabaseBackendImpl::transactionFinished): Accounting.
     45        (WebCore::IDBDatabaseBackendImpl::transaction): Accounting.
     46        (WebCore::IDBDatabaseBackendImpl::close): Unregister from factory when last connection is closed.
     47        (WebCore::IDBDatabaseBackendImpl::loadObjectStores): Don't pass in backing store reference.
     48        (WebCore::IDBDatabaseBackendImpl::removeObjectStoreFromMap):
     49        * Modules/indexeddb/IDBDatabaseBackendImpl.h:
     50        (WebCore):
     51        (IDBDatabaseBackendImpl):
     52        * Modules/indexeddb/IDBFactoryBackendImpl.cpp:
     53        (WebCore::IDBFactoryBackendImpl::deleteDatabase): Don't hang on to deleted databases eternally.
     54        * Modules/indexeddb/IDBFactoryBackendImpl.h: Backend map controls IDBDatabaseBackend lifetimes.
     55        (IDBFactoryBackendImpl):
     56        * Modules/indexeddb/IDBIndexBackendImpl.cpp: Don't hold backing store references.
     57        (WebCore::IDBIndexBackendImpl::IDBIndexBackendImpl):
     58        * Modules/indexeddb/IDBIndexBackendImpl.h:
     59        (WebCore::IDBIndexBackendImpl::create):
     60        (IDBIndexBackendImpl):
     61        (WebCore::IDBIndexBackendImpl::backingStore):
     62        (WebCore::IDBIndexBackendImpl::databaseId):
     63        * Modules/indexeddb/IDBObjectStoreBackendImpl.cpp: Don't hold backing store references.
     64        (WebCore::IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl):
     65        (WebCore::IDBObjectStoreBackendImpl::createIndex):
     66        (WebCore::IDBObjectStoreBackendImpl::loadIndexes):
     67        * Modules/indexeddb/IDBObjectStoreBackendImpl.h:
     68        (WebCore::IDBObjectStoreBackendImpl::create):
     69        (IDBObjectStoreBackendImpl):
     70        (WebCore::IDBObjectStoreBackendImpl::backingStore):
     71        (WebCore::IDBObjectStoreBackendImpl::databaseId):
     72        * Modules/indexeddb/IDBRequest.cpp:
     73        (WebCore::IDBRequest::onSuccess):
     74        * Modules/indexeddb/IDBTransaction.cpp:
     75        (WebCore::IDBTransaction::IDBTransaction): For IDBDatabase accounting, allow ref during ctor.
     76        (WebCore::IDBTransaction::onAbort): Accounting.
     77        (WebCore::IDBTransaction::onComplete): Accounting.
     78        * Modules/indexeddb/IDBTransaction.h:
     79        (WebCore::IDBTransaction::isVersionChange): Convenience function.
     80        (IDBTransaction):
     81        * Modules/indexeddb/IDBTransactionBackendImpl.cpp:
     82        (WebCore::IDBTransactionBackendImpl::abort): Cleanup ordering to allow backing store to close.
     83        (WebCore::IDBTransactionBackendImpl::commit): Cleanup ordering to allow backing store to close.
     84
    1852012-06-12  Adrienne Walker  <enne@google.com>
    286
  • trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp

    r120114 r120131  
    251251    if (m_cursor)
    252252        m_cursor->close();
     253    m_cursor.clear();
     254    m_savedCursor.clear();
    253255}
    254256
  • trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.h

    r115282 r120131  
    4343class IDBKeyRange;
    4444class IDBObjectStoreBackendInterface;
    45 class IDBBackingStore;
    4645class IDBTransactionBackendInterface;
    4746class SerializedScriptValue;
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp

    r119868 r120131  
    7474}
    7575
    76 void IDBDatabase::setVersionChangeTransaction(IDBTransaction* transaction)
    77 {
    78     ASSERT(!m_versionChangeTransaction);
    79     m_versionChangeTransaction = transaction;
    80 }
    81 
    82 void IDBDatabase::clearVersionChangeTransaction(IDBTransaction* transaction)
    83 {
    84     ASSERT_UNUSED(transaction, m_versionChangeTransaction == transaction);
    85     m_versionChangeTransaction = 0;
     76void IDBDatabase::transactionCreated(IDBTransaction* transaction)
     77{
     78    ASSERT(transaction);
     79    ASSERT(!m_transactions.contains(transaction));
     80    m_transactions.add(transaction);
     81
     82    if (transaction->isVersionChange()) {
     83        ASSERT(!m_versionChangeTransaction);
     84        m_versionChangeTransaction = transaction;
     85    }
     86}
     87
     88void IDBDatabase::transactionFinished(IDBTransaction* transaction)
     89{
     90    ASSERT(transaction);
     91    ASSERT(m_transactions.contains(transaction));
     92    m_transactions.remove(transaction);
     93
     94    if (transaction->isVersionChange()) {
     95        ASSERT(m_versionChangeTransaction == transaction);
     96        m_versionChangeTransaction = 0;
     97    }
     98
     99    if (m_closePending && m_transactions.isEmpty())
     100        closeConnection();
    86101}
    87102
     
    207222}
    208223
    209 
    210224void IDBDatabase::close()
    211225{
     
    214228
    215229    m_closePending = true;
     230
     231    if (m_transactions.isEmpty())
     232        closeConnection();
     233}
     234
     235void IDBDatabase::closeConnection()
     236{
     237    ASSERT(m_closePending);
     238    ASSERT(m_transactions.isEmpty());
     239
    216240    m_backend->close(m_databaseCallbacks);
    217241
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h

    r119868 r120131  
    5454    ~IDBDatabase();
    5555
    56     void setVersionChangeTransaction(IDBTransaction*);
    57     void clearVersionChangeTransaction(IDBTransaction*);
     56    void transactionCreated(IDBTransaction*);
     57    void transactionFinished(IDBTransaction*);
    5858
    5959    // Implement the IDL
     
    104104    virtual EventTargetData* ensureEventTargetData();
    105105
     106    void closeConnection();
     107
    106108    RefPtr<IDBDatabaseBackendInterface> m_backend;
    107109    RefPtr<IDBTransaction> m_versionChangeTransaction;
     110    HashSet<IDBTransaction*> m_transactions;
    108111
    109112    bool m_closePending;
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp

    r120114 r120131  
    127127IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl()
    128128{
    129     m_factory->removeIDBDatabaseBackend(m_identifier);
    130129}
    131130
     
    152151    }
    153152
    154     RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(m_backingStore.get(), m_id, name, keyPath, autoIncrement);
     153    RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(this, name, keyPath, autoIncrement);
    155154    ASSERT(objectStore->name() == name);
    156155
     
    237236
    238237    RefPtr<DOMStringList> objectStoreNames = DOMStringList::create();
     238    RefPtr<IDBTransactionBackendInterface> transaction = this->transaction(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, ec);
     239    ASSERT(!ec);
     240
    239241    RefPtr<IDBDatabaseBackendImpl> database = this;
    240     RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, this);
    241242    if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::setVersionInternal, database, version, callbacks, transaction),
    242243                                   createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_version))) {
     
    269270{
    270271    RefPtr<IDBTransactionBackendInterface> transaction = prpTransaction;
     272    ASSERT(m_transactions.contains(transaction.get()));
     273    m_transactions.remove(transaction.get());
    271274    if (transaction->mode() == IDBTransaction::VERSION_CHANGE) {
    272275        ASSERT(transaction.get() == m_runningVersionChangeTransaction.get());
     
    317320    }
    318321
    319     // FIXME: Return not allowed err if close has been called.
    320     return IDBTransactionBackendImpl::create(objectStoreNames, mode, this);
     322    RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStoreNames, mode, this);
     323    m_transactions.add(transaction.get());
     324    return transaction.release();
    321325}
    322326
     
    377381
    378382    processPendingCalls();
     383
     384    if (!m_databaseCallbacksSet.size()) {
     385        TransactionSet transactions(m_transactions);
     386        for (TransactionSet::const_iterator it = transactions.begin(); it != transactions.end(); ++it)
     387            (*it)->abort();
     388        ASSERT(m_transactions.isEmpty());
     389
     390        m_backingStore.clear();
     391        // This check should only be false in tests.
     392        if (m_factory)
     393            m_factory->removeIDBDatabaseBackend(m_identifier);
     394    }
    379395}
    380396
     
    392408
    393409    for (size_t i = 0; i < ids.size(); i++)
    394         m_objectStores.set(names[i], IDBObjectStoreBackendImpl::create(m_backingStore.get(), m_id, ids[i], names[i], keyPaths[i], autoIncrementFlags[i]));
    395 }
    396 
    397 void IDBDatabaseBackendImpl::removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore)
    398 {
     410        m_objectStores.set(names[i], IDBObjectStoreBackendImpl::create(this, ids[i], names[i], keyPaths[i], autoIncrementFlags[i]));
     411}
     412
     413void IDBDatabaseBackendImpl::removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> prpObjectStore)
     414{
     415    RefPtr<IDBObjectStoreBackendImpl> objectStore = prpObjectStore;
    399416    ASSERT(database->m_objectStores.contains(objectStore->name()));
    400417    database->m_objectStores.remove(objectStore->name());
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h

    r119868 r120131  
    4242class IDBFactoryBackendImpl;
    4343class IDBObjectStoreBackendImpl;
     44class IDBTransactionBackendInterface;
    4445class IDBTransactionCoordinator;
    4546
     
    104105    RefPtr<IDBTransactionBackendInterface> m_runningVersionChangeTransaction;
    105106
     107    typedef HashSet<IDBTransactionBackendInterface*> TransactionSet;
     108    TransactionSet m_transactions;
     109
    106110    class PendingSetVersionCall;
    107111    Deque<RefPtr<PendingSetVersionCall> > m_pendingSetVersionCalls;
  • trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp

    r117978 r120131  
    133133        m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
    134134        databaseBackend->deleteDatabase(callbacks);
     135        m_databaseBackendMap.remove(uniqueIdentifier);
    135136    } else
    136137        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
  • trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.h

    r117978 r120131  
    6969    void openInternal(const String& name, IDBCallbacks*, PassRefPtr<SecurityOrigin>, const String& dataDir);
    7070
    71     typedef HashMap<String, IDBDatabaseBackendImpl*> IDBDatabaseBackendMap;
     71    typedef HashMap<String, RefPtr<IDBDatabaseBackendImpl> > IDBDatabaseBackendMap;
    7272    IDBDatabaseBackendMap m_databaseBackendMap;
    7373
  • trunk/Source/WebCore/Modules/indexeddb/IDBIndexBackendImpl.cpp

    r119671 r120131  
    4242namespace WebCore {
    4343
    44 IDBIndexBackendImpl::IDBIndexBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, IDBObjectStoreBackendImpl* objectStoreBackend, int64_t id, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
    45     : m_backingStore(backingStore)
    46     , m_databaseId(databaseId)
     44IDBIndexBackendImpl::IDBIndexBackendImpl(const IDBDatabaseBackendImpl* database, IDBObjectStoreBackendImpl* objectStoreBackend, int64_t id, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
     45    : m_database(database)
    4746    , m_objectStoreBackend(objectStoreBackend)
    4847    , m_id(id)
     
    5453}
    5554
    56 IDBIndexBackendImpl::IDBIndexBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, IDBObjectStoreBackendImpl* objectStoreBackend, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
    57     : m_backingStore(backingStore)
    58     , m_databaseId(databaseId)
     55IDBIndexBackendImpl::IDBIndexBackendImpl(const IDBDatabaseBackendImpl* database, IDBObjectStoreBackendImpl* objectStoreBackend, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
     56    : m_database(database)
    5957    , m_objectStoreBackend(objectStoreBackend)
    6058    , m_id(InvalidId)
  • trunk/Source/WebCore/Modules/indexeddb/IDBIndexBackendImpl.h

    r119006 r120131  
    3030
    3131#include "IDBCursorBackendInterface.h"
     32#include "IDBDatabaseBackendImpl.h"
    3233#include "IDBIndexBackendInterface.h"
    3334#include "IDBKeyPath.h"
     
    4243class IDBIndexBackendImpl : public IDBIndexBackendInterface {
    4344public:
    44     static PassRefPtr<IDBIndexBackendImpl> create(IDBBackingStore* backingStore, int64_t databaseId, IDBObjectStoreBackendImpl* objectStoreBackend, int64_t id, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
     45    static PassRefPtr<IDBIndexBackendImpl> create(const IDBDatabaseBackendImpl* database, IDBObjectStoreBackendImpl* objectStoreBackend, int64_t id, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
    4546    {
    46         return adoptRef(new IDBIndexBackendImpl(backingStore, databaseId, objectStoreBackend, id, name, keyPath, unique, multiEntry));
     47        return adoptRef(new IDBIndexBackendImpl(database, objectStoreBackend, id, name, keyPath, unique, multiEntry));
    4748    }
    48     static PassRefPtr<IDBIndexBackendImpl> create(IDBBackingStore* backingStore, int64_t databaseId, IDBObjectStoreBackendImpl* objectStoreBackend, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
     49    static PassRefPtr<IDBIndexBackendImpl> create(const IDBDatabaseBackendImpl* database, IDBObjectStoreBackendImpl* objectStoreBackend, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
    4950    {
    50         return adoptRef(new IDBIndexBackendImpl(backingStore, databaseId, objectStoreBackend, name, keyPath, unique, multiEntry));
     51        return adoptRef(new IDBIndexBackendImpl(database, objectStoreBackend, name, keyPath, unique, multiEntry));
    5152    }
    5253    virtual ~IDBIndexBackendImpl();
     
    7576
    7677private:
    77     IDBIndexBackendImpl(IDBBackingStore*, int64_t databaseId, IDBObjectStoreBackendImpl*, int64_t id, const String& name, const IDBKeyPath&, bool unique, bool multiEntry);
    78     IDBIndexBackendImpl(IDBBackingStore*, int64_t databaseId, IDBObjectStoreBackendImpl*, const String& name, const IDBKeyPath&, bool unique, bool multiEntry);
     78    IDBIndexBackendImpl(const IDBDatabaseBackendImpl*, IDBObjectStoreBackendImpl*, int64_t id, const String& name, const IDBKeyPath&, bool unique, bool multiEntry);
     79    IDBIndexBackendImpl(const IDBDatabaseBackendImpl*, IDBObjectStoreBackendImpl*, const String& name, const IDBKeyPath&, bool unique, bool multiEntry);
    7980
    8081    static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBKeyRange>, unsigned short direction, IDBCursorBackendInterface::CursorType, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
     
    8384    static void getKeyInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>);
    8485
    85     PassRefPtr<IDBBackingStore> backingStore() const { return m_backingStore; }
    86     int64_t databaseId() const { return m_databaseId; }
    87 
    8886    static const int64_t InvalidId = 0;
    8987
    90     RefPtr<IDBBackingStore> m_backingStore;
     88    PassRefPtr<IDBBackingStore> backingStore() const { return m_database->backingStore(); }
     89    int64_t databaseId() const { return m_database->id(); }
    9190
    92     int64_t m_databaseId;
     91    const IDBDatabaseBackendImpl* m_database;
     92
    9393    IDBObjectStoreBackendImpl* m_objectStoreBackend;
    9494    int64_t m_id;
  • trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp

    r120114 r120131  
    5252}
    5353
    54 IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, int64_t id, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
    55     : m_backingStore(backingStore)
    56     , m_databaseId(databaseId)
     54IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl* database, int64_t id, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
     55    : m_database(database)
    5756    , m_id(id)
    5857    , m_name(name)
     
    6463}
    6564
    66 IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
    67     : m_backingStore(backingStore)
    68     , m_databaseId(databaseId)
     65IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl* database, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
     66    : m_database(database)
    6967    , m_id(InvalidId)
    7068    , m_name(name)
     
    485483    }
    486484
    487     RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(backingStore().get(), databaseId(), this, name, keyPath, unique, multiEntry);
     485    RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_database, this, name, keyPath, unique, multiEntry);
    488486    ASSERT(index->name() == name);
    489487
     
    632630
    633631    for (size_t i = 0; i < ids.size(); i++)
    634         m_indexes.set(names[i], IDBIndexBackendImpl::create(backingStore().get(), databaseId(), this, ids[i], names[i], keyPaths[i], uniqueFlags[i], multiEntryFlags[i]));
     632        m_indexes.set(names[i], IDBIndexBackendImpl::create(m_database, this, ids[i], names[i], keyPaths[i], uniqueFlags[i], multiEntryFlags[i]));
    635633}
    636634
  • trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.h

    r119006 r120131  
    2727#define IDBObjectStoreBackendImpl_h
    2828
     29#include "IDBDatabaseBackendImpl.h"
    2930#include "IDBKeyPath.h"
    3031#include "IDBObjectStoreBackendInterface.h"
     
    3637namespace WebCore {
    3738
    38 class IDBBackingStore;
    3939class IDBDatabaseBackendImpl;
    4040class IDBIndexBackendImpl;
     
    4444class IDBObjectStoreBackendImpl : public IDBObjectStoreBackendInterface {
    4545public:
    46     static PassRefPtr<IDBObjectStoreBackendImpl> create(IDBBackingStore* backingStore, int64_t databaseId, int64_t id, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
     46    static PassRefPtr<IDBObjectStoreBackendImpl> create(const IDBDatabaseBackendImpl* database, int64_t id, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
    4747    {
    48         return adoptRef(new IDBObjectStoreBackendImpl(backingStore, databaseId, id, name, keyPath, autoIncrement));
     48        return adoptRef(new IDBObjectStoreBackendImpl(database, id, name, keyPath, autoIncrement));
    4949    }
    50     static PassRefPtr<IDBObjectStoreBackendImpl> create(IDBBackingStore* backingStore, int64_t databaseId, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
     50    static PassRefPtr<IDBObjectStoreBackendImpl> create(const IDBDatabaseBackendImpl* database, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
    5151    {
    52         return adoptRef(new IDBObjectStoreBackendImpl(backingStore, databaseId, name, keyPath, autoIncrement));
     52        return adoptRef(new IDBObjectStoreBackendImpl(database, name, keyPath, autoIncrement));
    5353    }
    5454    virtual ~IDBObjectStoreBackendImpl();
     
    8383
    8484private:
    85     IDBObjectStoreBackendImpl(IDBBackingStore*, int64_t databaseId, int64_t id, const String& name, const IDBKeyPath&, bool autoIncrement);
    86     IDBObjectStoreBackendImpl(IDBBackingStore*, int64_t databaseId, const String& name, const IDBKeyPath&, bool autoIncrement);
     85    IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl*, int64_t databaseId, const String& name, const IDBKeyPath&, bool autoIncrement);
     86    IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl*, const String& name, const IDBKeyPath&, bool autoIncrement);
    8787
    8888    void loadIndexes();
     
    104104    static void revertAutoIncrementKeyCache(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>);
    105105
    106     PassRefPtr<IDBBackingStore> backingStore() const { return m_backingStore; }
    107     int64_t databaseId() const { return m_databaseId; }
     106    PassRefPtr<IDBBackingStore> backingStore() const { return m_database->backingStore(); }
     107    int64_t databaseId() const { return m_database->id(); }
    108108
    109     RefPtr<IDBBackingStore> m_backingStore;
    110 
    111     int64_t m_databaseId;
     109    const IDBDatabaseBackendImpl* m_database;
    112110    int64_t m_id;
    113111    String m_name;
  • trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp

    r119868 r120131  
    288288
    289289    ASSERT(m_source->type() == IDBAny::IDBDatabaseType);
    290     ASSERT(m_transaction->mode() == IDBTransaction::modeVersionChange());
    291     m_source->idbDatabase()->setVersionChangeTransaction(frontend.get());
     290    ASSERT(m_transaction->isVersionChange());
    292291
    293292    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction->backend());
  • trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp

    r119751 r120131  
    9090    ASSERT(m_backend);
    9191    IDBPendingTransactionMonitor::addPendingTransaction(m_backend.get());
     92    // We pass a reference of this object before it can be adopted.
     93    relaxAdoptionRequirement();
     94    m_database->transactionCreated(this);
    9295}
    9396
     
    231234    }
    232235
    233     if (m_mode == IDBTransaction::VERSION_CHANGE)
    234         m_database->clearVersionChangeTransaction(this);
    235236    closeOpenCursors();
     237    m_database->transactionFinished(this);
    236238
    237239    if (m_contextStopped || !scriptExecutionContext())
     
    244246{
    245247    ASSERT(!m_transactionFinished);
    246     if (m_mode == IDBTransaction::VERSION_CHANGE)
    247         m_database->clearVersionChangeTransaction(this);
    248248    closeOpenCursors();
     249    m_database->transactionFinished(this);
    249250
    250251    if (m_contextStopped || !scriptExecutionContext())
  • trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h

    r120114 r120131  
    6969    IDBTransactionBackendInterface* backend() const;
    7070    bool isFinished() const;
     71    bool isVersionChange() const { return m_mode == VERSION_CHANGE; }
    7172
     73    // Implement the IDBTransaction IDL
    7274    const String& mode() const;
    7375    bool isReadOnly() const { return m_mode == READ_ONLY; }
  • trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp

    r119751 r120131  
    121121    m_taskEventTimer.stop();
    122122
    123     closeOpenCursors();
    124123    if (wasRunning)
    125124        m_transaction->rollback();
     
    132131    }
    133132
    134     if (m_callbacks)
    135         m_callbacks->onAbort();
     133    // Backing store resources (held via cursors) must be released before script callbacks
     134    // are fired, as the script callbacks may release references and allow the backing store
     135    // itself to be released, and order is critical.
     136    closeOpenCursors();
     137    m_transaction = 0;
     138
     139    // Transactions must also be marked as completed before the front-end is notified, as
     140    // the transaction completion unblocks operations like closing connections.
    136141    m_database->transactionCoordinator()->didFinishTransaction(this);
    137142    ASSERT(!m_database->transactionCoordinator()->isActive(this));
    138143    m_database->transactionFinished(this);
     144
     145    if (m_callbacks)
     146        m_callbacks->onAbort();
     147
    139148    m_database = 0;
    140149}
     
    197206
    198207    m_state = Finished;
     208
     209    bool committed = m_transaction->commit();
     210
     211    // Backing store resources (held via cursors) must be released before script callbacks
     212    // are fired, as the script callbacks may release references and allow the backing store
     213    // itself to be released, and order is critical.
    199214    closeOpenCursors();
    200     if (m_transaction->commit())
     215    m_transaction = 0;
     216
     217    // Transactions must also be marked as completed before the front-end is notified, as
     218    // the transaction completion unblocks operations like closing connections.
     219    m_database->transactionCoordinator()->didFinishTransaction(this);
     220    m_database->transactionFinished(this);
     221
     222    if (committed)
    201223        m_callbacks->onComplete();
    202224    else
    203225        m_callbacks->onAbort();
    204     m_database->transactionCoordinator()->didFinishTransaction(this);
    205     m_database->transactionFinished(this);
     226
    206227    m_database = 0;
    207228}
  • trunk/Source/WebKit/chromium/ChangeLog

    r120128 r120131  
     12012-06-12  Joshua Bell  <jsbell@chromium.org>
     2
     3        IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
     4        https://bugs.webkit.org/show_bug.cgi?id=83074
     5
     6        Reviewed by Tony Chang.
     7
     8        * WebKit.gypi:
     9        * tests/IDBDatabaseBackendTest.cpp: Added.
     10        (WebCore):
     11        (WebCore::TEST):
     12
    1132012-06-12  Dana Jansens  <danakj@chromium.org>
    214
  • trunk/Source/WebKit/chromium/WebKit.gypi

    r119886 r120131  
    114114            'tests/IDBAbortOnCorruptTest.cpp',
    115115            'tests/IDBBindingUtilitiesTest.cpp',
     116            'tests/IDBDatabaseBackendTest.cpp',
    116117            'tests/IDBFakeBackingStore.h',
    117118            'tests/IDBKeyPathTest.cpp',
Note: See TracChangeset for help on using the changeset viewer.