summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/database/sqlite/SQLiteConnectionPool.java42
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java65
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;
}
}