summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2018-09-25 15:12:15 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-09-25 15:12:15 +0000
commit0f88f865bdce7cb15dc9872a2728cd593d5ac66e (patch)
tree17fb4348f68a2355e238f7b0e994fd651c5ed9e7
parent45fda272111f43fe570540e9cf75772efa5c6cff (diff)
parent0939c5a2b313d7fc32ca5e1a6c161b0089e141e9 (diff)
Merge "Truncate(*1) it if WAL file is too big when opening DB" into pi-dev
-rw-r--r--core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java15
-rw-r--r--core/java/android/database/sqlite/SQLiteConnection.java36
-rw-r--r--core/java/android/database/sqlite/SQLiteGlobal.java17
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java6
7 files changed, 81 insertions, 0 deletions
diff --git a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
index 5bf3a7c43640..06c069c583b5 100644
--- a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
+++ b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
@@ -41,6 +41,7 @@ public class SQLiteCompatibilityWalFlags {
private static volatile boolean sFlagsSet;
private static volatile boolean sCompatibilityWalSupported;
private static volatile String sWALSyncMode;
+ private static volatile long sTruncateSize = -1;
// This flag is used to avoid recursive initialization due to circular dependency on Settings
private static volatile boolean sCallingGlobalSettings;
@@ -71,6 +72,19 @@ public class SQLiteCompatibilityWalFlags {
return sWALSyncMode;
}
+ /**
+ * Override {@link com.android.internal.R.integer#db_wal_truncate_size}.
+ *
+ * @return the value set in the global setting, or -1 if a value is not set.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static long getTruncateSize() {
+ initIfNeeded();
+ return sTruncateSize;
+ }
+
private static void initIfNeeded() {
if (sInitialized || sCallingGlobalSettings) {
return;
@@ -115,6 +129,7 @@ public class SQLiteCompatibilityWalFlags {
sCompatibilityWalSupported = parser.getBoolean("compatibility_wal_supported",
SQLiteGlobal.isCompatibilityWalSupported());
sWALSyncMode = parser.getString("wal_syncmode", SQLiteGlobal.getWALSyncMode());
+ sTruncateSize = parser.getInt("truncate_size", -1);
Log.i(TAG, "Read compatibility WAL flags: compatibility_wal_supported="
+ sCompatibilityWalSupported + ", wal_syncmode=" + sWALSyncMode);
sFlagsSet = true;
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 101fb821f4ce..9c639a5a9867 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -32,6 +32,7 @@ import android.util.Printer;
import dalvik.system.BlockGuard;
import dalvik.system.CloseGuard;
+import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -303,6 +304,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
} else {
setSyncMode(SQLiteGlobal.getWALSyncMode());
}
+ maybeTruncateWalFile();
} else {
setJournalMode(mConfiguration.journalMode == null
? SQLiteGlobal.getDefaultJournalMode() : mConfiguration.journalMode);
@@ -312,6 +314,40 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
}
}
+ /**
+ * If the WAL file exists and larger than a threshold, truncate it by executing
+ * PRAGMA wal_checkpoint.
+ */
+ private void maybeTruncateWalFile() {
+ final long threshold = SQLiteGlobal.getWALTruncateSize();
+ if (DEBUG) {
+ Log.d(TAG, "Truncate threshold=" + threshold);
+ }
+ if (threshold == 0) {
+ return;
+ }
+
+ final File walFile = new File(mConfiguration.path + "-wal");
+ if (!walFile.isFile()) {
+ return;
+ }
+ final long size = walFile.length();
+ if (size < threshold) {
+ if (DEBUG) {
+ Log.d(TAG, walFile.getAbsolutePath() + " " + size + " bytes: No need to truncate");
+ }
+ return;
+ }
+
+ Log.i(TAG, walFile.getAbsolutePath() + " " + size + " bytes: Bigger than "
+ + threshold + "; truncating");
+ try {
+ executeForString("PRAGMA wal_checkpoint(TRUNCATE)", null, null);
+ } catch (SQLiteException e) {
+ Log.w(TAG, "Failed to truncate the -wal file", e);
+ }
+ }
+
private void setSyncMode(String newValue) {
String value = executeForString("PRAGMA synchronous", null, null);
if (!canonicalizeSyncMode(value).equalsIgnoreCase(
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index e6b6acf7b8ee..67e5f65d5a1f 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -164,4 +164,21 @@ public final class SQLiteGlobal {
com.android.internal.R.integer.db_default_idle_connection_timeout));
}
+ /**
+ * When opening a database, if the WAL file is larger than this size, we'll truncate it.
+ *
+ * (If it's 0, we do not truncate.)
+ *
+ * @hide
+ */
+ public static long getWALTruncateSize() {
+ final long setting = SQLiteCompatibilityWalFlags.getTruncateSize();
+ if (setting >= 0) {
+ return setting;
+ }
+ return SystemProperties.getInt("debug.sqlite.wal.truncatesize",
+ Resources.getSystem().getInteger(
+ com.android.internal.R.integer.db_wal_truncate_size));
+ }
+
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index fbe6f3ee7dff..e00ff205c082 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12777,6 +12777,7 @@ public final class Settings {
* Supported keys:
* compatibility_wal_supported (boolean)
* wal_syncmode (String)
+ * truncate_size (int)
*
* @hide
*/
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a9d69c1bcbbe..a10c1975339d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1873,6 +1873,10 @@
truncate it after committing the transaction. -->
<integer name="db_journal_size_limit">524288</integer>
+ <!-- When opening a database with WAL enabled and if the wal file already exists and larger
+ than this size in bytes, we'll truncate it. -->
+ <integer name="db_wal_truncate_size">1048576</integer>
+
<!-- The database synchronization mode when using the default journal mode.
FULL is safest and preserves durability at the cost of extra fsyncs.
NORMAL also preserves durability in non-WAL modes and uses checksums to ensure
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a3ed1b0526d0..95af9a602577 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3415,4 +3415,6 @@
<java-symbol type="string" name="config_misprovisionedDeviceModel" />
<java-symbol type="string" name="config_misprovisionedBrandValue" />
+
+ <java-symbol type="integer" name="db_wal_truncate_size" />
</resources>
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
index 230655de8a00..551a58ed7cb5 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
@@ -62,18 +62,24 @@ public class SQLiteCompatibilityWalFlagsTest {
assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
assertFalse(SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
assertEquals("OFF", SQLiteCompatibilityWalFlags.getWALSyncMode());
+ assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
SQLiteCompatibilityWalFlags.init("wal_syncmode=VALUE");
assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
assertEquals(SQLiteGlobal.isCompatibilityWalSupported(),
SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
assertEquals("VALUE", SQLiteCompatibilityWalFlags.getWALSyncMode());
+ assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
SQLiteCompatibilityWalFlags.init("compatibility_wal_supported=true");
assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
assertEquals(SQLiteGlobal.getWALSyncMode(),
SQLiteCompatibilityWalFlags.getWALSyncMode());
assertTrue(SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
+ assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
+
+ SQLiteCompatibilityWalFlags.init("truncate_size=1024");
+ assertEquals(1024, SQLiteCompatibilityWalFlags.getTruncateSize());
SQLiteCompatibilityWalFlags.reset();
SQLiteCompatibilityWalFlags.init("Invalid value");