diff options
| author | 2017-10-25 16:09:35 -0700 | |
|---|---|---|
| committer | 2017-10-26 11:21:19 -0700 | |
| commit | 5bd43ad2e7e4e1ee2c31d920ba4b148bbdf74d11 (patch) | |
| tree | 5e89bd4ae207a4564f5df8f2d67eeba5fb555b0d | |
| parent | 75dcc4f040199f410e680fc5938aeae53c501d7a (diff) | |
Initial version of compatibility WAL
In this mode, only database journal mode will be changed, connection pool
size will still be limited to a single connection.
If enabled, compatibility WAL mode will be used if an app hasn't explicitly
requested journal mode, by calling disable/enableWriteAheadLogging.
Compatibility WAL mode is controlled by debug.sqlite.use_compatibility_wal
property and db_use_compatibility_wal config resource.
Impact on write performance:
On ext4, with WAL, there is approx 300% increase in speed of update operations
On f2fs, with WAL, there is approx 5% increase in speed of update operations
Impact on number of writes:
On ext4, switching to WAL reduces the number of writes by approx 50%.
On f2fs, switching to WAL increases the number of writes by approx 15%.
Test: CtsDatabaseTestCases
Test: manual, running device
Bug: 33044236
Change-Id: Iaffb5651df39d8c9f710d7dbbe174f9c0d8a3186
| -rw-r--r-- | core/java/android/database/sqlite/SQLiteConnection.java | 4 | ||||
| -rw-r--r-- | core/java/android/database/sqlite/SQLiteDatabase.java | 11 | ||||
| -rw-r--r-- | core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java | 10 | ||||
| -rw-r--r-- | core/java/android/database/sqlite/SQLiteGlobal.java | 11 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 5 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 1 |
6 files changed, 39 insertions, 3 deletions
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index c28583ea867a..361b81b77f1d 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -289,7 +289,9 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen private void setWalModeFromConfiguration() { if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) { - if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) { + boolean walEnabled = + (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0; + if (walEnabled || mConfiguration.useCompatibilityWal) { setJournalMode("WAL"); setSyncMode(SQLiteGlobal.getWALSyncMode()); } else { diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index df0e262b712f..83b8dc76bfc3 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -285,6 +285,7 @@ public final class SQLiteDatabase extends SQLiteClosable { } } mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs; + mConfigurationLocked.useCompatibilityWal = SQLiteGlobal.isCompatibilityWalSupported(); } @Override @@ -2070,15 +2071,21 @@ public final class SQLiteDatabase extends SQLiteClosable { synchronized (mLock) { throwIfNotOpenLocked(); - if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) { + final boolean oldUseCompatibilityWal = mConfigurationLocked.useCompatibilityWal; + final int oldFlags = mConfigurationLocked.openFlags; + if (!oldUseCompatibilityWal && (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) { return; } mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING; + // If an app explicitly disables WAL, do not even use compatibility mode + mConfigurationLocked.useCompatibilityWal = false; + try { mConnectionPoolLocked.reconfigure(mConfigurationLocked); } catch (RuntimeException ex) { - mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING; + mConfigurationLocked.openFlags = oldFlags; + mConfigurationLocked.useCompatibilityWal = oldUseCompatibilityWal; throw ex; } } diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java index 34c9b3395d1a..905da7247308 100644 --- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java +++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java @@ -111,6 +111,15 @@ public final class SQLiteDatabaseConfiguration { public long idleConnectionTimeoutMs = Long.MAX_VALUE; /** + * Enables compatibility WAL mode. Applications cannot explicitly choose compatibility WAL mode, + * therefore it is not exposed as a flag. + * + * <p>In this mode, only database journal mode will be changed, connection pool + * size will still be limited to a single connection. + */ + public boolean useCompatibilityWal; + + /** * Creates a database configuration with the required parameters for opening a * database and default values for all other parameters. * @@ -170,6 +179,7 @@ public final class SQLiteDatabaseConfiguration { lookasideSlotSize = other.lookasideSlotSize; lookasideSlotCount = other.lookasideSlotCount; idleConnectionTimeoutMs = other.idleConnectionTimeoutMs; + useCompatibilityWal = other.useCompatibilityWal; } /** diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java index 94d5555c4c24..bb2a51706767 100644 --- a/core/java/android/database/sqlite/SQLiteGlobal.java +++ b/core/java/android/database/sqlite/SQLiteGlobal.java @@ -81,6 +81,17 @@ public final class SQLiteGlobal { } /** + * Returns true if compatibility WAL mode is supported. In this mode, only + * database journal mode is changed. Connection pool will use at most one connection. + * @hide + */ + public static boolean isCompatibilityWalSupported() { + return SystemProperties.getBoolean("debug.sqlite.compatibility_wal_supported", + Resources.getSystem().getBoolean( + com.android.internal.R.bool.db_compatibility_wal_supported)); + } + + /** * Gets the journal size limit in bytes. */ public static int getJournalSizeLimit() { diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 571aad9bdafa..f727dd5e543e 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1686,6 +1686,11 @@ a transaction, so it interacts poorly with SECURE_DELETE. --> <string name="db_default_journal_mode" translatable="false">TRUNCATE</string> + <!-- Enables compatibility WAL mode. + In this mode, only database journal mode will be changed, connection pool + size will still be limited to a single connection. --> + <bool name="db_compatibility_wal_supported">true</bool> + <!-- Maximum size of the persistent journal file in bytes. If the journal file grows to be larger than this amount then SQLite will truncate it after committing the transaction. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 896de53cbc4e..8899f28c4a49 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -666,6 +666,7 @@ <java-symbol type="string" name="date_time" /> <java-symbol type="string" name="date_time_set" /> <java-symbol type="string" name="date_time_done" /> + <java-symbol type="bool" name="db_compatibility_wal_supported" /> <java-symbol type="string" name="db_default_journal_mode" /> <java-symbol type="string" name="db_default_sync_mode" /> <java-symbol type="string" name="db_wal_sync_mode" /> |