Skip to content

Commit 0aa4713

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Support enabling WAL using a flag when DB is opened."
2 parents cbe55a1 + 47847f3 commit 0aa4713

File tree

10 files changed

+182
-88
lines changed

10 files changed

+182
-88
lines changed

api/current.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5204,6 +5204,7 @@ package android.content {
52045204
field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
52055205
field public static final java.lang.String LOCATION_SERVICE = "location";
52065206
field public static final int MODE_APPEND = 32768; // 0x8000
5207+
field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
52075208
field public static final int MODE_MULTI_PROCESS = 4; // 0x4
52085209
field public static final int MODE_PRIVATE = 0; // 0x0
52095210
field public static final int MODE_WORLD_READABLE = 1; // 0x1
@@ -7334,6 +7335,7 @@ package android.database.sqlite {
73347335
method public deprecated boolean isDbLockedByOtherThreads();
73357336
method public boolean isOpen();
73367337
method public boolean isReadOnly();
7338+
method public boolean isWriteAheadLoggingEnabled();
73377339
method public deprecated void markTableSyncable(java.lang.String, java.lang.String);
73387340
method public deprecated void markTableSyncable(java.lang.String, java.lang.String, java.lang.String);
73397341
method public boolean needUpgrade(int);
@@ -7375,6 +7377,7 @@ package android.database.sqlite {
73757377
field public static final int CONFLICT_REPLACE = 5; // 0x5
73767378
field public static final int CONFLICT_ROLLBACK = 1; // 0x1
73777379
field public static final int CREATE_IF_NECESSARY = 268435456; // 0x10000000
7380+
field public static final int ENABLE_WRITE_AHEAD_LOGGING = 536870912; // 0x20000000
73787381
field public static final int MAX_SQL_CACHE_SIZE = 100; // 0x64
73797382
field public static final int NO_LOCALIZED_COLLATORS = 16; // 0x10
73807383
field public static final int OPEN_READONLY = 1; // 0x1
@@ -7438,6 +7441,7 @@ package android.database.sqlite {
74387441
method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
74397442
method public void onOpen(android.database.sqlite.SQLiteDatabase);
74407443
method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
7444+
method public void setWriteAheadLoggingEnabled(boolean);
74417445
}
74427446

74437447
public class SQLiteOutOfMemoryException extends android.database.sqlite.SQLiteException {

core/java/android/app/ContextImpl.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -766,17 +766,18 @@ public String[] fileList() {
766766

767767
@Override
768768
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
769-
File f = validateFilePath(name, true);
770-
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
771-
setFilePermissionsFromMode(f.getPath(), mode, 0);
772-
return db;
769+
return openOrCreateDatabase(name, mode, factory, null);
773770
}
774771

775772
@Override
776773
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
777774
DatabaseErrorHandler errorHandler) {
778775
File f = validateFilePath(name, true);
779-
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
776+
int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
777+
if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
778+
flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
779+
}
780+
SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
780781
setFilePermissionsFromMode(f.getPath(), mode, 0);
781782
return db;
782783
}

core/java/android/content/Context.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ public abstract class Context {
9898
*/
9999
public static final int MODE_MULTI_PROCESS = 0x0004;
100100

101+
/**
102+
* Database open flag: when set, the database is opened with write-ahead
103+
* logging enabled by default.
104+
*
105+
* @see #openOrCreateDatabase(String, int, CursorFactory)
106+
* @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler)
107+
* @see SQLiteDatabase#enableWriteAheadLogging
108+
*/
109+
public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;
110+
101111
/**
102112
* Flag for {@link #bindService}: automatically create the service as long
103113
* as the binding exists. Note that while this will create the service,
@@ -691,6 +701,7 @@ public abstract FileOutputStream openFileOutput(String name, int mode)
691701
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
692702
* default operation, {@link #MODE_WORLD_READABLE}
693703
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
704+
* Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
694705
* @param factory An optional factory class that is called to instantiate a
695706
* cursor when query is called.
696707
*
@@ -700,6 +711,7 @@ public abstract FileOutputStream openFileOutput(String name, int mode)
700711
* @see #MODE_PRIVATE
701712
* @see #MODE_WORLD_READABLE
702713
* @see #MODE_WORLD_WRITEABLE
714+
* @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
703715
* @see #deleteDatabase
704716
*/
705717
public abstract SQLiteDatabase openOrCreateDatabase(String name,
@@ -716,6 +728,7 @@ public abstract SQLiteDatabase openOrCreateDatabase(String name,
716728
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
717729
* default operation, {@link #MODE_WORLD_READABLE}
718730
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
731+
* Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
719732
* @param factory An optional factory class that is called to instantiate a
720733
* cursor when query is called.
721734
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
@@ -726,6 +739,7 @@ public abstract SQLiteDatabase openOrCreateDatabase(String name,
726739
* @see #MODE_PRIVATE
727740
* @see #MODE_WORLD_READABLE
728741
* @see #MODE_WORLD_WRITEABLE
742+
* @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
729743
* @see #deleteDatabase
730744
*/
731745
public abstract SQLiteDatabase openOrCreateDatabase(String name,

core/java/android/database/sqlite/SQLiteConnection.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ private void setJournalSizeLimit() {
269269

270270
private void setWalModeFromConfiguration() {
271271
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
272-
if (mConfiguration.walEnabled) {
272+
if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
273273
setJournalMode("WAL");
274274
setSyncMode(SQLiteGlobal.getWALSyncMode());
275275
} else {
@@ -389,7 +389,8 @@ void reconfigure(SQLiteDatabaseConfiguration configuration) {
389389
}
390390

391391
// Remember what changed.
392-
boolean walModeChanged = configuration.walEnabled != mConfiguration.walEnabled;
392+
boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
393+
& SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
393394
boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
394395

395396
// Update configuration parameters.

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

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public final class SQLiteConnectionPool implements Closeable {
8181
private final Object mLock = new Object();
8282
private final AtomicBoolean mConnectionLeaked = new AtomicBoolean();
8383
private final SQLiteDatabaseConfiguration mConfiguration;
84+
private int mMaxConnectionPoolSize;
8485
private boolean mIsOpen;
8586
private int mNextConnectionId;
8687

@@ -146,6 +147,7 @@ enum AcquiredConnectionStatus {
146147

147148
private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
148149
mConfiguration = new SQLiteDatabaseConfiguration(configuration);
150+
setMaxConnectionPoolSizeLocked();
149151
}
150152

151153
@Override
@@ -257,8 +259,9 @@ public void reconfigure(SQLiteDatabaseConfiguration configuration) {
257259
synchronized (mLock) {
258260
throwIfClosedLocked();
259261

260-
boolean restrictToOneConnection = false;
261-
if (mConfiguration.walEnabled != configuration.walEnabled) {
262+
boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
263+
& SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
264+
if (walModeChanged) {
262265
// WAL mode can only be changed if there are no acquired connections
263266
// because we need to close all but the primary connection first.
264267
if (!mAcquiredConnections.isEmpty()) {
@@ -272,15 +275,13 @@ public void reconfigure(SQLiteDatabaseConfiguration configuration) {
272275
// because none of them are in use.
273276
closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
274277
assert mAvailableNonPrimaryConnections.isEmpty();
275-
276-
restrictToOneConnection = true;
277278
}
278279

279280
if (mConfiguration.openFlags != configuration.openFlags) {
280281
// If we are changing open flags and WAL mode at the same time, then
281282
// we have no choice but to close the primary connection beforehand
282283
// because there can only be one connection open when we change WAL mode.
283-
if (restrictToOneConnection) {
284+
if (walModeChanged) {
284285
closeAvailableConnectionsAndLogExceptionsLocked();
285286
}
286287

@@ -296,9 +297,11 @@ public void reconfigure(SQLiteDatabaseConfiguration configuration) {
296297

297298
mAvailablePrimaryConnection = newPrimaryConnection;
298299
mConfiguration.updateParametersFrom(configuration);
300+
setMaxConnectionPoolSizeLocked();
299301
} else {
300302
// Reconfigure the database connections in place.
301303
mConfiguration.updateParametersFrom(configuration);
304+
setMaxConnectionPoolSizeLocked();
302305

303306
closeExcessConnectionsAndLogExceptionsLocked();
304307
reconfigureAllConnectionsLocked();
@@ -360,8 +363,7 @@ public void releaseConnection(SQLiteConnection connection) {
360363
mAvailablePrimaryConnection = connection;
361364
}
362365
wakeConnectionWaitersLocked();
363-
} else if (mAvailableNonPrimaryConnections.size() >=
364-
mConfiguration.maxConnectionPoolSize - 1) {
366+
} else if (mAvailableNonPrimaryConnections.size() >= mMaxConnectionPoolSize - 1) {
365367
closeConnectionAndLogExceptionsLocked(connection);
366368
} else {
367369
if (recycleConnectionLocked(connection, status)) {
@@ -499,7 +501,7 @@ private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() {
499501
// Can't throw.
500502
private void closeExcessConnectionsAndLogExceptionsLocked() {
501503
int availableCount = mAvailableNonPrimaryConnections.size();
502-
while (availableCount-- > mConfiguration.maxConnectionPoolSize - 1) {
504+
while (availableCount-- > mMaxConnectionPoolSize - 1) {
503505
SQLiteConnection connection =
504506
mAvailableNonPrimaryConnections.remove(availableCount);
505507
closeConnectionAndLogExceptionsLocked(connection);
@@ -874,7 +876,7 @@ private SQLiteConnection tryAcquireNonPrimaryConnectionLocked(
874876
if (mAvailablePrimaryConnection != null) {
875877
openConnections += 1;
876878
}
877-
if (openConnections >= mConfiguration.maxConnectionPoolSize) {
879+
if (openConnections >= mMaxConnectionPoolSize) {
878880
return null;
879881
}
880882
connection = openConnectionLocked(mConfiguration,
@@ -926,6 +928,18 @@ private static int getPriority(int connectionFlags) {
926928
return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0;
927929
}
928930

931+
private void setMaxConnectionPoolSizeLocked() {
932+
if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
933+
mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
934+
} else {
935+
// TODO: We don't actually need to restrict the connection pool size to 1
936+
// for non-WAL databases. There might be reasons to use connection pooling
937+
// with other journal modes. For now, enabling connection pooling and
938+
// using WAL are the same thing in the API.
939+
mMaxConnectionPoolSize = 1;
940+
}
941+
}
942+
929943
private void throwIfClosedLocked() {
930944
if (!mIsOpen) {
931945
throw new IllegalStateException("Cannot perform this operation "
@@ -972,7 +986,7 @@ public void dump(Printer printer, boolean verbose) {
972986
synchronized (mLock) {
973987
printer.println("Connection pool for " + mConfiguration.path + ":");
974988
printer.println(" Open: " + mIsOpen);
975-
printer.println(" Max connections: " + mConfiguration.maxConnectionPoolSize);
989+
printer.println(" Max connections: " + mMaxConnectionPoolSize);
976990

977991
printer.println(" Available primary connection:");
978992
if (mAvailablePrimaryConnection != null) {

0 commit comments

Comments
 (0)