Merge "Truncate(*1) it if WAL file is too big when opening DB" into pi-dev
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12777,6 +12777,7 @@ public final class Settings {
|
||||
* Supported keys:
|
||||
* compatibility_wal_supported (boolean)
|
||||
* wal_syncmode (String)
|
||||
* truncate_size (int)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user