Bug 858680 - Part 4: Perform maintenance on databases while idle, r=janv.

--HG--
extra : rebase_source : b541f27d0a746949d721584dd061f499209cc05a
This commit is contained in:
Ben Turner 2015-05-04 22:56:47 -07:00
Родитель 805bc94273
Коммит 2e348da54f
6 изменённых файлов: 1672 добавлений и 84 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -96,4 +96,5 @@ LOCAL_INCLUDES += [
'/dom/workers',
'/ipc/glue',
'/xpcom/build',
'/xpcom/threads',
]

Просмотреть файл

@ -0,0 +1,136 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
let uri = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI("https://www.example.com", null, null);
let principal = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager).
getNoAppCodebasePrincipal(uri);
info("Setting permissions");
let permMgr =
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
permMgr.add(uri, "indexedDB", Ci.nsIPermissionManager.ALLOW_ACTION);
info("Setting idle preferences to prevent real 'idle-daily' notification");
let prefs =
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setIntPref("idle.lastDailyNotification", (Date.now() / 1000) - 10);
info("Activating real idle service");
do_get_idle();
info("Creating databases");
let quotaManager =
Cc["@mozilla.org/dom/quota/manager;1"].getService(Ci.nsIQuotaManager);
let dbCount = 0;
for (let persistence of ["persistent", "temporary", "default"]) {
for (let i = 1; i <= 5; i++) {
let dbName = "foo-" + i;
let dbPersistence = persistence;
let req = indexedDB.openForPrincipal(principal,
dbName,
{ version: 1,
storage: dbPersistence });
req.onerror = event => {
if (dbPersistence != "persistent") {
errorHandler(event);
return;
}
// Explicit persistence is currently blocked on mobile.
info("Failed to create persistent database '" + dbPersistence + "/" +
dbName + "', hopefully this is on mobile!");
event.preventDefault();
if (!(--dbCount)) {
continueToNextStep();
}
};
req.onupgradeneeded = event => {
let db = event.target.result;
let objectStore = db.createObjectStore("foo");
// Add lots of data...
for (let j = 0; j < 100; j++) {
objectStore.add("abcdefghijklmnopqrstuvwxyz0123456789", j);
}
// And then clear it so that maintenance has some space to reclaim.
objectStore.clear();
};
req.onsuccess = event => {
let db = event.target.result;
ok(db, "Created database '" + dbPersistence + "/" + dbName + "'");
db.close();
if (!(--dbCount)) {
continueToNextStep();
}
};
dbCount++;
}
}
yield undefined;
info("Getting usage before maintenance");
let usageBeforeMaintenance;
quotaManager.getUsageForURI(uri, (url, usage) => {
ok(usage > 0, "Usage is non-zero");
usageBeforeMaintenance = usage;
continueToNextStep();
});
yield undefined;
info("Sending fake 'idle-daily' notification to QuotaManager");
let observer = quotaManager.QueryInterface(Ci.nsIObserver);
observer.observe(null, "idle-daily", "");
info("Waiting for maintenance to start");
// This time is totally arbitrary. Most likely directory scanning will have
// completed, QuotaManager locks will be acquired, and maintenance tasks will
// be scheduled before this time has elapsed, so we will be testing the
// maintenance code. However, if something is slow then this will test
// shutting down in the middle of maintenance.
setTimeout(continueToNextStep, 10000);
yield undefined;
info("Getting usage after maintenance");
let usageAfterMaintenance;
quotaManager.getUsageForURI(uri, (url, usage) => {
ok(usage > 0, "Usage is non-zero");
usageAfterMaintenance = usage;
continueToNextStep();
});
yield undefined;
info("Usage before: " + usageBeforeMaintenance + ". " +
"Usage after: " + usageAfterMaintenance);
ok(usageAfterMaintenance <= usageBeforeMaintenance,
"Maintenance decreased file sizes or left them the same");
finishTest();
yield undefined;
}

Просмотреть файл

@ -26,6 +26,7 @@ support-files =
[test_defaultStorageUpgrade.js]
[test_globalObjects_ipc.js]
skip-if = toolkit == 'android'
[test_idle_maintenance.js]
[test_invalidate.js]
# disabled for the moment.
skip-if = true

