Bug 83074 - IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
Summary: IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Joshua Bell
URL:
Keywords:
Depends on: 86652 86655
Blocks: 71491
  Show dependency treegraph
 
Reported: 2012-04-03 14:40 PDT by Joshua Bell
Modified: 2012-06-12 15:37 PDT (History)
5 users (show)

See Also:


Attachments
Patch (40.41 KB, patch)
2012-04-03 16:08 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (40.52 KB, patch)
2012-04-05 16:45 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (68.94 KB, patch)
2012-05-15 14:27 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (39.45 KB, patch)
2012-05-17 15:27 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (35.05 KB, patch)
2012-05-22 13:02 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (45.69 KB, patch)
2012-06-07 12:13 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (45.74 KB, patch)
2012-06-07 13:51 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch (45.38 KB, patch)
2012-06-07 14:05 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ec2-cr-linux-04 (466.41 KB, application/zip)
2012-06-07 20:03 PDT, WebKit Review Bot
no flags Details
Patch (57.11 KB, patch)
2012-06-11 13:09 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff
Patch for landing (56.23 KB, patch)
2012-06-12 14:22 PDT, Joshua Bell
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Joshua Bell 2012-04-03 14:40:32 PDT
IndexedDB: ObjectStore/Index shouldn't hold reference to backing store
Comment 1 Joshua Bell 2012-04-03 16:08:13 PDT
Created attachment 135444 [details]
Patch
Comment 2 Joshua Bell 2012-04-04 08:46:55 PDT
dgrogan@, can you take a look and see if this makes sense before I send it off for formal review? The WebCore ChangeLog comment includes my understanding of the object ownership graph.
Comment 3 David Grogan 2012-04-05 15:07:19 PDT
Comment on attachment 135444 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=135444&action=review

LGTM

I went through our dependency graph; it's amazing we haven't had more problems with leaks or use-after-frees.  Though I guess we have had quite a number.

> Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp:123
> +    if (m_factory)

Can you add a comment here saying that this check should only be triggered in tests?

