Keystore2: Stop using WAL mode
WAL mode attempts to open an additional file for use as a shared memory mechanism. If storage is too full, then the database fails to open. Remove the use of WAL mode so that keystore can perform read-only transactions on the database and startup even on a full disk. Disabling WAL mode shows about a 5% performance drop on a synthetic test that creates and destroys 5000 AES keys. Bug: 190142197 Test: keystore2_test Change-Id: I9b1cb7e6398e07fa9f02f0ba4e9eb48313c06472 Merged-In: I9b1cb7e6398e07fa9f02f0ba4e9eb48313c06472
This commit is contained in:
parent
ee5c643f54
commit
fbe5cf545c
3 changed files with 1 additions and 65 deletions
|
@ -831,20 +831,6 @@ impl KeystoreDB {
|
|||
/// Name of the file that holds the cross-boot persistent database.
|
||||
pub const PERSISTENT_DB_FILENAME: &'static str = &"persistent.sqlite";
|
||||
|
||||
/// Set write-ahead logging mode on the persistent database found in `db_root`.
|
||||
pub fn set_wal_mode(db_root: &Path) -> Result<()> {
|
||||
let path = Self::make_persistent_path(&db_root)?;
|
||||
let conn =
|
||||
Connection::open(path).context("In KeystoreDB::set_wal_mode: Failed to open DB")?;
|
||||
let mode: String = conn
|
||||
.pragma_update_and_check(None, "journal_mode", &"WAL", |row| row.get(0))
|
||||
.context("In KeystoreDB::set_wal_mode: Failed to set journal_mode")?;
|
||||
match mode.as_str() {
|
||||
"wal" => Ok(()),
|
||||
_ => Err(anyhow!("Unable to set WAL mode, db is still in {} mode.", mode)),
|
||||
}
|
||||
}
|
||||
|
||||
/// This will create a new database connection connecting the two
|
||||
/// files persistent.sqlite and perboot.sqlite in the given directory.
|
||||
/// It also attempts to initialize all of the tables.
|
||||
|
@ -3244,7 +3230,6 @@ mod tests {
|
|||
use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
|
||||
Timestamp::Timestamp,
|
||||
};
|
||||
use rusqlite::DatabaseName::Attached;
|
||||
use rusqlite::NO_PARAMS;
|
||||
use rusqlite::TransactionBehavior;
|
||||
use std::cell::RefCell;
|
||||
|
@ -5761,28 +5746,6 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_wal_mode() -> Result<()> {
|
||||
let temp_dir = TempDir::new("test_set_wal_mode")?;
|
||||
let mut db = KeystoreDB::new(temp_dir.path(), None)?;
|
||||
let mode: String =
|
||||
db.conn.pragma_query_value(Some(Attached("persistent")), "journal_mode", |row| {
|
||||
row.get(0)
|
||||
})?;
|
||||
assert_eq!(mode, "delete");
|
||||
db.conn.close().expect("Close didn't work");
|
||||
|
||||
KeystoreDB::set_wal_mode(temp_dir.path())?;
|
||||
|
||||
db = KeystoreDB::new(temp_dir.path(), None)?;
|
||||
let mode: String =
|
||||
db.conn.pragma_query_value(Some(Attached("persistent")), "journal_mode", |row| {
|
||||
row.get(0)
|
||||
})?;
|
||||
assert_eq!(mode, "wal");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_key_descriptor() -> Result<()> {
|
||||
let mut db = new_test_db()?;
|
||||
|
|
|
@ -44,7 +44,6 @@ use std::{cell::RefCell, sync::Once};
|
|||
use std::{collections::HashMap, path::Path, path::PathBuf};
|
||||
|
||||
static DB_INIT: Once = Once::new();
|
||||
static DB_SET_WAL_MODE: Once = Once::new();
|
||||
|
||||
/// Open a connection to the Keystore 2.0 database. This is called during the initialization of
|
||||
/// the thread local DB field. It should never be called directly. The first time this is called
|
||||
|
@ -57,12 +56,6 @@ static DB_SET_WAL_MODE: Once = Once::new();
|
|||
pub fn create_thread_local_db() -> KeystoreDB {
|
||||
let db_path = DB_PATH.read().expect("Could not get the database directory.");
|
||||
|
||||
DB_SET_WAL_MODE.call_once(|| {
|
||||
log::info!("Setting Keystore 2.0 database to WAL mode first time since boot.");
|
||||
KeystoreDB::set_wal_mode(&db_path)
|
||||
.expect("In create_thread_local_db: Could not set WAL mode.");
|
||||
});
|
||||
|
||||
let mut db = KeystoreDB::new(&db_path, Some(GC.clone())).expect("Failed to open database.");
|
||||
|
||||
DB_INIT.call_once(|| {
|
||||
|
|
|
@ -22,7 +22,7 @@ use android_security_vpnprofilestore::binder::{
|
|||
BinderFeatures, ExceptionCode, Result as BinderResult, Status as BinderStatus, Strong,
|
||||
ThreadState,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use anyhow::{Context, Result};
|
||||
use keystore2::{async_task::AsyncTask, legacy_blob::LegacyBlobLoader, utils::watchdog as wd};
|
||||
use rusqlite::{
|
||||
params, Connection, OptionalExtension, Transaction, TransactionBehavior, NO_PARAMS,
|
||||
|
@ -30,22 +30,14 @@ use rusqlite::{
|
|||
use std::{
|
||||
collections::HashSet,
|
||||
path::{Path, PathBuf},
|
||||
sync::Once,
|
||||
};
|
||||
|
||||
static DB_SET_WAL_MODE: Once = Once::new();
|
||||
|
||||
struct DB {
|
||||
conn: Connection,
|
||||
}
|
||||
|
||||
impl DB {
|
||||
fn new(db_file: &Path) -> Result<Self> {
|
||||
DB_SET_WAL_MODE.call_once(|| {
|
||||
log::info!("Setting VpnProfileStore database to WAL mode first time since boot.");
|
||||
Self::set_wal_mode(&db_file).expect("In vpnprofilestore: Could not set WAL mode.");
|
||||
});
|
||||
|
||||
let mut db = Self {
|
||||
conn: Connection::open(db_file).context("Failed to initialize SQLite connection.")?,
|
||||
};
|
||||
|
@ -54,18 +46,6 @@ impl DB {
|
|||
Ok(db)
|
||||
}
|
||||
|
||||
fn set_wal_mode(db_file: &Path) -> Result<()> {
|
||||
let conn = Connection::open(db_file)
|
||||
.context("In VpnProfileStore set_wal_mode: Failed to open DB.")?;
|
||||
let mode: String = conn
|
||||
.pragma_update_and_check(None, "journal_mode", &"WAL", |row| row.get(0))
|
||||
.context("In VpnProfileStore set_wal_mode: Failed to set journal_mode")?;
|
||||
match mode.as_str() {
|
||||
"wal" => Ok(()),
|
||||
_ => Err(anyhow!("Unable to set WAL mode, db is still in {} mode.", mode)),
|
||||
}
|
||||
}
|
||||
|
||||
fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
|
||||
where
|
||||
F: Fn(&Transaction) -> Result<T>,
|
||||
|
|
Loading…
Reference in a new issue