Bug 858674 - 'Tweak SQLite pragmas on mobile devices for space savings'. r=khuey.

This commit is contained in:
Ben Turner 2013-04-08 12:47:13 -07:00
parent 5252041839
commit b5169f935a
3 changed files with 96 additions and 22 deletions

View File

@ -300,21 +300,41 @@ IDBFactory::GetConnection(const nsAString& aDatabaseFilePath,
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(connection));
NS_ENSURE_SUCCESS(rv, nullptr);
// 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 recursive_triggers = ON;"
));
rv = SetDefaultPragmas(connection);
NS_ENSURE_SUCCESS(rv, nullptr);
return connection.forget();
}
// static
nsresult
IDBFactory::SetDefaultPragmas(mozIStorageConnection* aConnection)
{
NS_ASSERTION(aConnection, "Null connection!");
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
// We use foreign keys in lots of places.
"PRAGMA foreign_keys = ON; "
// 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.
"PRAGMA recursive_triggers = ON; "
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
// Switch the journaling mode to TRUNCATE to avoid changing the directory
// structure at the conclusion of every transaction for devices with slower
// file systems.
"PRAGMA journal_mode = TRUNCATE; "
#endif
));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return NS_OK;
}
inline
bool
IgnoreWhitespace(PRUnichar c)

View File

@ -80,6 +80,9 @@ public:
GetConnection(const nsAString& aDatabaseFilePath,
const nsACString& aOrigin);
static nsresult
SetDefaultPragmas(mozIStorageConnection* aConnection);
static nsresult
LoadDatabaseInformation(mozIStorageConnection* aConnection,
nsIAtom* aDatabaseId,

View File

@ -36,7 +36,7 @@ MOZ_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1,
"Need to update the major schema version.");
// Major schema version. Bump for almost everything.
const uint32_t kMajorSchemaVersion = 12;
const uint32_t kMajorSchemaVersion = 13;
// Minor schema version. Should almost always be 0 (maybe bump on release
// branches if we have to).
@ -1323,6 +1323,33 @@ UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection)
return NS_OK;
}
nsresult
UpgradeSchemaFrom12_0To13_0(mozIStorageConnection* aConnection,
bool* aVacuumNeeded)
{
nsresult rv;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
int32_t defaultPageSize;
rv = aConnection->GetDefaultPageSize(&defaultPageSize);
NS_ENSURE_SUCCESS(rv, rv);
// Enable auto_vacuum mode and update the page size to the platform default.
nsAutoCString upgradeQuery("PRAGMA auto_vacuum = FULL; PRAGMA page_size = ");
upgradeQuery.AppendInt(defaultPageSize);
rv = aConnection->ExecuteSimpleSQL(upgradeQuery);
NS_ENSURE_SUCCESS(rv, rv);
*aVacuumNeeded = true;
#endif
rv = aConnection->SetSchemaVersion(MakeSchemaVersion(13, 0));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
class VersionChangeEventsRunnable;
class SetVersionHelper : public AsyncConnectionHelper,
@ -1814,6 +1841,9 @@ OpenDatabaseHelper::CreateDatabaseConnection(
}
NS_ENSURE_SUCCESS(rv, rv);
rv = IDBFactory::SetDefaultPragmas(connection);
NS_ENSURE_SUCCESS(rv, rv);
rv = connection->EnableModule(NS_LITERAL_CSTRING("filesystem"));
NS_ENSURE_SUCCESS(rv, rv);
@ -1836,6 +1866,17 @@ OpenDatabaseHelper::CreateDatabaseConnection(
bool vacuumNeeded = false;
if (schemaVersion != kSQLiteSchemaVersion) {
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
if (!schemaVersion) {
// Have to do this before opening a transaction.
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
// Turn on auto_vacuum mode to reclaim disk space on mobile devices.
"PRAGMA auto_vacuum = FULL; "
));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
#endif
mozStorageTransaction transaction(connection, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
@ -1863,7 +1904,7 @@ OpenDatabaseHelper::CreateDatabaseConnection(
}
else {
// This logic needs to change next time we change the schema!
MOZ_STATIC_ASSERT(kSQLiteSchemaVersion == int32_t((12 << 4) + 0),
MOZ_STATIC_ASSERT(kSQLiteSchemaVersion == int32_t((13 << 4) + 0),
"Need upgrade code from schema version increase.");
while (schemaVersion != kSQLiteSchemaVersion) {
@ -1892,6 +1933,9 @@ OpenDatabaseHelper::CreateDatabaseConnection(
else if (schemaVersion == MakeSchemaVersion(11, 0)) {
rv = UpgradeSchemaFrom11_0To12_0(connection);
}
else if (schemaVersion == MakeSchemaVersion(12, 0)) {
rv = UpgradeSchemaFrom12_0To13_0(connection, &vacuumNeeded);
}
else {
NS_WARNING("Unable to open IndexedDB database, no upgrade path is "
"available!");
@ -1906,7 +1950,7 @@ OpenDatabaseHelper::CreateDatabaseConnection(
NS_ASSERTION(schemaVersion == kSQLiteSchemaVersion, "Huh?!");
}
rv = transaction.Commit();
rv = transaction.Commit();
if (rv == NS_ERROR_FILE_NO_DEVICE_SPACE) {
// mozstorage translates SQLITE_FULL to NS_ERROR_FILE_NO_DEVICE_SPACE,
// which we know better as NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR.
@ -1916,18 +1960,10 @@ OpenDatabaseHelper::CreateDatabaseConnection(
}
if (vacuumNeeded) {
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"VACUUM;"
));
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING("VACUUM;"));
NS_ENSURE_SUCCESS(rv, rv);
}
// Turn on foreign key constraints.
rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"PRAGMA foreign_keys = ON;"
));
NS_ENSURE_SUCCESS(rv, rv);
connection.forget(aConnection);
return NS_OK;
}
@ -2469,6 +2505,21 @@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
}
}
nsCOMPtr<nsIFile> dbJournalFile;
rv = directory->Clone(getter_AddRefs(dbJournalFile));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = dbJournalFile->Append(filename + NS_LITERAL_STRING(".sqlite-journal"));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = dbJournalFile->Exists(&exists);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (exists) {
rv = dbJournalFile->Remove(false);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
nsCOMPtr<nsIFile> fmDirectory;
rv = directory->Clone(getter_AddRefs(fmDirectory));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);