diff --git a/cli/main.rs b/cli/main.rs index 700e0a098..3ef3d6774 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -1,12 +1,7 @@ -use anyhow::Result; use clap::{Parser, ValueEnum}; use cli_table::{Cell, Table}; -use lig_core::{Database, DatabaseRef, Value}; +use lig_core::{Database, Value, SyncIO}; use rustyline::{error::ReadlineError, DefaultEditor}; -use std::cell::RefCell; -use std::collections::HashMap; -use std::fs::File; -use std::io::{Read, Seek}; use std::path::PathBuf; use std::sync::Arc; @@ -35,7 +30,7 @@ struct Opts { fn main() -> anyhow::Result<()> { let opts = Opts::parse(); - let io = IO::new(); + let io = SyncIO::new(); let db = Database::open(Arc::new(io), opts.database.to_str().unwrap())?; let conn = db.connect(); let mut rl = DefaultEditor::new()?; @@ -108,47 +103,3 @@ fn main() -> anyhow::Result<()> { Ok(()) } -struct IO { - inner: RefCell, -} - -struct IOInner { - db_refs: usize, - db_files: HashMap, -} - -impl lig_core::IO for IO { - fn open(&self, path: &str) -> Result { - let file = std::fs::File::open(path)?; - let mut inner = self.inner.borrow_mut(); - let db_ref = inner.db_refs; - inner.db_refs += 1; - inner.db_files.insert(db_ref, file); - Ok(db_ref) - } - - fn get(&self, database_ref: DatabaseRef, page_idx: usize, buf: &mut [u8]) -> Result<()> { - let page_size = buf.len(); - assert!(page_idx > 0); - assert!(page_size >= 512); - assert!(page_size <= 65536); - assert!((page_size & (page_size - 1)) == 0); - let mut inner = self.inner.borrow_mut(); - let file = inner.db_files.get_mut(&database_ref).unwrap(); - let pos = (page_idx - 1) * page_size; - file.seek(std::io::SeekFrom::Start(pos as u64))?; - file.read_exact(buf)?; - Ok(()) - } -} - -impl IO { - fn new() -> Self { - Self { - inner: RefCell::new(IOInner { - db_refs: 0, - db_files: HashMap::new(), - }), - } - } -} diff --git a/core/benches/benchmark.rs b/core/benches/benchmark.rs index 23f3266f9..59b33bd49 100644 --- a/core/benches/benchmark.rs +++ b/core/benches/benchmark.rs @@ -1,61 +1,11 @@ -use anyhow::Result; use criterion::{criterion_group, criterion_main, Criterion, Throughput}; -use lig_core::{Database, DatabaseRef}; +use lig_core::{Database, SyncIO}; use pprof::criterion::{Output, PProfProfiler}; -use std::cell::RefCell; -use std::collections::HashMap; -use std::fs::File; -use std::io::{Read, Seek}; use std::sync::Arc; -struct IO { - inner: RefCell, -} - -struct IOInner { - db_refs: usize, - db_files: HashMap, -} - -impl lig_core::IO for IO { - fn open(&self, path: &str) -> Result { - println!("Opening database file {}", path); - let file = std::fs::File::open(path)?; - let mut inner = self.inner.borrow_mut(); - let db_ref = inner.db_refs; - inner.db_refs += 1; - inner.db_files.insert(db_ref, file); - Ok(db_ref) - } - - fn get(&self, database_ref: DatabaseRef, page_idx: usize, buf: &mut [u8]) -> Result<()> { - let page_size = buf.len(); - assert!(page_idx > 0); - assert!(page_size >= 512); - assert!(page_size <= 65536); - assert!((page_size & (page_size - 1)) == 0); - let mut inner = self.inner.borrow_mut(); - let file = inner.db_files.get_mut(&database_ref).unwrap(); - let pos = (page_idx - 1) * page_size; - file.seek(std::io::SeekFrom::Start(pos as u64))?; - file.read_exact(buf)?; - Ok(()) - } -} - -impl IO { - fn new() -> Self { - Self { - inner: RefCell::new(IOInner { - db_refs: 0, - db_files: HashMap::new(), - }), - } - } -} fn bench_db() -> Database { - let io = IO::new(); + let io = SyncIO::new(); Database::open(Arc::new(io), "../testing/hello.db").unwrap() } diff --git a/core/io/mod.rs b/core/io/mod.rs new file mode 100644 index 000000000..5678c41b5 --- /dev/null +++ b/core/io/mod.rs @@ -0,0 +1 @@ +pub(crate) mod sync_io; diff --git a/core/io/sync_io.rs b/core/io/sync_io.rs new file mode 100644 index 000000000..385dd96c0 --- /dev/null +++ b/core/io/sync_io.rs @@ -0,0 +1,53 @@ +use crate::{DatabaseRef, IO}; + +use std::io::{Read, Seek}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::fs::File; +use anyhow::Result; + +/// Synchronous I/O using traditional read() and write() system calls. +pub struct SyncIO { + inner: RefCell, +} + +struct SyncIOInner { + db_refs: usize, + db_files: HashMap, +} + +impl IO for SyncIO { + fn open(&self, path: &str) -> Result { + let file = std::fs::File::open(path)?; + let mut inner = self.inner.borrow_mut(); + let db_ref = inner.db_refs; + inner.db_refs += 1; + inner.db_files.insert(db_ref, file); + Ok(db_ref) + } + + fn get(&self, database_ref: DatabaseRef, page_idx: usize, buf: &mut [u8]) -> Result<()> { + let page_size = buf.len(); + assert!(page_idx > 0); + assert!(page_size >= 512); + assert!(page_size <= 65536); + assert!((page_size & (page_size - 1)) == 0); + let mut inner = self.inner.borrow_mut(); + let file = inner.db_files.get_mut(&database_ref).unwrap(); + let pos = (page_idx - 1) * page_size; + file.seek(std::io::SeekFrom::Start(pos as u64))?; + file.read_exact(buf)?; + Ok(()) + } +} + +impl SyncIO { + pub fn new() -> Self { + Self { + inner: RefCell::new(SyncIOInner { + db_refs: 0, + db_files: HashMap::new(), + }), + } + } +} diff --git a/core/lib.rs b/core/lib.rs index 0781c52ee..3ebf67b34 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -5,6 +5,7 @@ mod schema; mod sqlite3_ondisk; mod types; mod vdbe; +mod io; use mimalloc::MiMalloc; @@ -18,6 +19,7 @@ use schema::Schema; use sqlite3_parser::{ast::Cmd, lexer::sql::Parser}; use std::{borrow::BorrowMut, sync::Arc}; +pub use io::sync_io::SyncIO; pub use types::Value; pub struct Database {