> Source/WebKit/chromium/tests/IDBDatabaseBackendTest.cpp:42
> +class MockIDBBackingStore : public IDBBackingStore {

Some bike-shedding: Mock means that it is going to verify that some set of operations were called on it. This should be Fake or Stub.
Comment 4 Joshua Bell 2012-04-05 16:45:33 PDT
Created attachment 135936 [details]
Patch
Comment 5 Joshua Bell 2012-04-05 16:46:47 PDT
(In reply to comment #3)
> > Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp:123
> > +    if (m_factory)
> 
> Can you add a comment here saying that this check should only be triggered in tests?

Done.

> > Source/WebKit/chromium/tests/IDBDatabaseBackendTest.cpp:42
> > +class MockIDBBackingStore : public IDBBackingStore {
> 
> Some bike-shedding: Mock means that it is going to verify that some set of operations were called on it. This should be Fake or Stub.

Done.
Comment 6 Joshua Bell 2012-04-05 16:47:10 PDT
tony@ - would you take a look?
Comment 7 Joshua Bell 2012-04-05 16:50:08 PDT
Oh, and for the record: this refactor part of the work to enable the DB connection to be closed to unlock the backing store on disk so it can be deleted at the user's request, regardless of lingering object references on the JS side.
Comment 8 WebKit Review Bot 2012-04-06 12:07:05 PDT
Comment on attachment 135936 [details]
Patch

Clearing flags on attachment: 135936

Committed r113473: <http://trac.webkit.org/changeset/113473>
Comment 9 WebKit Review Bot 2012-04-06 12:07:09 PDT
All reviewed patches have been landed.  Closing bug.
Comment 10 Joshua Bell 2012-04-09 14:37:28 PDT
Reverted r113473 for reason:

Change does not handle cursor retention of LevelDB iterators

Committed r113622: <http://trac.webkit.org/changeset/113622>
Comment 11 Joshua Bell 2012-05-15 14:27:49 PDT
Created attachment 142055 [details]
Patch
Comment 12 Joshua Bell 2012-05-15 14:29:10 PDT
dgrogan@ - take a look at the latest patch

(It includes https://bugs.webkit.org/show_bug.cgi?id=86499 and requires https://chromiumcodereview.appspot.com/10382180 for the tests to pass in DRT)
Comment 13 David Grogan 2012-05-15 14:58:38 PDT
Comment on attachment 142055 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=142055&action=review

I'd break this up into 3-4 patches:
1. Already exists in https://bugs.webkit.org/show_bug.cgi?id=86499
2. Tracing stuff
3. Change instances of index->m_backingStore to index->backingStore() that returns m_backingStore, same with index->m_databaseID, and possibly the finished -> isFinished change.
4. The rest.

> Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp:391
> +        // This check should only be false in tests.

Thanks for this comment.

> Source/WebCore/Modules/indexeddb/IDBTracing.h:37
> +#define IDB_TRACE(a) TRACE_EVENT0("IndexedDB", (a)); LOG_ERROR((a));

Guessing this wasn't supposed to be included?

> Source/WebKit/chromium/tests/IDBDatabaseBackendTest.cpp:42
> +class FakeIDBBackingStore : public IDBBackingStore {

I will adapt, or just use, this for us in a webkit unit test I'm writing, thanks.
Comment 14 Joshua Bell 2012-05-15 15:05:40 PDT
(In reply to comment #13)
> (From update of attachment 142055 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=142055&action=review
> 
> I'd break this up into 3-4 patches:
> 1. Already exists in https://bugs.webkit.org/show_bug.cgi?id=86499
> 2. Tracing stuff

^^^ I wasn't actually going to include that in the final patch, it was just for understanding the code. Will remove it before really submitting for review.

> 3. Change instances of index->m_backingStore to index->backingStore() that returns m_backingStore, same with index->m_databaseID, and possibly the finished -> isFinished change.

Good idea.

> 4. The rest.
 
> > Source/WebCore/Modules/indexeddb/IDBTracing.h:37
> > +#define IDB_TRACE(a) TRACE_EVENT0("IndexedDB", (a)); LOG_ERROR((a));
> 
> Guessing this wasn't supposed to be included?

Right, just temporary. 

> > Source/WebKit/chromium/tests/IDBDatabaseBackendTest.cpp:42
> > +class FakeIDBBackingStore : public IDBBackingStore {
> 
> I will adapt, or just use, this for us in a webkit unit test I'm writing, thanks.

Cool!
Comment 15 Joshua Bell 2012-05-17 15:27:54 PDT
Created attachment 142568 [details]
Patch
Comment 16 Joshua Bell 2012-05-22 13:02:59 PDT
Created attachment 143351 [details]
Patch
Comment 17 David Grogan 2012-05-22 15:46:59 PDT
Comment on attachment 143351 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=143351&action=review

> Source/WebCore/Modules/indexeddb/IDBDatabase.cpp:232
> +        closeConnection();

Does this change behavior? Were there cases before where we closed while transactions were still running?  I see that this is one of the cases you want to test.  Perhaps before this patch there was an implicit mechanism that prevented a database from closing while there were still transactions?

> Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp:135
> +        m_databaseBackendMap.remove(uniqueIdentifier);

Out of scope for this patch, but it looks like if someone deletes a non-existing database we create it *on disk* and then delete it.  Is that true?

> Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.h:29
> +#include "IDBDatabaseBackendImpl.h"

I think you can get rid of this if you move the accessor methods to the cpp file.

> Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp:134
> +    // database to be fully close.

closeOpenCursors has to happen before transactionFinished to avoid the deletion order problem we had with the last similar patch, correct?

I don't understand why the location of the callbacks call matters, though. The script-supplied callback could call db.close()?  Why does it matter if that happens before or after the call to transactionFinished()?
Comment 18 Joshua Bell 2012-05-22 16:58:15 PDT
Comment on attachment 143351 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=143351&action=review

>> Source/WebCore/Modules/indexeddb/IDBDatabase.cpp:232
>> +        closeConnection();
> 
> Does this change behavior? Were there cases before where we closed while transactions were still running?  I see that this is one of the cases you want to test.  Perhaps before this patch there was an implicit mechanism that prevented a database from closing while there were still transactions?

Not processing the close until all transactions have finished is explicitly in the IDB spec. IIRC our previous behavior was that a close would end up aborting running transactions rather than waiting for them to finish, so this represents an intentional behavior change. (I need to add tests to verify that *was* the previous behavior, though.)

>> Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp:135
>> +        m_databaseBackendMap.remove(uniqueIdentifier);
> 
> Out of scope for this patch, but it looks like if someone deletes a non-existing database we create it *on disk* and then delete it.  Is that true?

I believe so. Go us. :)

>> Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp:134
>> +    // database to be fully close.
> 
> closeOpenCursors has to happen before transactionFinished to avoid the deletion order problem we had with the last similar patch, correct?
> 
> I don't understand why the location of the callbacks call matters, though. The script-supplied callback could call db.close()?  Why does it matter if that happens before or after the call to transactionFinished()?

Yes, and.... I'm not sure. In the diff it looks like an intentional change but I suspect it wasn't (i.e. some code was rearranged then re-ordered and that line's position changed *because* it didn't matter)

I definitely need to go over this with a fine toothed comb again and finish those tests before calling this ready.
Comment 19 David Grogan 2012-05-22 17:35:02 PDT
Comment on attachment 143351 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=143351&action=review

>>> Source/WebCore/Modules/indexeddb/IDBDatabase.cpp:232
>>> +        closeConnection();
>> 
>> Does this change behavior? Were there cases before where we closed while transactions were still running?  I see that this is one of the cases you want to test.  Perhaps before this patch there was an implicit mechanism that prevented a database from closing while there were still transactions?
> 
> Not processing the close until all transactions have finished is explicitly in the IDB spec. IIRC our previous behavior was that a close would end up aborting running transactions rather than waiting for them to finish, so this represents an intentional behavior change. (I need to add tests to verify that *was* the previous behavior, though.)

SG - I know it's in the spec, I should have mentioned that I like how it's now explicit in the code :)

>>> Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp:134
>>> +    // database to be fully close.
>> 
>> closeOpenCursors has to happen before transactionFinished to avoid the deletion order problem we had with the last similar patch, correct?
>> 
>> I don't understand why the location of the callbacks call matters, though. The script-supplied callback could call db.close()?  Why does it matter if that happens before or after the call to transactionFinished()?
> 
> Yes, and.... I'm not sure. In the diff it looks like an intentional change but I suspect it wasn't (i.e. some code was rearranged then re-ordered and that line's position changed *because* it didn't matter)
> 
> I definitely need to go over this with a fine toothed comb again and finish those tests before calling this ready.

Doesn't your comment refer to the order?  I guess I didn't understand what the comment was talking about, not only why it matters.
Comment 20 Joshua Bell 2012-05-22 17:43:08 PDT
Comment on attachment 143351 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=143351&action=review

>>>> Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp:134
>>>> +    // database to be fully close.
>>> 
>>> closeOpenCursors has to happen before transactionFinished to avoid the deletion order problem we had with the last similar patch, correct?
>>> 
>>> I don't understand why the location of the callbacks call matters, though. The script-supplied callback could call db.close()?  Why does it matter if that happens before or after the call to transactionFinished()?
>> 
>> Yes, and.... I'm not sure. In the diff it looks like an intentional change but I suspect it wasn't (i.e. some code was rearranged then re-ordered and that line's position changed *because* it didn't matter)
>> 
>> I definitely need to go over this with a fine toothed comb again and finish those tests before calling this ready.
> 
> Doesn't your comment refer to the order?  I guess I didn't understand what the comment was talking about, not only why it matters.

I believe the comment only applies to the closeOpenCursors() and m_transaction line which (as you mention) must occur first to address the deletion order problem. The m_database->transactionFinished(this); can probably move back down.
Comment 21 Joshua Bell 2012-06-07 12:13:37 PDT
Created attachment 146358 [details]
Patch
Comment 22 Joshua Bell 2012-06-07 13:51:14 PDT
Created attachment 146380 [details]
Patch
Comment 23 Joshua Bell 2012-06-07 14:05:38 PDT
Created attachment 146386 [details]
Patch
Comment 24 Joshua Bell 2012-06-07 14:08:10 PDT
(In reply to comment #23)
> Created an attachment (id=146386) [details]
> Patch

Sorry for the churn. Last patches include:

* Added layout test to verify behavior of closing databases (all transactions are allowed to complete first, and closing unblocks version changes and deletes)
* Rebase changes and tests
* Restore the ordering of m_database->transactionFinished(this); calls per discussion here
Comment 25 WebKit Review Bot 2012-06-07 20:02:54 PDT
Comment on attachment 146386 [details]
Patch

Attachment 146386 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/12921392

New failing tests:
http/tests/inspector/indexeddb/resources-panel.html
http/tests/inspector/indexeddb/database-data.html
storage/indexeddb/database-close.html
http/tests/inspector/indexeddb/database-structure.html
Comment 26 WebKit Review Bot 2012-06-07 20:03:01 PDT
Created attachment 146459 [details]
Archive of layout-test-results from ec2-cr-linux-04

The attached test failures were seen while running run-webkit-tests on the chromium-ews.
Bot: ec2-cr-linux-04  Port: <class 'webkitpy.common.config.ports.ChromiumXVFBPort'>  Platform: Linux-2.6.35-28-virtual-x86_64-with-Ubuntu-10.10-maverick
Comment 27 Joshua Bell 2012-06-11 13:09:36 PDT
Created attachment 146890 [details]
Patch
Comment 28 Joshua Bell 2012-06-11 13:12:00 PDT
This should be good to go except that it includes the fix in http://webkit.org/b/88788 as that is necessary for passing the tests. Once that has landed I'll rebase/re-up this patch.

r? anyone?
Comment 29 Build Bot 2012-06-11 13:28:27 PDT
Comment on attachment 146890 [details]
Patch

Attachment 146890 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/12941406
Comment 30 Joshua Bell 2012-06-12 13:52:41 PDT
(In reply to comment #29)
> (From update of attachment 146890 [details])
> Attachment 146890 [details] did not pass mac-ews (mac):
> Output: http://queues.webkit.org/results/12941406

Failure was in JSC binding for WebGL (JSOESTextureFloat) - unrelated.
Comment 31 Tony Chang 2012-06-12 14:15:49 PDT
Comment on attachment 146890 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=146890&action=review

> LayoutTests/storage/indexeddb/database-close-expected.txt:42
> +FAIL code should be 6. Was 11.
> +FAIL ename should be NotAllowedError. Was InvalidStateError.

These are expected failures, right?  You might want to add a FIXME to database-close.js about this.
Comment 32 Joshua Bell 2012-06-12 14:17:19 PDT
(In reply to comment #31)
> (From update of attachment 146890 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=146890&action=review
> 
> > LayoutTests/storage/indexeddb/database-close-expected.txt:42
> > +FAIL code should be 6. Was 11.
> > +FAIL ename should be NotAllowedError. Was InvalidStateError.
> 
> These are expected failures, right?  You might want to add a FIXME to database-close.js about this.

No, not expected - they're the result of another patch that just landed which changed the codes to match the spec. I just noticed these myself and am re-running/updating expectations.
Comment 33 Joshua Bell 2012-06-12 14:22:52 PDT
Created attachment 147160 [details]
Patch for landing
Comment 34 WebKit Review Bot 2012-06-12 15:37:10 PDT
Comment on attachment 147160 [details]
Patch for landing

Clearing flags on attachment: 147160

Committed r120131: <http://trac.webkit.org/changeset/120131>
Comment 35 WebKit Review Bot 2012-06-12 15:37:16 PDT
All reviewed patches have been landed.  Closing bug.