summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-03-22 19:13:11 -0700
committerJeff Brown <jeffbrown@google.com>2012-03-23 13:26:26 -0700
commit47847f3f4dcf2a0dbea0bc0e4f02528e21d37a88 (patch)
tree95198c432b05cef99e38a09165c2686906dc48bb /core
parent3c4da3cad04ca878a4a37fcca3f3e2ff51d03fcb (diff)
downloadframeworks_base-47847f3f4dcf2a0dbea0bc0e4f02528e21d37a88.zip
frameworks_base-47847f3f4dcf2a0dbea0bc0e4f02528e21d37a88.tar.gz
frameworks_base-47847f3f4dcf2a0dbea0bc0e4f02528e21d37a88.tar.bz2
Support enabling WAL using a flag when DB is opened.
Using enableWriteAheadLogging() to enable WAL is inefficient because we previously disabled WAL mode when the database was opened. Switching from WAL to PERSIST then back to WAL is inefficient and could slow down application launch time. It would be better to leave the database in WAL mode when we open it to begin with. To do that, we need to know ahead of time whether we will want to have WAL enabled for the newly opened database. Using this flag also reduces the chance that we will encounter an error enabling WAL mode due to there being other open connections to the database. Bug: 6124556 Change-Id: I38ec7a528baeda9f1ef77e25e88b3ca4b6296200
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/ContextImpl.java11
-rw-r--r--core/java/android/content/Context.java14
-rw-r--r--core/java/android/database/sqlite/SQLiteConnection.java5
-rw-r--r--core/java/android/database/sqlite/SQLiteConnectionPool.java34
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java144
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java18
-rw-r--r--core/java/android/database/sqlite/SQLiteOpenHelper.java38
7 files changed, 177 insertions, 87 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7043a73..d758eca 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -766,17 +766,18 @@ class ContextImpl extends Context {
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
- File f = validateFilePath(name, true);
- SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
- setFilePermissionsFromMode(f.getPath(), mode, 0);
- return db;
+ return openOrCreateDatabase(name, mode, factory, null);
}
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
DatabaseErrorHandler errorHandler) {
File f = validateFilePath(name, true);
- SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
+ int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
+ if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
+ flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
+ }
+ SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
setFilePermissionsFromMode(f.getPath(), mode, 0);
return db;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 741a6e9..2902504 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -99,6 +99,16 @@ public abstract class Context {
public static final int MODE_MULTI_PROCESS = 0x0004;
/**
+ * Database open flag: when set, the database is opened with write-ahead
+ * logging enabled by default.
+ *
+ * @see #openOrCreateDatabase(String, int, CursorFactory)
+ * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler)
+ * @see SQLiteDatabase#enableWriteAheadLogging
+ */
+ public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;
+
+ /**
* Flag for {@link #bindService}: automatically create the service as long
* as the binding exists. Note that while this will create the service,
* its {@link android.app.Service#onStartCommand}
@@ -691,6 +701,7 @@ public abstract class Context {
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
+ * Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
*
@@ -700,6 +711,7 @@ public abstract class Context {
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
+ * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
* @see #deleteDatabase
*/
public abstract SQLiteDatabase openOrCreateDatabase(String name,
@@ -716,6 +728,7 @@ public abstract class Context {
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
+ * Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
@@ -726,6 +739,7 @@ public abstract class Context {
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
+ * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
* @see #deleteDatabase
*/
public abstract SQLiteDatabase openOrCreateDatabase(String name,
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index bf10bcb..e999316 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -269,7 +269,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
private void setWalModeFromConfiguration() {
if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
- if (mConfiguration.walEnabled) {
+ if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
setJournalMode("WAL");
setSyncMode(SQLiteGlobal.getWALSyncMode());
} else {
@@ -389,7 +389,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
}
// Remember what changed.
- boolean walModeChanged = configuration.walEnabled != mConfiguration.walEnabled;
+ boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
+ & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
// Update configuration parameters.
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 27c9ee5..0538ce4 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -81,6 +81,7 @@ public final class SQLiteConnectionPool implements Closeable {
private final Object mLock = new Object();
private final AtomicBoolean mConnectionLeaked = new AtomicBoolean();
private final SQLiteDatabaseConfiguration mConfiguration;
+ private int mMaxConnectionPoolSize;
private boolean mIsOpen;
private int mNextConnectionId;
@@ -146,6 +147,7 @@ public final class SQLiteConnectionPool implements Closeable {
private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
mConfiguration = new SQLiteDatabaseConfiguration(configuration);
+ setMaxConnectionPoolSizeLocked();
}
@Override
@@ -257,8 +259,9 @@ public final class SQLiteConnectionPool implements Closeable {
synchronized (mLock) {
throwIfClosedLocked();
- boolean restrictToOneConnection = false;
- if (mConfiguration.walEnabled != configuration.walEnabled) {
+ boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
+ & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
+ if (walModeChanged) {
// 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()) {
@@ -272,15 +275,13 @@ public final class SQLiteConnectionPool implements Closeable {
// 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) {
+ if (walModeChanged) {
closeAvailableConnectionsAndLogExceptionsLocked();
}
@@ -296,9 +297,11 @@ public final class SQLiteConnectionPool implements Closeable {
mAvailablePrimaryConnection = newPrimaryConnection;
mConfiguration.updateParametersFrom(configuration);
+ setMaxConnectionPoolSizeLocked();
} else {
// Reconfigure the database connections in place.
mConfiguration.updateParametersFrom(configuration);
+ setMaxConnectionPoolSizeLocked();
closeExcessConnectionsAndLogExceptionsLocked();
reconfigureAllConnectionsLocked();
@@ -360,8 +363,7 @@ public final class SQLiteConnectionPool implements Closeable {
mAvailablePrimaryConnection = connection;
}
wakeConnectionWaitersLocked();
- } else if (mAvailableNonPrimaryConnections.size() >=
- mConfiguration.maxConnectionPoolSize - 1) {
+ } else if (mAvailableNonPrimaryConnections.size() >= mMaxConnectionPoolSize - 1) {
closeConnectionAndLogExceptionsLocked(connection);
} else {
if (recycleConnectionLocked(connection, status)) {
@@ -499,7 +501,7 @@ public final class SQLiteConnectionPool implements Closeable {
// Can't throw.
private void closeExcessConnectionsAndLogExceptionsLocked() {
int availableCount = mAvailableNonPrimaryConnections.size();
- while (availableCount-- > mConfiguration.maxConnectionPoolSize - 1) {
+ while (availableCount-- > mMaxConnectionPoolSize - 1) {
SQLiteConnection connection =
mAvailableNonPrimaryConnections.remove(availableCount);
closeConnectionAndLogExceptionsLocked(connection);
@@ -874,7 +876,7 @@ public final class SQLiteConnectionPool implements Closeable {
if (mAvailablePrimaryConnection != null) {
openConnections += 1;
}
- if (openConnections >= mConfiguration.maxConnectionPoolSize) {
+ if (openConnections >= mMaxConnectionPoolSize) {
return null;
}
connection = openConnectionLocked(mConfiguration,
@@ -926,6 +928,18 @@ public final class SQLiteConnectionPool implements Closeable {
return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0;
}
+ private void setMaxConnectionPoolSizeLocked() {
+ if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
+ mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
+ } else {
+ // TODO: We don't actually need to restrict the connection pool size to 1
+ // for non-WAL databases. There might be reasons to use connection pooling
+ // with other journal modes. For now, enabling connection pooling and
+ // using WAL are the same thing in the API.
+ mMaxConnectionPoolSize = 1;
+ }
+ }
+
private void throwIfClosedLocked() {
if (!mIsOpen) {
throw new IllegalStateException("Cannot perform this operation "
@@ -972,7 +986,7 @@ public final class SQLiteConnectionPool implements Closeable {
synchronized (mLock) {
printer.println("Connection pool for " + mConfiguration.path + ":");
printer.println(" Open: " + mIsOpen);
- printer.println(" Max connections: " + mConfiguration.maxConnectionPoolSize);
+ printer.println(" Max connections: " + mMaxConnectionPoolSize);
printer.println(" Available primary connection:");
if (mAvailablePrimaryConnection != null) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0ecce4d..049a615 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -232,6 +232,18 @@ public final class SQLiteDatabase extends SQLiteClosable {
public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
/**
+ * Open flag: Flag for {@link #openDatabase} to open the database file with
+ * write-ahead logging enabled by default. Using this flag is more efficient
+ * than calling {@link #enableWriteAheadLogging}.
+ *
+ * Write-ahead logging cannot be used with read-only databases so the value of
+ * this flag is ignored if the database is opened read-only.
+ *
+ * @see #enableWriteAheadLogging
+ */
+ public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
+
+ /**
* Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
*
* Each prepared-statement is between 1K - 6K, depending on the complexity of the
@@ -654,7 +666,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
* @throws SQLiteException if the database cannot be opened
*/
public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {
- return openDatabase(path, factory, flags, new DefaultDatabaseErrorHandler());
+ return openDatabase(path, factory, flags, null);
}
/**
@@ -694,7 +706,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
* Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
*/
public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
- return openDatabase(path, factory, CREATE_IF_NECESSARY);
+ return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
}
/**
@@ -1781,56 +1793,84 @@ public final class SQLiteDatabase extends SQLiteClosable {
}
/**
- * This method enables parallel execution of queries from multiple threads on the same database.
- * It does this by opening multiple handles to the database and using a different
- * database handle for each query.
- * <p>
- * If a transaction is in progress on one connection handle and say, a table is updated in the
- * transaction, then query on the same table on another connection handle will block for the
- * transaction to complete. But this method enables such queries to execute by having them
- * return old version of the data from the table. Most often it is the data that existed in the
- * table prior to the above transaction updates on that table.
+ * This method enables parallel execution of queries from multiple threads on the
+ * same database. It does this by opening multiple connections to the database
+ * and using a different database connection for each query. The database
+ * journal mode is also changed to enable writes to proceed concurrently with reads.
* <p>
- * Maximum number of simultaneous handles used to execute queries in parallel is
+ * When write-ahead logging is not enabled (the default), it is not possible for
+ * reads and writes to occur on the database at the same time. Before modifying the
+ * database, the writer implicitly acquires an exclusive lock on the database which
+ * prevents readers from accessing the database until the write is completed.
+ * </p><p>
+ * In contrast, when write-ahead logging is enabled (by calling this method), write
+ * operations occur in a separate log file which allows reads to proceed concurrently.
+ * While a write is in progress, readers on other threads will perceive the state
+ * of the database as it was before the write began. When the write completes, readers
+ * on other threads will then perceive the new state of the database.
+ * </p><p>
+ * It is a good idea to enable write-ahead logging whenever a database will be
+ * concurrently accessed and modified by multiple threads at the same time.
+ * However, write-ahead logging uses significantly more memory than ordinary
+ * journaling because there are multiple connections to the same database.
+ * So if a database will only be used by a single thread, or if optimizing
+ * concurrency is not very important, then write-ahead logging should be disabled.
+ * </p><p>
+ * After calling this method, execution of queries in parallel is enabled as long as
+ * the database remains open. To disable execution of queries in parallel, either
+ * call {@link #disableWriteAheadLogging} or close the database and reopen it.
+ * </p><p>
+ * The maximum number of connections used to execute queries in parallel is
* dependent upon the device memory and possibly other properties.
- * <p>
- * After calling this method, execution of queries in parallel is enabled as long as this
- * database handle is open. To disable execution of queries in parallel, database should
- * be closed and reopened.
- * <p>
+ * </p><p>
* If a query is part of a transaction, then it is executed on the same database handle the
* transaction was begun.
- * <p>
- * If the database has any attached databases, then execution of queries in paralel is NOT
- * possible. In such cases, a message is printed to logcat and false is returned.
- * <p>
- * This feature is not available for :memory: databases. In such cases,
- * a message is printed to logcat and false is returned.
- * <p>
- * A typical way to use this method is the following:
- * <pre>
- * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
- * CREATE_IF_NECESSARY, myDatabaseErrorHandler);
- * db.enableWriteAheadLogging();
- * </pre>
- * <p>
+ * </p><p>
* Writers should use {@link #beginTransactionNonExclusive()} or
* {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
- * to start a trsnsaction.
- * Non-exclusive mode allows database file to be in readable by threads executing queries.
+ * to start a transaction. Non-exclusive mode allows database file to be in readable
+ * by other threads executing queries.
+ * </p><p>
+ * If the database has any attached databases, then execution of queries in parallel is NOT
+ * possible. Likewise, write-ahead logging is not supported for read-only databases
+ * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false.
+ * </p><p>
+ * The best way to enable write-ahead logging is to pass the
+ * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is
+ * more efficient than calling {@link #enableWriteAheadLogging}.
+ * <code><pre>
+ * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
+ * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
+ * myDatabaseErrorHandler);
+ * db.enableWriteAheadLogging();
+ * </pre></code>
+ * </p><p>
+ * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
+ * after opening the database.
+ * <code><pre>
+ * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
+ * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
+ * db.enableWriteAheadLogging();
+ * </pre></code>
+ * </p><p>
+ * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
+ * more details about how write-ahead logging works.
* </p>
*
- * @return true if write-ahead-logging is set. false otherwise
+ * @return True if write-ahead logging is enabled.
*
* @throws 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.
+ *
+ * @see #ENABLE_WRITE_AHEAD_LOGGING
+ * @see #disableWriteAheadLogging
*/
public boolean enableWriteAheadLogging() {
synchronized (mLock) {
throwIfNotOpenLocked();
- if (mConfigurationLocked.walEnabled) {
+ if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
return true;
}
@@ -1855,14 +1895,11 @@ public final class SQLiteDatabase extends SQLiteClosable {
return false;
}
- final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
- mConfigurationLocked.maxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
- mConfigurationLocked.walEnabled = true;
+ mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
- mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
- mConfigurationLocked.walEnabled = false;
+ mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
throw ex;
}
}
@@ -1875,29 +1912,44 @@ public final class SQLiteDatabase extends SQLiteClosable {
* @throws 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.
+ *
+ * @see #enableWriteAheadLogging
*/
public void disableWriteAheadLogging() {
synchronized (mLock) {
throwIfNotOpenLocked();
- if (!mConfigurationLocked.walEnabled) {
+ if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
return;
}
- final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
- mConfigurationLocked.maxConnectionPoolSize = 1;
- mConfigurationLocked.walEnabled = false;
+ mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
try {
mConnectionPoolLocked.reconfigure(mConfigurationLocked);
} catch (RuntimeException ex) {
- mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
- mConfigurationLocked.walEnabled = true;
+ mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
throw ex;
}
}
}
/**
+ * Returns true if write-ahead logging has been enabled for this database.
+ *
+ * @return True if write-ahead logging has been enabled for this database.
+ *
+ * @see #enableWriteAheadLogging
+ * @see #ENABLE_WRITE_AHEAD_LOGGING
+ */
+ public boolean isWriteAheadLoggingEnabled() {
+ synchronized (mLock) {
+ throwIfNotOpenLocked();
+
+ return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
+ }
+ }
+
+ /**
* Collect statistics about all open databases in the current process.
* Used by bug report.
*/
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index e06a5ee..123c2c6 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -62,14 +62,6 @@ public final class SQLiteDatabaseConfiguration {
public int openFlags;
/**
- * The maximum number of connections to retain in the connection pool.
- * Must be at least 1.
- *
- * Default is 1.
- */
- public int maxConnectionPoolSize;
-
- /**
* The maximum size of the prepared statement cache for each database connection.
* Must be non-negative.
*
@@ -85,13 +77,6 @@ public final class SQLiteDatabaseConfiguration {
public Locale locale;
/**
- * True if WAL mode is enabled.
- *
- * Default is false.
- */
- public boolean walEnabled;
-
- /**
* The custom functions to register.
*/
public final ArrayList<SQLiteCustomFunction> customFunctions =
@@ -114,7 +99,6 @@ public final class SQLiteDatabaseConfiguration {
this.openFlags = openFlags;
// Set default values for optional parameters.
- maxConnectionPoolSize = 1;
maxSqlCacheSize = 25;
locale = Locale.getDefault();
}
@@ -150,10 +134,8 @@ public final class SQLiteDatabaseConfiguration {
}
openFlags = other.openFlags;
- maxConnectionPoolSize = other.maxConnectionPoolSize;
maxSqlCacheSize = other.maxSqlCacheSize;
locale = other.locale;
- walEnabled = other.walEnabled;
customFunctions.clear();
customFunctions.addAll(other.customFunctions);
}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index ffa4663..fe37b8f 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -58,6 +58,7 @@ public abstract class SQLiteOpenHelper {
private SQLiteDatabase mDatabase;
private boolean mIsInitializing;
+ private boolean mEnableWriteAheadLogging;
private final DatabaseErrorHandler mErrorHandler;
/**
@@ -74,7 +75,7 @@ public abstract class SQLiteOpenHelper {
* newer, {@link #onDowngrade} will be used to downgrade the database
*/
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
- this(context, name, factory, version, new DefaultDatabaseErrorHandler());
+ this(context, name, factory, version, null);
}
/**
@@ -92,14 +93,11 @@ public abstract class SQLiteOpenHelper {
* {@link #onUpgrade} will be used to upgrade the database; if the database is
* newer, {@link #onDowngrade} will be used to downgrade the database
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
- * corruption.
+ * corruption, or null to use the default error handler.
*/
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler) {
if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
- if (errorHandler == null) {
- throw new IllegalArgumentException("DatabaseErrorHandler param value can't be null.");
- }
mContext = context;
mName = name;
@@ -117,6 +115,32 @@ public abstract class SQLiteOpenHelper {
}
/**
+ * Enables or disables the use of write-ahead logging for the database.
+ *
+ * Write-ahead logging cannot be used with read-only databases so the value of
+ * this flag is ignored if the database is opened read-only.
+ *
+ * @param enabled True if write-ahead logging should be enabled, false if it
+ * should be disabled.
+ *
+ * @see SQLiteDatabase#enableWriteAheadLogging()
+ */
+ public void setWriteAheadLoggingEnabled(boolean enabled) {
+ synchronized (this) {
+ if (mEnableWriteAheadLogging != enabled) {
+ if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
+ if (enabled) {
+ mDatabase.enableWriteAheadLogging();
+ } else {
+ mDatabase.disableWriteAheadLogging();
+ }
+ }
+ mEnableWriteAheadLogging = enabled;
+ }
+ }
+ }
+
+ /**
* Create and/or open a database that will be used for reading and writing.
* The first time this is called, the database will be opened and
* {@link #onCreate}, {@link #onUpgrade} and/or {@link #onOpen} will be
@@ -197,7 +221,9 @@ public abstract class SQLiteOpenHelper {
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
} else {
- db = mContext.openOrCreateDatabase(mName, 0, mFactory, mErrorHandler);
+ db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
+ Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
+ mFactory, mErrorHandler);
}
} catch (SQLiteException ex) {
if (writable) {