diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-03-21 17:24:05 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-03-21 18:08:09 -0700 |
commit | e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fc (patch) | |
tree | d8d0206806fc245148ac7cf12ad3c8f7312f1d09 /core | |
parent | 3e6792232aa0ce3e650eaa03529c9eb2fe023ca9 (diff) | |
download | frameworks_base-e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fc.zip frameworks_base-e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fc.tar.gz frameworks_base-e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fc.tar.bz2 |
Throw if WAL enabled/disabled when connections are in use.
Changing WAL mode requires obtaining an exclusive lock on the
database and can only be done when there are NO other active
database connections.
Check that this is really the case, and bail with a useful
error message if an application attempts to change WAL mode while
transactions are in progress.
Expose disableWriteAheadLogging() in the API.
Change-Id: I87599de3b88c53dcd75677aefd72e40de216c2c1
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/database/sqlite/SQLiteConnectionPool.java | 42 | ||||
-rw-r--r-- | core/java/android/database/sqlite/SQLiteDatabase.java | 65 |
2 files changed, 94 insertions, 13 deletions
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java index 3562e89..00d3309 100644 --- a/core/java/android/database/sqlite/SQLiteConnectionPool.java +++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java @@ -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); @@ -466,6 +489,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(); while (availableCount-- > mConfiguration.maxConnectionPoolSize - 1) { diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index bf32ea7..e575c26 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -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; } } |