Просмотреть файл

@ -1079,7 +1079,7 @@ nsresult
GetDirectoryMetadataInputStream(nsIFile* aDirectory,
nsIBinaryInputStream** aStream)
{
AssertIsOnIOThread();
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aStream);
@ -1109,51 +1109,6 @@ GetDirectoryMetadataInputStream(nsIFile* aDirectory,
return NS_OK;
}
nsresult
GetDirectoryMetadata(nsIFile* aDirectory,
int64_t* aTimestamp,
nsACString& aGroup,
nsACString& aOrigin,
bool* aIsApp)
{
AssertIsOnIOThread();
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aTimestamp);
nsCOMPtr<nsIBinaryInputStream> binaryStream;
nsresult rv =
GetDirectoryMetadataInputStream(aDirectory, getter_AddRefs(binaryStream));
NS_ENSURE_SUCCESS(rv, rv);
uint64_t timestamp;
rv = binaryStream->Read64(&timestamp);
NS_ENSURE_SUCCESS(rv, rv);
nsCString group;
rv = binaryStream->ReadCString(group);
NS_ENSURE_SUCCESS(rv, rv);
nsCString origin;
rv = binaryStream->ReadCString(origin);
NS_ENSURE_SUCCESS(rv, rv);
bool isApp;
if (aIsApp) {
rv = binaryStream->ReadBoolean(&isApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
*aTimestamp = timestamp;
aGroup = group;
aOrigin = origin;
if (aIsApp) {
*aIsApp = isApp;
}
return NS_OK;
}
nsresult
GetDirectoryMetadataWithRestore(nsIFile* aDirectory,
bool aPersistent,
@ -1162,22 +1117,22 @@ GetDirectoryMetadataWithRestore(nsIFile* aDirectory,
nsACString& aOrigin,
bool* aIsApp)
{
nsresult rv = GetDirectoryMetadata(aDirectory,
aTimestamp,
aGroup,
aOrigin,
aIsApp);
nsresult rv = QuotaManager::GetDirectoryMetadata(aDirectory,
aTimestamp,
aGroup,
aOrigin,
aIsApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
rv = RestoreDirectoryMetadata(aDirectory, aPersistent);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = GetDirectoryMetadata(aDirectory,
aTimestamp,
aGroup,
aOrigin,
aIsApp);
rv = QuotaManager::GetDirectoryMetadata(aDirectory,
aTimestamp,
aGroup,
aOrigin,
aIsApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -2775,6 +2730,52 @@ QuotaManager::ChromeOrigin(nsACString& aOrigin)
aOrigin.AssignLiteral(kChromeOrigin);
}
// static
nsresult
QuotaManager::GetDirectoryMetadata(nsIFile* aDirectory,
int64_t* aTimestamp,
nsACString& aGroup,
nsACString& aOrigin,
bool* aIsApp)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aTimestamp);
nsCOMPtr<nsIBinaryInputStream> binaryStream;
nsresult rv =
GetDirectoryMetadataInputStream(aDirectory, getter_AddRefs(binaryStream));
NS_ENSURE_SUCCESS(rv, rv);
uint64_t timestamp;
rv = binaryStream->Read64(&timestamp);
NS_ENSURE_SUCCESS(rv, rv);
nsCString group;
rv = binaryStream->ReadCString(group);
NS_ENSURE_SUCCESS(rv, rv);
nsCString origin;
rv = binaryStream->ReadCString(origin);
NS_ENSURE_SUCCESS(rv, rv);
bool isApp;
if (aIsApp) {
rv = binaryStream->ReadBoolean(&isApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
*aTimestamp = timestamp;
aGroup = group;
aOrigin = origin;
if (aIsApp) {
*aIsApp = isApp;
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(QuotaManager, nsIQuotaManager, nsIObserver)
NS_IMETHODIMP

Просмотреть файл

@ -313,6 +313,13 @@ public:
EmptyCString(), _retval);
}
static nsresult
GetDirectoryMetadata(nsIFile* aDirectory,
int64_t* aTimestamp,
nsACString& aGroup,
nsACString& aOrigin,
bool* aIsApp);
private:
QuotaManager();