Repository: servo/servo
File: components/storage/indexeddb/engines/sqlite.rs (Rust)

Code before:
        let rows_affected = self.connection.execute(
            "UPDATE database SET version = ?",
            params![i64::from_ne_bytes(version.to_ne_bytes())],
        )?;
        if rows_affected == 0 {
            return Err(Error::QueryReturnedNoRows);
        }
        Ok(())
    }
}

fn get_db_status(connection: &Connection, op: i32) -> Result<i32, i32> {
    let mut p_curr = 0;
    let mut p_hiwater = 0;
    let res = unsafe {
        rusqlite::ffi::sqlite3_db_status(connection.handle(), op, &mut p_curr, &mut p_hiwater, 0)
    };
    if res != 0 { Err(res) } else { Ok(p_curr) }
}

impl MallocSizeOf for SqliteEngine {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        self.created_db_path.size_of(ops) +
            get_db_status(
                &self.connection,
                rusqlite::ffi::SQLITE_DBSTATUS_LOOKASIDE_USED,
            )
            .unwrap_or_default() as usize +
            get_db_status(
                &self.connection,
                rusqlite::ffi::SQLITE_DBSTATUS_CACHE_USED_SHARED,
            )
            .unwrap_or_default() as usize +
            get_db_status(&self.connection, rusqlite::ffi::SQLITE_DBSTATUS_SCHEMA_USED)
                .unwrap_or_default() as usize +
            get_db_status(&self.connection, rusqlite::ffi::SQLITE_DBSTATUS_STMT_USED)
                .unwrap_or_default() as usize
    }
}

#[cfg(test)]
mod tests {
    use std::collections::VecDeque;
    use std::sync::Arc;

    use base::generic_channel::{self, GenericReceiver, GenericSender};
    use base::threadpool::ThreadPool;
    use profile_traits::generic_callback::GenericCallback;
    use profile_traits::time::ProfilerChan;
    use serde::{Deserialize, Serialize};
    use servo_url::ImmutableOrigin;

Review comment (suggestion):
I wonder if this is a bit misleading, because the Lookaside memory is all pre-allocated and this only tells us how much of that memory is being used. The total memory use would be based on the number of DB connections we have times the configured size of the lookaside.

Code after:
        self.created_db_path.size_of(ops) +
            DEFAULT_LOOKASIDE_SIZE +
            get_db_status(
                &self.connection,
                rusqlite::ffi::SQLITE_DBSTATUS_CACHE_USED_SHARED,
            )
            .unwrap_or_default() as usize +
            get_db_status(&self.connection, rusqlite::ffi::SQLITE_DBSTATUS_SCHEMA_USED)
                .unwrap_or_default() as usize +
            get_db_status(&self.connection, rusqlite::ffi::SQLITE_DBSTATUS_STMT_USED)
                .unwrap_or_default() as usize
    }
}

#[cfg(test)]
mod tests {
    use std::collections::VecDeque;
    use std::sync::Arc;

    use base::generic_channel::{self, GenericReceiver, GenericSender};
    use base::threadpool::ThreadPool;
    use profile_traits::generic_callback::GenericCallback;
    use profile_traits::time::ProfilerChan;
    use serde::{Deserialize, Serialize};
    use servo_url::ImmutableOrigin;
    use storage_traits::indexeddb::{
        AsyncOperation, AsyncReadOnlyOperation, AsyncReadWriteOperation, CreateObjectResult,
        IndexedDBKeyRange, IndexedDBKeyType, IndexedDBTxnMode, KeyPath, PutItemResult,
    };
    use url::Host;

    use crate::indexeddb::IndexedDBDescription;
    use crate::indexeddb::engines::{KvsEngine, KvsOperation, KvsTransaction, SqliteEngine};

    fn test_origin() -> ImmutableOrigin {
        ImmutableOrigin::Tuple(
            "test_origin".to_string(),
            Host::Domain("localhost".to_string()),
            80,
        )
    }

    fn get_pool() -> Arc<ThreadPool> {
        Arc::new(ThreadPool::new(1, "test".to_string()))
    }

    #[test]
    fn test_cycle() {
        let base_dir = tempfile::tempdir().expect("Failed to create temp dir");
        let thread_pool = get_pool();
        // Test create