From 44dcd480715ac086895b5913e13ed731dd415239 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sun, 14 Jan 2024 15:26:13 +0200 Subject: [PATCH] Fix WebAssembly build --- bindings/wasm/lib.rs | 19 ++++++++++++++++--- cli/main.rs | 4 ++-- core/io/darwin.rs | 22 ++++++++++++---------- core/io/linux.rs | 22 ++++++++++++---------- core/io/mod.rs | 15 +++++++++++++-- core/lib.rs | 14 +++++++------- core/pager.rs | 12 ++++++------ core/sqlite3_ondisk.rs | 10 +++++----- core/storage.rs | 20 +++++++++++--------- 9 files changed, 84 insertions(+), 54 deletions(-) diff --git a/bindings/wasm/lib.rs b/bindings/wasm/lib.rs index 81b93480f..acfabc2b5 100644 --- a/bindings/wasm/lib.rs +++ b/bindings/wasm/lib.rs @@ -10,15 +10,28 @@ pub struct Database { #[wasm_bindgen] impl Database { pub fn open(_path: &str) -> Database { - let storage = limbo_core::Storage::from_io(Arc::new(IO {})); - let inner = limbo_core::Database::open(storage).unwrap(); + let io = Arc::new(IO {}); + let page_source = limbo_core::PageSource::from_io(Arc::new(PageIO {})); + let inner = limbo_core::Database::open(io, page_source).unwrap(); Database { _inner: inner } } } pub struct IO {} -impl limbo_core::StorageIO for IO { +impl limbo_core::IO for IO { + fn open_file(&self, _path: &str) -> Result> { + todo!(); + } + + fn run_once(&self) -> Result<()> { + todo!(); + } +} + +pub struct PageIO {} + +impl limbo_core::PageIO for PageIO { fn get(&self, _page_idx: usize, _c: Arc) -> Result<()> { todo!(); } diff --git a/cli/main.rs b/cli/main.rs index 04a6f5e5d..d380ae014 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -2,7 +2,7 @@ use clap::{Parser, ValueEnum}; use cli_table::{Cell, Table}; use limbo_core::{Database, RowResult, Value}; use rustyline::{error::ReadlineError, DefaultEditor}; -use std::path::PathBuf; +use std::{path::PathBuf, sync::Arc}; #[derive(ValueEnum, Copy, Clone, Debug, PartialEq, Eq)] enum OutputMode { @@ -31,7 +31,7 @@ struct Opts { fn main() -> anyhow::Result<()> { let opts = Opts::parse(); let path = opts.database.to_str().unwrap(); - let io = limbo_core::IO::new()?; + let io = Arc::new(limbo_core::PlatformIO::new()?); let db = Database::open_file(io, path)?; let conn = db.connect(); if let Some(sql) = opts.sql { diff --git a/core/io/darwin.rs b/core/io/darwin.rs index 578263813..328aa8a25 100644 --- a/core/io/darwin.rs +++ b/core/io/darwin.rs @@ -1,34 +1,36 @@ -use super::Completion; +use super::{Completion, File, IO}; use anyhow::{Ok, Result}; use std::sync::Arc; use std::cell::RefCell; use std::io::{Read, Seek}; -pub struct IO {} +pub struct DarwinIO {} -impl IO { +impl DarwinIO { pub fn new() -> Result { Ok(Self {}) } +} - pub fn open_file(&self, path: &str) -> Result { +impl IO for DarwinIO { + fn open_file(&self, path: &str) -> Result> { let file = std::fs::File::open(path)?; - Ok(File { + Ok(Box::new(DarwinFile { file: RefCell::new(file), - }) + })) } - pub(crate) fn run_once(&self) -> Result<()> { + fn run_once(&self) -> Result<()> { Ok(()) } } -pub struct File { +pub struct DarwinFile { file: RefCell, } -impl File { - pub fn pread(&self, pos: usize, c: Arc) -> Result<()> { +impl File for DarwinFile { + fn pread(&self, pos: usize, c: Arc) -> Result<()> { let mut file = self.file.borrow_mut(); file.seek(std::io::SeekFrom::Start(pos as u64))?; { diff --git a/core/io/linux.rs b/core/io/linux.rs index 0467ecb81..f05a6167d 100644 --- a/core/io/linux.rs +++ b/core/io/linux.rs @@ -1,31 +1,33 @@ -use super::Completion; +use super::{Completion, File, IO}; use anyhow::Result; use std::cell::RefCell; use std::os::unix::io::AsRawFd; use std::rc::Rc; use std::sync::Arc; -pub struct IO { +pub struct LinuxIO { ring: Rc>, } -impl IO { +impl LinuxIO { pub fn new() -> Result { let ring = io_uring::IoUring::new(8)?; Ok(Self { ring: Rc::new(RefCell::new(ring)), }) } +} - pub fn open_file(&self, path: &str) -> Result { +impl IO for LinuxIO { + fn open_file(&self, path: &str) -> Result> { let file = std::fs::File::open(path)?; - Ok(File { + Ok(Box::new(LinuxFile { ring: self.ring.clone(), file, - }) + })) } - pub fn run_once(&self) -> Result<()> { + fn run_once(&self) -> Result<()> { let mut ring = self.ring.borrow_mut(); ring.submit_and_wait(1)?; let cqe = ring.completion().next().expect("completion queue is empty"); @@ -33,13 +35,13 @@ impl IO { } } -pub struct File { +pub struct LinuxFile { ring: Rc>, file: std::fs::File, } -impl File { - pub fn pread(&self, pos: usize, c: Arc) -> Result<()> { +impl File for LinuxFile { + fn pread(&self, pos: usize, c: Arc) -> Result<()> { let fd = io_uring::types::Fd(self.file.as_raw_fd()); let read_e = { let mut buf = c.buf_mut(); diff --git a/core/io/mod.rs b/core/io/mod.rs index e4ec1a739..ca54ac62d 100644 --- a/core/io/mod.rs +++ b/core/io/mod.rs @@ -1,3 +1,4 @@ +use anyhow::Result; use cfg_block::cfg_block; use std::{ cell::{Ref, RefCell, RefMut}, @@ -6,6 +7,16 @@ use std::{ sync::Arc, }; +pub trait File { + fn pread(&self, pos: usize, c: Arc) -> Result<()>; +} + +pub trait IO { + fn open_file(&self, path: &str) -> Result>; + + fn run_once(&self) -> Result<()>; +} + pub type Complete = dyn Fn(&Buffer) + Send + Sync; pub struct Completion { @@ -84,11 +95,11 @@ impl Buffer { cfg_block! { #[cfg(target_os = "linux")] { mod linux; - pub use linux::{File, IO}; + pub use linux::LinuxIO as PlatformIO; } #[cfg(target_os = "macos")] { mod darwin; - pub use darwin::{File, IO}; + pub use darwin::DarwinIO as PlatformIO; } } diff --git a/core/lib.rs b/core/lib.rs index 9de052fce..340aa269d 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -21,9 +21,9 @@ use sqlite3_parser::{ast::Cmd, lexer::sql::Parser}; use std::sync::Arc; #[cfg(feature = "fs")] -pub use io::IO; -pub use io::{Buffer, Completion}; -pub use storage::{Storage, StorageIO}; +pub use io::PlatformIO; +pub use io::{Buffer, Completion, File, IO}; +pub use storage::{PageIO, PageSource}; pub use types::Value; pub struct Database { @@ -33,14 +33,14 @@ pub struct Database { impl Database { #[cfg(feature = "fs")] - pub fn open_file(io: crate::io::IO, path: &str) -> Result { + pub fn open_file(io: Arc, path: &str) -> Result { let file = io.open_file(path)?; - let storage = storage::Storage::from_file(file); + let storage = storage::PageSource::from_file(file); Self::open(io, storage) } - pub fn open(io: crate::io::IO, storage: Storage) -> Result { - let pager = Arc::new(Pager::open(storage)?); + pub fn open(io: Arc, page_source: PageSource) -> Result { + let pager = Arc::new(Pager::open(page_source)?); let bootstrap_schema = Arc::new(Schema::new()); let conn = Connection { pager: pager.clone(), diff --git a/core/pager.rs b/core/pager.rs index 8f8b693cd..f9346959a 100644 --- a/core/pager.rs +++ b/core/pager.rs @@ -1,7 +1,7 @@ use crate::buffer_pool::BufferPool; use crate::sqlite3_ondisk; use crate::sqlite3_ondisk::BTreePage; -use crate::Storage; +use crate::PageSource; use concurrent_lru::unsharded::LruCache; use std::sync::RwLock; use std::sync::{ @@ -67,19 +67,19 @@ impl Page { } pub struct Pager { - storage: Storage, + page_source: PageSource, page_cache: LruCache>, buffer_pool: Arc, } impl Pager { - pub fn open(storage: Storage) -> anyhow::Result { - let db_header = sqlite3_ondisk::read_database_header(&storage)?; + pub fn open(page_source: PageSource) -> anyhow::Result { + let db_header = sqlite3_ondisk::read_database_header(&page_source)?; let page_size = db_header.page_size as usize; let buffer_pool = Arc::new(BufferPool::new(page_size)); let page_cache = LruCache::new(10); Ok(Self { - storage, + page_source, buffer_pool, page_cache, }) @@ -90,7 +90,7 @@ impl Pager { let page = Arc::new(Page::new()); page.set_locked(); sqlite3_ondisk::begin_read_btree_page( - &self.storage, + &self.page_source, self.buffer_pool.clone(), page.clone(), page_idx, diff --git a/core/sqlite3_ondisk.rs b/core/sqlite3_ondisk.rs index 0fcd87dca..5863743d1 100644 --- a/core/sqlite3_ondisk.rs +++ b/core/sqlite3_ondisk.rs @@ -27,7 +27,7 @@ use crate::buffer_pool::BufferPool; use crate::io::{Buffer, Completion}; use crate::pager::Page; use crate::types::{Record, Value}; -use crate::Storage; +use crate::PageSource; use anyhow::{anyhow, Result}; use std::sync::Arc; @@ -61,12 +61,12 @@ pub struct DatabaseHeader { version_number: u32, } -pub fn read_database_header(storage: &Storage) -> Result { +pub fn read_database_header(page_source: &PageSource) -> Result { let drop_fn = Arc::new(|_buf| {}); let buf = Buffer::allocate(512, drop_fn); let complete = Box::new(move |_buf: &Buffer| {}); let c = Arc::new(Completion::new(buf, complete)); - storage.get(1, c.clone())?; + page_source.get(1, c.clone())?; let buf = c.buf(); let buf = buf.as_slice(); let mut header = DatabaseHeader::default(); @@ -136,7 +136,7 @@ pub struct BTreePage { } pub fn begin_read_btree_page( - storage: &Storage, + page_source: &PageSource, buffer_pool: Arc, page: Arc, page_idx: usize, @@ -154,7 +154,7 @@ pub fn begin_read_btree_page( } }); let c = Arc::new(Completion::new(buf, complete)); - storage.get(page_idx, c.clone())?; + page_source.get(page_idx, c.clone())?; Ok(()) } diff --git a/core/storage.rs b/core/storage.rs index f7e4c6f12..577365ab9 100644 --- a/core/storage.rs +++ b/core/storage.rs @@ -1,18 +1,20 @@ use crate::io::Completion; +#[cfg(feature = "fs")] +use crate::io::File; use anyhow::Result; use std::sync::Arc; -pub struct Storage { - io: Arc, +pub struct PageSource { + io: Arc, } -impl Storage { - pub fn from_io(io: Arc) -> Self { +impl PageSource { + pub fn from_io(io: Arc) -> Self { Self { io } } #[cfg(feature = "fs")] - pub fn from_file(file: crate::io::File) -> Self { + pub fn from_file(file: Box) -> Self { Self { io: Arc::new(FileStorage::new(file)), } @@ -23,17 +25,17 @@ impl Storage { } } -pub trait StorageIO { +pub trait PageIO { fn get(&self, page_idx: usize, c: Arc) -> Result<()>; } #[cfg(feature = "fs")] struct FileStorage { - file: crate::io::File, + file: Box, } #[cfg(feature = "fs")] -impl StorageIO for FileStorage { +impl PageIO for FileStorage { fn get(&self, page_idx: usize, c: Arc) -> Result<()> { let page_size = c.buf().len(); assert!(page_idx > 0); @@ -48,7 +50,7 @@ impl StorageIO for FileStorage { #[cfg(feature = "fs")] impl FileStorage { - pub fn new(file: crate::io::File) -> Self { + pub fn new(file: Box) -> Self { Self { file } } }