summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-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) {