Bug 767193 - FileHandles do not get GCed/removed when overwritten in indexeddb. r=bent
authorJan Varga <jan.varga@gmail.com>
Wed, 27 Jun 2012 05:14:53 +0200
changeset 97688 5cdbeae144058bfc99438bf33c515eb76ddbd408
parent 97687 be373f4b243feda9d4b2942c690b055611e635f0
child 97753 1a56f1f011c964815844ef8bdd9f313db20feebf
push id22992
push userJan.Varga@gmail.com
push dateWed, 27 Jun 2012 04:39:29 +0000
treeherdermozilla-central@5cdbeae14405 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs767193
milestone16.0a1
first release with
nightly linux32
5cdbeae14405 / 16.0a1 / 20120627030527 / files
nightly linux64
5cdbeae14405 / 16.0a1 / 20120627030527 / files
nightly mac
5cdbeae14405 / 16.0a1 / 20120627030527 / files
nightly win32
5cdbeae14405 / 16.0a1 / 20120627030527 / files
nightly win64
5cdbeae14405 / 16.0a1 / 20120627030527 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 767193 - FileHandles do not get GCed/removed when overwritten in indexeddb. r=bent
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/test/Makefile.in
dom/indexedDB/test/test_file_replace.html
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -179,19 +179,25 @@ IDBFactory::GetConnection(const nsAStrin
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, nsnull);
 
   nsCOMPtr<mozIStorageConnection> connection;
   rv = ss->OpenDatabaseWithVFS(dbFile, NS_LITERAL_CSTRING("quota"),
                                getter_AddRefs(connection));
   NS_ENSURE_SUCCESS(rv, nsnull);
 
-  // Turn on foreign key constraints!
+  // Turn on foreign key constraints and recursive triggers.
+  // The "INSERT OR REPLACE" statement doesn't fire the update trigger,
+  // instead it fires only the insert trigger. This confuses the update
+  // refcount function. This behavior changes with enabled recursive triggers,
+  // so the statement fires the delete trigger first and then the insert
+  // trigger.
   rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
-    "PRAGMA foreign_keys = ON;"
+    "PRAGMA foreign_keys = ON; "
+    "PRAGMA recursive_triggers = ON;"
   ));
   NS_ENSURE_SUCCESS(rv, nsnull);
 
   return connection.forget();
 }
 
 inline
 bool
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -46,16 +46,17 @@ TEST_FILES = \
   test_event_source.html \
   test_exceptions_in_success_events.html \
   test_file_array.html \
   test_file_cross_database_copying.html \
   test_file_delete.html \
   test_file_os_delete.html \
   test_file_put_get_object.html \
   test_file_put_get_values.html \
+  test_file_replace.html \
   test_file_resurrection_delete.html \
   test_file_resurrection_transaction_abort.html \
   test_file_sharing.html \
   test_file_transaction_abort.html \
   test_filehandle_serialization.html \
   test_filehandle_store_snapshot.html \
   test_getAll.html \
   test_global_data.html \
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_file_replace.html
@@ -0,0 +1,67 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+  function testSteps()
+  {
+    const name = window.location.pathname;
+    const description = "My Test Database";
+
+    const objectStoreName = "Blobs";
+
+    const blobData = { key: 42, blobs: [] };
+
+    for (let i = 0; i < 100; i++) {
+      blobData.blobs[i] = getRandomBlob(i);
+    }
+
+    let request = mozIndexedDB.open(name, 1, description);
+    request.onerror = errorHandler;
+    request.onupgradeneeded = grabEventAndContinueHandler;
+    request.onsuccess = grabEventAndContinueHandler;
+    let event = yield;
+
+    is(event.type, "upgradeneeded", "Got correct event type");
+
+    let db = event.target.result;
+    db.onerror = errorHandler;
+
+    let objectStore = db.createObjectStore(objectStoreName, { });
+
+    for (let i = 0; i < blobData.blobs.length; i++) {
+      objectStore.put(blobData.blobs[i], blobData.key);
+    }
+
+    event = yield;
+
+    is(event.type, "success", "Got correct event type");
+
+    for (let id = 1; id <= 100; id++) {
+      let refs = {};
+      let dbRefs = {};
+      let hasFileInfo = utils.getFileReferences(name, id, refs, dbRefs);
+      ok(hasFileInfo, "Has file info");
+      is(refs.value, 1, "Correct ref count");
+      is(dbRefs.value, id / 100 >> 0, "Correct db ref count");
+    }
+
+    finishTest();
+    yield;
+  }
+  </script>
+  <script type="text/javascript;version=1.7" src="file.js"></script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>