mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-24 03:19:06 +00:00
Bug 628921 - Changing from WAL to a rollback journal to change page_size may cause a infinite loop @AsyncExecuteStatements::executeStatement.
r=sdwilsh a=blocking
This commit is contained in:
parent
d06b864012
commit
296464cbe5
@ -54,12 +54,8 @@ interface mozIStorageVacuumParticipant : nsISupports {
|
||||
* The expected page size in bytes for the database. The vacuum manager will
|
||||
* try to correct the page size during idle based on this value.
|
||||
*
|
||||
* @note If the database is using the WAL journal mode and the current page
|
||||
* size is not the expected one, the journal mode will be changed to
|
||||
* TRUNCATE because WAL does not allow page size changes.
|
||||
* The vacuum manager will try to restore WAL mode, but for this to
|
||||
* work reliably the participant must ensure to always reset statements.
|
||||
* If restoring the journal mode should fail it will stick to TRUNCATE.
|
||||
* @note If the database is using the WAL journal mode, the page size won't
|
||||
* be changed to the requested value. See bug 634374.
|
||||
* @note Valid page size values are from 512 to 65536.
|
||||
* The suggested value is mozIStorageConnection::DEFAULT_PAGE_SIZE.
|
||||
*/
|
||||
|
@ -148,7 +148,6 @@ private:
|
||||
nsCOMPtr<nsIPrefBranch> mPrefBranch;
|
||||
nsCString mDBFilename;
|
||||
nsCOMPtr<mozIStorageConnection> mDBConn;
|
||||
bool mRestoreWAL;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -180,7 +179,7 @@ NotifyCallback::NotifyCallback(Vacuumer *aVacuumer,
|
||||
NS_IMETHODIMP
|
||||
NotifyCallback::HandleCompletion(PRUint16 aReason)
|
||||
{
|
||||
// We succeeded if both vacuum are WAL restoration succeeded.
|
||||
// We succeeded if vacuum succeeded.
|
||||
nsresult rv = mVacuumer->notifyCompletion(mVacuumSucceeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
@ -193,7 +192,6 @@ Vacuumer::Vacuumer(mozIStorageVacuumParticipant *aParticipant,
|
||||
nsIPrefBranch *aPrefBranch)
|
||||
: mParticipant(aParticipant)
|
||||
, mPrefBranch(aPrefBranch)
|
||||
, mRestoreWAL(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -222,7 +220,7 @@ Vacuumer::execute()
|
||||
expectedPageSize = mozIStorageConnection::DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
|
||||
bool canOptimizePageSize;
|
||||
bool canOptimizePageSize = false;
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
@ -237,7 +235,26 @@ Vacuumer::execute()
|
||||
rv = stmt->GetInt32(0, ¤tPageSize);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ASSERTION(currentPageSize > 0, "Got invalid page size value?");
|
||||
canOptimizePageSize = currentPageSize != expectedPageSize;
|
||||
if (currentPageSize != expectedPageSize) {
|
||||
// Check journal mode. WAL journaling does not allow vacuum to change
|
||||
// the page size.
|
||||
// TODO Bug 634374: figure out a strategy to fix page size with WAL.
|
||||
nsCAutoString journalMode;
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA journal_mode"
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
PRBool hasResult;
|
||||
rv = stmt->ExecuteStep(&hasResult);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_TRUE(hasResult, false);
|
||||
rv = stmt->GetUTF8String(0, journalMode);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
canOptimizePageSize = !journalMode.EqualsLiteral("wal");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the database filename. Last vacuum time is stored under this name
|
||||
@ -282,41 +299,6 @@ Vacuumer::execute()
|
||||
}
|
||||
|
||||
if (canOptimizePageSize) {
|
||||
// Check journal mode. WAL journaling does not allow vacuum to change page
|
||||
// size, thus we have to temporarily switch the journal mode to TRUNCATE.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA journal_mode"
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
PRBool hasResult;
|
||||
rv = stmt->ExecuteStep(&hasResult);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_TRUE(hasResult, false);
|
||||
nsCAutoString journalMode;
|
||||
rv = stmt->GetUTF8String(0, journalMode);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
rv = stmt->Reset();
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (journalMode.EqualsLiteral("wal")) {
|
||||
mRestoreWAL = true;
|
||||
// Set the journal mode to a backwards compatible one.
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt;
|
||||
rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA journal_mode = TRUNCATE"
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
nsCOMPtr<BaseCallback> callback = new BaseCallback();
|
||||
NS_ENSURE_TRUE(callback, false);
|
||||
nsCOMPtr<mozIStoragePendingStatement> ps;
|
||||
rv = stmt->ExecuteAsync(callback, getter_AddRefs(ps));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
// WARNING: any statement after we check for journal mode must be async
|
||||
// to ensure the correct execution order.
|
||||
|
||||
nsCOMPtr<mozIStorageAsyncStatement> pageSizeStmt;
|
||||
rv = mDBConn->CreateAsyncStatement(nsPrintfCString(
|
||||
"PRAGMA page_size = %ld", expectedPageSize
|
||||
@ -399,27 +381,7 @@ Vacuumer::HandleCompletion(PRUint16 aReason)
|
||||
(void)mPrefBranch->SetIntPref(mDBFilename.get(), now);
|
||||
}
|
||||
|
||||
// Check if we should restore WAL journal mode.
|
||||
if (mRestoreWAL) {
|
||||
// Restoring WAL is expensive, so must be done async.
|
||||
// End of vacuum will be notified once it finishes.
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt;
|
||||
(void)mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"PRAGMA journal_mode = WAL"
|
||||
), getter_AddRefs(stmt));
|
||||
nsCOMPtr<NotifyCallback> callback =
|
||||
new NotifyCallback(this, aReason == REASON_FINISHED);
|
||||
// Handle errors now, it's important to notify participant before throwing.
|
||||
if (!stmt || !callback) {
|
||||
notifyCompletion(false);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsCOMPtr<mozIStoragePendingStatement> ps;
|
||||
stmt->ExecuteAsync(callback, getter_AddRefs(ps));
|
||||
}
|
||||
else {
|
||||
notifyCompletion(aReason == REASON_FINISHED);
|
||||
}
|
||||
notifyCompletion(aReason == REASON_FINISHED);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -218,6 +218,7 @@ function test_skipped_optout_vacuum()
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
/* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
|
||||
function test_page_size_change_with_wal()
|
||||
{
|
||||
print("\n*** Test that a VACUUM changes page_size with WAL mode");
|
||||
@ -282,6 +283,7 @@ function test_page_size_change_with_wal()
|
||||
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
*/
|
||||
|
||||
function test_memory_database_crash()
|
||||
{
|
||||
@ -309,7 +311,7 @@ function test_memory_database_crash()
|
||||
synthesize_idle_daily();
|
||||
},
|
||||
|
||||
/* Test temporarily disabled due to bug 599098.
|
||||
/* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
|
||||
function test_wal_restore_fail()
|
||||
{
|
||||
print("\n*** Test that a failing WAL restoration notifies failure");
|
||||
|
Loading…
x
Reference in New Issue
Block a user