Skip to content

Commit 2d00872

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Throw if WAL enabled/disabled when connections are in use."
2 parents 3004cc5 + e67ca42 commit 2d00872

File tree

3 files changed

+95
-13
lines changed

3 files changed

+95
-13
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7312,6 +7312,7 @@ package android.database.sqlite {
73127312
method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
73137313
method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
73147314
method public static boolean deleteDatabase(java.io.File);
7315+
method public void disableWriteAheadLogging();
73157316
method public boolean enableWriteAheadLogging();
73167317
method public void endTransaction();
73177318
method public void execSQL(java.lang.String) throws android.database.SQLException;

core/java/android/database/sqlite/SQLiteConnectionPool.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,34 @@ public void reconfigure(SQLiteDatabaseConfiguration configuration) {
257257
synchronized (mLock) {
258258
throwIfClosedLocked();
259259

260+
boolean restrictToOneConnection = false;
261+
if (mConfiguration.journalMode.equalsIgnoreCase("WAL")
262+
!= configuration.journalMode.equalsIgnoreCase("WAL")) {
263+
// WAL mode can only be changed if there are no acquired connections
264+
// because we need to close all but the primary connection first.
265+
if (!mAcquiredConnections.isEmpty()) {
266+
throw new IllegalStateException("Write Ahead Logging (WAL) mode cannot "
267+
+ "be enabled or disabled while there are transactions in "
268+
+ "progress. Finish all transactions and release all active "
269+
+ "database connections first.");
270+
}
271+
272+
// Close all non-primary connections. This should happen immediately
273+
// because none of them are in use.
274+
closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
275+
assert mAvailableNonPrimaryConnections.isEmpty();
276+
277+
restrictToOneConnection = true;
278+
}
279+
260280
if (mConfiguration.openFlags != configuration.openFlags) {
281+
// If we are changing open flags and WAL mode at the same time, then
282+
// we have no choice but to close the primary connection beforehand
283+
// because there can only be one connection open when we change WAL mode.
284+
if (restrictToOneConnection) {
285+
closeAvailableConnectionsAndLogExceptionsLocked();
286+
}
287+
261288
// Try to reopen the primary connection using the new open flags then
262289
// close and discard all existing connections.
263290
// This might throw if the database is corrupt or cannot be opened in
@@ -453,18 +480,23 @@ void onConnectionLeaked() {
453480

454481
// Can't throw.
455482
private void closeAvailableConnectionsAndLogExceptionsLocked() {
456-
final int count = mAvailableNonPrimaryConnections.size();
457-
for (int i = 0; i < count; i++) {
458-
closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i));
459-
}
460-
mAvailableNonPrimaryConnections.clear();
483+
closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
461484

462485
if (mAvailablePrimaryConnection != null) {
463486
closeConnectionAndLogExceptionsLocked(mAvailablePrimaryConnection);
464487
mAvailablePrimaryConnection = null;
465488
}
466489
}
467490

491+
// Can't throw.
492+
private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() {
493+
final int count = mAvailableNonPrimaryConnections.size();
494+
for (int i = 0; i < count; i++) {
495+
closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i));
496+
}
497+
mAvailableNonPrimaryConnections.clear();
498+
}
499+
468500
// Can't throw.
469501
private void closeExcessConnectionsAndLogExceptionsLocked() {
470502
int availableCount = mAvailableNonPrimaryConnections.size();

core/java/android/database/sqlite/SQLiteDatabase.java

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -834,8 +834,14 @@ public void addCustomFunction(String name, int numArgs, CustomFunction function)
834834

835835
synchronized (mLock) {
836836
throwIfNotOpenLocked();
837+
837838
mConfigurationLocked.customFunctions.add(wrapper);
838-
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
839+
try {
840+
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
841+
} catch (RuntimeException ex) {
842+
mConfigurationLocked.customFunctions.remove(wrapper);
843+
throw ex;
844+
}
839845
}
840846
}
841847

@@ -1733,8 +1739,15 @@ public void setLocale(Locale locale) {
17331739

17341740
synchronized (mLock) {
17351741
throwIfNotOpenLocked();
1742+
1743+
final Locale oldLocale = mConfigurationLocked.locale;
17361744
mConfigurationLocked.locale = locale;
1737-
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1745+
try {
1746+
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1747+
} catch (RuntimeException ex) {
1748+
mConfigurationLocked.locale = oldLocale;
1749+
throw ex;
1750+
}
17381751
}
17391752
}
17401753

@@ -1759,8 +1772,15 @@ public void setMaxSqlCacheSize(int cacheSize) {
17591772

17601773
synchronized (mLock) {
17611774
throwIfNotOpenLocked();
1775+
1776+
final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize;
17621777
mConfigurationLocked.maxSqlCacheSize = cacheSize;
1763-
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1778+
try {
1779+
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1780+
} catch (RuntimeException ex) {
1781+
mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize;
1782+
throw ex;
1783+
}
17641784
}
17651785
}
17661786

@@ -1805,6 +1825,10 @@ public void setMaxSqlCacheSize(int cacheSize) {
18051825
* </p>
18061826
*
18071827
* @return true if write-ahead-logging is set. false otherwise
1828+
*
1829+
* @throw IllegalStateException if there are transactions in progress at the
1830+
* time this method is called. WAL mode can only be changed when there are no
1831+
* transactions in progress.
18081832
*/
18091833
public boolean enableWriteAheadLogging() {
18101834
synchronized (mLock) {
@@ -1835,18 +1859,32 @@ public boolean enableWriteAheadLogging() {
18351859
return false;
18361860
}
18371861

1838-
mIsWALEnabledLocked = true;
1862+
final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
1863+
final String oldSyncMode = mConfigurationLocked.syncMode;
1864+
final String oldJournalMode = mConfigurationLocked.journalMode;
18391865
mConfigurationLocked.maxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
18401866
mConfigurationLocked.syncMode = SQLiteGlobal.getWALSyncMode();
18411867
mConfigurationLocked.journalMode = "WAL";
1842-
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1868+
try {
1869+
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1870+
} catch (RuntimeException ex) {
1871+
mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
1872+
mConfigurationLocked.syncMode = oldSyncMode;
1873+
mConfigurationLocked.journalMode = oldJournalMode;
1874+
throw ex;
1875+
}
1876+
1877+
mIsWALEnabledLocked = true;
18431878
}
18441879
return true;
18451880
}
18461881

18471882
/**
18481883
* This method disables the features enabled by {@link #enableWriteAheadLogging()}.
1849-
* @hide
1884+
*
1885+
* @throw IllegalStateException if there are transactions in progress at the
1886+
* time this method is called. WAL mode can only be changed when there are no
1887+
* transactions in progress.
18501888
*/
18511889
public void disableWriteAheadLogging() {
18521890
synchronized (mLock) {
@@ -1856,11 +1894,22 @@ public void disableWriteAheadLogging() {
18561894
return;
18571895
}
18581896

1859-
mIsWALEnabledLocked = false;
1897+
final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
1898+
final String oldSyncMode = mConfigurationLocked.syncMode;
1899+
final String oldJournalMode = mConfigurationLocked.journalMode;
18601900
mConfigurationLocked.maxConnectionPoolSize = 1;
18611901
mConfigurationLocked.syncMode = SQLiteGlobal.getDefaultSyncMode();
18621902
mConfigurationLocked.journalMode = SQLiteGlobal.getDefaultJournalMode();
1863-
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1903+
try {
1904+
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
1905+
} catch (RuntimeException ex) {
1906+
mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
1907+
mConfigurationLocked.syncMode = oldSyncMode;
1908+
mConfigurationLocked.journalMode = oldJournalMode;
1909+
throw ex;
1910+
}
1911+
1912+
mIsWALEnabledLocked = false;
18641913
}
18651914
}
18661915

0 commit comments

Comments
 (0)