Merge "Truncate(*1) it if WAL file is too big when opening DB" into pi-dev

This commit is contained in:
Makoto Onuki
2018-09-25 15:12:15 +00:00
committed by Android (Google) Code Review
7 changed files with 81 additions and 0 deletions

View File

@@ -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;

View File

@@ -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(

View File

@@ -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));
}
}

View File

@@ -12777,6 +12777,7 @@ public final class Settings {
* Supported keys:
* compatibility_wal_supported (boolean)
* wal_syncmode (String)
* truncate_size (int)
*
* @hide
*/

View File

@@ -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

View File

@@ -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>

View File

@@ -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");