Changeset 87508 in webkit


Ignore:
Timestamp:
May 27, 2011 7:02:26 AM (13 years ago)
Author:
hans@chromium.org
Message:

2011-05-27 Hans Wennborg <hans@chromium.org>

Reviewed by Tony Gentilcore.

IndexedDB: Support mutating cursors on top of LevelDB
https://bugs.webkit.org/show_bug.cgi?id=61615

New test for adding new entries to an objecet store while running a
cursor over it.

  • storage/indexeddb/mutating-cursor-expected.txt: Added.
  • storage/indexeddb/mutating-cursor.html: Added.

2011-05-27 Hans Wennborg <hans@chromium.org>

Reviewed by Tony Gentilcore.

IndexedDB: Support mutating cursors on top of LevelDB
https://bugs.webkit.org/show_bug.cgi?id=61615

We need to support the case where a new node is added to the tree in a
transaction after the TreeIterator has covered the whole tree.

Since this is done lazily, i.e. we set a flag that the tree might have
changed, and act upon it later, some members need to be mutable,
because we might need to re-seek the tree iterator in a const function.

Test: storage/indexeddb/mutating-cursor.html

storage/indexeddb/mozilla/cursor-mutation-objectstore-only.html (existing)

  • platform/leveldb/LevelDBTransaction.cpp: (WebCore::LevelDBTransaction::set): (WebCore::LevelDBTransaction::TreeIterator::reset): (WebCore::LevelDBTransaction::TreeIterator::~TreeIterator): (WebCore::LevelDBTransaction::TreeIterator::TreeIterator): (WebCore::LevelDBTransaction::TransactionIterator::TransactionIterator): (WebCore::LevelDBTransaction::TransactionIterator::~TransactionIterator): (WebCore::LevelDBTransaction::TransactionIterator::next): (WebCore::LevelDBTransaction::TransactionIterator::prev): (WebCore::LevelDBTransaction::TransactionIterator::key): (WebCore::LevelDBTransaction::TransactionIterator::value): (WebCore::LevelDBTransaction::TransactionIterator::treeChanged): (WebCore::LevelDBTransaction::TransactionIterator::refreshTreeIterator): (WebCore::LevelDBTransaction::registerIterator): (WebCore::LevelDBTransaction::unregisterIterator): (WebCore::LevelDBTransaction::notifyIteratorsOfTreeChange):
  • platform/leveldb/LevelDBTransaction.h:
  • storage/IDBFactoryBackendImpl.cpp: (WebCore::IDBFactoryBackendImpl::open):
  • storage/IDBLevelDBBackingStore.cpp: (WebCore::IDBLevelDBBackingStore::open):
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r87506 r87508  
     12011-05-27  Hans Wennborg  <hans@chromium.org>
     2
     3        Reviewed by Tony Gentilcore.
     4
     5        IndexedDB: Support mutating cursors on top of LevelDB
     6        https://bugs.webkit.org/show_bug.cgi?id=61615
     7
     8        New test for adding new entries to an objecet store while running a
     9        cursor over it.
     10
     11        * storage/indexeddb/mutating-cursor-expected.txt: Added.
     12        * storage/indexeddb/mutating-cursor.html: Added.
     13
    1142011-05-27  Csaba Osztrogonác  <ossy@webkit.org>
    215
  • trunk/Source/WebCore/ChangeLog

    r87507 r87508  
     12011-05-27  Hans Wennborg  <hans@chromium.org>
     2
     3        Reviewed by Tony Gentilcore.
     4
     5        IndexedDB: Support mutating cursors on top of LevelDB
     6        https://bugs.webkit.org/show_bug.cgi?id=61615
     7
     8        We need to support the case where a new node is added to the tree in a
     9        transaction after the TreeIterator has covered the whole tree.
     10
     11        Since this is done lazily, i.e. we set a flag that the tree might have
     12        changed, and act upon it later, some members need to be mutable,
     13        because we might need to re-seek the tree iterator in a const function.
     14
     15        Test: storage/indexeddb/mutating-cursor.html
     16              storage/indexeddb/mozilla/cursor-mutation-objectstore-only.html (existing)
     17
     18        * platform/leveldb/LevelDBTransaction.cpp:
     19        (WebCore::LevelDBTransaction::set):
     20        (WebCore::LevelDBTransaction::TreeIterator::reset):
     21        (WebCore::LevelDBTransaction::TreeIterator::~TreeIterator):
     22        (WebCore::LevelDBTransaction::TreeIterator::TreeIterator):
     23        (WebCore::LevelDBTransaction::TransactionIterator::TransactionIterator):
     24        (WebCore::LevelDBTransaction::TransactionIterator::~TransactionIterator):
     25        (WebCore::LevelDBTransaction::TransactionIterator::next):
     26        (WebCore::LevelDBTransaction::TransactionIterator::prev):
     27        (WebCore::LevelDBTransaction::TransactionIterator::key):
     28        (WebCore::LevelDBTransaction::TransactionIterator::value):
     29        (WebCore::LevelDBTransaction::TransactionIterator::treeChanged):
     30        (WebCore::LevelDBTransaction::TransactionIterator::refreshTreeIterator):
     31        (WebCore::LevelDBTransaction::registerIterator):
     32        (WebCore::LevelDBTransaction::unregisterIterator):
     33        (WebCore::LevelDBTransaction::notifyIteratorsOfTreeChange):
     34        * platform/leveldb/LevelDBTransaction.h:
     35        * storage/IDBFactoryBackendImpl.cpp:
     36        (WebCore::IDBFactoryBackendImpl::open):
     37        * storage/IDBLevelDBBackingStore.cpp:
     38        (WebCore::IDBLevelDBBackingStore::open):
     39
    1402011-05-27  Sujin Park  <sujjin.park@gmail.com>
    241
  • trunk/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp

    r87370 r87508  
    8888
    8989    if (newNode)
    90         resetIterators();
     90        notifyIteratorsOfTreeChange();
    9191    return true;
    9292}
     
    223223void LevelDBTransaction::TreeIterator::reset()
    224224{
    225     // FIXME: Be lazy: set a flag and do the actual reset next time we use the iterator.
    226     if (isValid()) {
    227         m_iterator.start_iter(*m_tree, m_key, TreeType::EQUAL);
    228         ASSERT(isValid());
    229     }
     225    ASSERT(isValid());
     226    m_iterator.start_iter(*m_tree, m_key, TreeType::EQUAL);
     227    ASSERT(isValid());
    230228}
    231229
    232230LevelDBTransaction::TreeIterator::~TreeIterator()
    233231{
    234     m_transaction->unregisterIterator(this);
    235232}
    236233
     
    239236    , m_transaction(transaction)
    240237{
    241     transaction->registerIterator(this);
    242238}
    243239
     
    254250    , m_current(0)
    255251    , m_direction(kForward)
    256 {
     252    , m_treeChanged(false)
     253{
     254    m_transaction->registerIterator(this);
     255}
     256
     257LevelDBTransaction::TransactionIterator::~TransactionIterator()
     258{
     259    m_transaction->unregisterIterator(this);
    257260}
    258261
     
    285288{
    286289    ASSERT(isValid());
     290    if (m_treeChanged)
     291        refreshTreeIterator();
    287292
    288293    if (m_direction != kForward) {
     
    308313{
    309314    ASSERT(isValid());
     315    if (m_treeChanged)
     316        refreshTreeIterator();
    310317
    311318    if (m_direction != kReverse) {
     
    337344{
    338345    ASSERT(isValid());
     346    if (m_treeChanged)
     347        refreshTreeIterator();
    339348    return m_current->key();
    340349}
     
    343352{
    344353    ASSERT(isValid());
     354    if (m_treeChanged)
     355        refreshTreeIterator();
    345356    return m_current->value();
     357}
     358
     359void LevelDBTransaction::TransactionIterator::treeChanged()
     360{
     361    m_treeChanged = true;
     362}
     363
     364void LevelDBTransaction::TransactionIterator::refreshTreeIterator() const
     365{
     366    ASSERT(m_treeChanged);
     367
     368    if (m_treeIterator->isValid()) {
     369        m_treeIterator->reset();
     370        return;
     371    }
     372
     373    if (m_dbIterator->isValid()) {
     374        ASSERT(!m_treeIterator->isValid());
     375
     376        // There could be new nodes in the tree that we should iterate over.
     377
     378        if (m_direction == kForward) {
     379            // Try to seek tree iterator to something greater than the db iterator.
     380            m_treeIterator->seek(m_dbIterator->key());
     381            if (m_treeIterator->isValid() && !m_comparator->compare(m_treeIterator->key(), m_dbIterator->key()))
     382                m_treeIterator->next(); // If equal, take another step so the tree iterator is strictly greater.
     383        } else {
     384            // If going backward, seek to a key less than the db iterator.
     385            ASSERT(m_direction == kReverse);
     386            m_treeIterator->seek(m_dbIterator->key());
     387            if (m_treeIterator->isValid())
     388                m_treeIterator->prev();
     389        }
     390    }
     391
     392    m_treeChanged = false;
    346393}
    347394
     
    403450}
    404451
    405 void LevelDBTransaction::registerIterator(TreeIterator* iterator)
    406 {
    407     ASSERT(!m_treeIterators.contains(iterator));
    408     m_treeIterators.add(iterator);
    409 }
    410 
    411 void LevelDBTransaction::unregisterIterator(TreeIterator* iterator)
    412 {
    413     ASSERT(m_treeIterators.contains(iterator));
    414     m_treeIterators.remove(iterator);
    415 }
    416 
    417 void LevelDBTransaction::resetIterators()
    418 {
    419     for (HashSet<TreeIterator*>::iterator i = m_treeIterators.begin(); i != m_treeIterators.end(); ++i) {
    420         TreeIterator* treeIterator = *i;
    421         treeIterator->reset();
     452void LevelDBTransaction::registerIterator(TransactionIterator* iterator)
     453{
     454    ASSERT(!m_iterators.contains(iterator));
     455    m_iterators.add(iterator);
     456}
     457
     458void LevelDBTransaction::unregisterIterator(TransactionIterator* iterator)
     459{
     460    ASSERT(m_iterators.contains(iterator));
     461    m_iterators.remove(iterator);
     462}
     463
     464void LevelDBTransaction::notifyIteratorsOfTreeChange()
     465{
     466    for (HashSet<TransactionIterator*>::iterator i = m_iterators.begin(); i != m_iterators.end(); ++i) {
     467        TransactionIterator* transactionIterator = *i;
     468        transactionIterator->treeChanged();
    422469    }
    423470}
  • trunk/Source/WebCore/platform/leveldb/LevelDBTransaction.h

    r87370 r87508  
    122122    class TransactionIterator : public LevelDBIterator {
    123123    public:
    124         ~TransactionIterator() { };
     124        ~TransactionIterator();
    125125        static PassOwnPtr<TransactionIterator> create(PassRefPtr<LevelDBTransaction>);
    126126
     
    132132        virtual LevelDBSlice key() const;
    133133        virtual LevelDBSlice value() const;
     134        void treeChanged();
    134135
    135136    private:
     
    138139        void setCurrentIteratorToSmallestKey();
    139140        void setCurrentIteratorToLargestKey();
     141        void refreshTreeIterator() const;
    140142
    141143        RefPtr<LevelDBTransaction> m_transaction;
    142144        const LevelDBComparator* m_comparator;
    143         OwnPtr<TreeIterator> m_treeIterator;
     145        mutable OwnPtr<TreeIterator> m_treeIterator;
    144146        OwnPtr<LevelDBIterator> m_dbIterator;
    145147        LevelDBIterator* m_current;
     
    150152        };
    151153        Direction m_direction;
     154        mutable bool m_treeChanged;
    152155    };
    153156
    154157    bool set(const LevelDBSlice& key, const Vector<char>& value, bool deleted);
    155158    void clearTree();
    156     void registerIterator(TreeIterator*);
    157     void unregisterIterator(TreeIterator*);
    158     void resetIterators();
     159    void registerIterator(TransactionIterator*);
     160    void unregisterIterator(TransactionIterator*);
     161    void notifyIteratorsOfTreeChange();
    159162
    160163    LevelDBDatabase* m_db;
     
    162165    TreeType m_tree;
    163166    bool m_finished;
    164     HashSet<TreeIterator*> m_treeIterators;
     167    HashSet<TransactionIterator*> m_iterators;
    165168};
    166169
Note: See TracChangeset for help on using the changeset viewer.