Merge "Throw if WAL enabled/disabled when connections are in use."

This commit is contained in:
Jeff Brown
2012-03-21 18:30:50 -07:00
committed by Android (Google) Code Review
3 changed files with 95 additions and 13 deletions

View File

@@ -7312,6 +7312,7 @@ package android.database.sqlite {
method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
method public static boolean deleteDatabase(java.io.File);
method public void disableWriteAheadLogging();
method public boolean enableWriteAheadLogging();
method public void endTransaction();
method public void execSQL(java.lang.String) throws android.database.SQLException;

View File

@@ -257,7 +257,34 @@ public final class SQLiteConnectionPool implements Closeable {
synchronized (mLock) {
throwIfClosedLocked();
boolean restrictToOneConnection = false;
if (mConfiguration.journalMode.equalsIgnoreCase("WAL")
!= configuration.journalMode.equalsIgnoreCase("WAL")) {
// WAL mode can only be changed if there are no acquired connections
// because we need to close all but the primary connection first.
if (!mAcquiredConnections.isEmpty()) {
throw new IllegalStateException("Write Ahead Logging (WAL) mode cannot "
+ "be enabled or disabled while there are transactions in "
+ "progress. Finish all transactions and release all active "
+ "database connections first.");
}
// Close all non-primary connections. This should happen immediately
// because none of them are in use.
closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
assert mAvailableNonPrimaryConnections.isEmpty();
restrictToOneConnection = true;
}
if (mConfiguration.openFlags != configuration.openFlags) {
// If we are changing open flags and WAL mode at the same time, then
// we have no choice but to close the primary connection beforehand
// because there can only be one connection open when we change WAL mode.
if (restrictToOneConnection) {
closeAvailableConnectionsAndLogExceptionsLocked();
}
// Try to reopen the primary connection using the new open flags then
// close and discard all existing connections.
// This might throw if the database is corrupt or cannot be opened in
@@ -453,11 +480,7 @@ public final class SQLiteConnectionPool implements Closeable {
// Can't throw.
private void closeAvailableConnectionsAndLogExceptionsLocked() {
final int count = mAvailableNonPrimaryConnections.size();
for (int i = 0; i < count; i++) {
closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i));
}
mAvailableNonPrimaryConnections.clear();
closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
if (mAvailablePrimaryConnection != null) {
closeConnectionAndLogExceptionsLocked(mAvailablePrimaryConnection);
@@ -465,6 +488,15 @@ public final class SQLiteConnectionPool implements Closeable {
}
}
// Can't throw.
private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() {
final int count = mAvailableNonPrimaryConnections.size();
for (int i = 0; i < count; i++) {
closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i));
}
mAvailableNonPrimaryConnections.clear();
}
// Can't throw.
private void closeExcessConnectionsAndLogExceptionsLocked() {
int availableCount = mAvailableNonPrimaryConnections.size();

View File

@@ -834,8 +834,14 @@ public final class SQLiteDatabase extends SQLiteClosable {
synchronized (mLock) {
throwIfNotOpenLocked();
mConfigurationLocked.customFunctions.add(wrapper);
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.customFunctions.remove(wrapper);
throw ex;
}
}
}
@@ -1733,8 +1739,15 @@ public final class SQLiteDatabase extends SQLiteClosable {
synchronized (mLock) {
throwIfNotOpenLocked();
final Locale oldLocale = mConfigurationLocked.locale;
mConfigurationLocked.locale = locale;
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.locale = oldLocale;
throw ex;
}
}
}
@@ -1759,8 +1772,15 @@ public final class SQLiteDatabase extends SQLiteClosable {
synchronized (mLock) {
throwIfNotOpenLocked();
final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
mConfigurationLocked.maxSqlCacheSize = cacheSize;
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
throw ex;
}
}
}
@@ -1805,6 +1825,10 @@ public final class SQLiteDatabase extends SQLiteClosable {
* </p>
*
* @return true if write-ahead-logging is set. false otherwise
*
* @throw IllegalStateException if there are transactions in progress at the
* time this method is called. WAL mode can only be changed when there are no
* transactions in progress.
*/
public boolean enableWriteAheadLogging() {
synchronized (mLock) {
@@ -1835,18 +1859,32 @@ public final class SQLiteDatabase extends SQLiteClosable {
return false;
}
mIsWALEnabledLocked = true;
final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
final String oldSyncMode = mConfigurationLocked.syncMode;
final String oldJournalMode = mConfigurationLocked.journalMode;
mConfigurationLocked.maxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
mConfigurationLocked.syncMode = SQLiteGlobal.getWALSyncMode();
mConfigurationLocked.journalMode = "WAL";
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
mConfigurationLocked.syncMode = oldSyncMode;
mConfigurationLocked.journalMode = oldJournalMode;
throw ex;
}
mIsWALEnabledLocked = true;
}
return true;
}
/**
* This method disables the features enabled by {@link #enableWriteAheadLogging()}.
* @hide
*
* @throw IllegalStateException if there are transactions in progress at the
* time this method is called. WAL mode can only be changed when there are no
* transactions in progress.
*/
public void disableWriteAheadLogging() {
synchronized (mLock) {
@@ -1856,11 +1894,22 @@ public final class SQLiteDatabase extends SQLiteClosable {
return;
}
mIsWALEnabledLocked = false;
final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
final String oldSyncMode = mConfigurationLocked.syncMode;
final String oldJournalMode = mConfigurationLocked.journalMode;
mConfigurationLocked.maxConnectionPoolSize = 1;
mConfigurationLocked.syncMode = SQLiteGlobal.getDefaultSyncMode();
mConfigurationLocked.journalMode = SQLiteGlobal.getDefaultJournalMode();
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
mConfigurationLocked.syncMode = oldSyncMode;
mConfigurationLocked.journalMode = oldJournalMode;
throw ex;
}
mIsWALEnabledLocked = false;
}
}