Merge pull request #24 from penberg/fix-wasm

Fix WebAssembly build
This commit is contained in:
Pekka Enberg
2024-01-14 15:32:34 +02:00
committed by GitHub
9 changed files with 84 additions and 54 deletions

View File

@@ -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<Box<dyn limbo_core::File>> {
todo!();
}
fn run_once(&self) -> Result<()> {
todo!();
}
}
pub struct PageIO {}
impl limbo_core::PageIO for PageIO {
fn get(&self, _page_idx: usize, _c: Arc<limbo_core::Completion>) -> Result<()> {
todo!();
}

View File

@@ -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 {

View File

@@ -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<Self> {
Ok(Self {})
}
}
pub fn open_file(&self, path: &str) -> Result<File> {
impl IO for DarwinIO {
fn open_file(&self, path: &str) -> Result<Box<dyn File>> {
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<std::fs::File>,
}
impl File {
pub fn pread(&self, pos: usize, c: Arc<Completion>) -> Result<()> {
impl File for DarwinFile {
fn pread(&self, pos: usize, c: Arc<Completion>) -> Result<()> {
let mut file = self.file.borrow_mut();
file.seek(std::io::SeekFrom::Start(pos as u64))?;
{

View File

@@ -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<RefCell<io_uring::IoUring>>,
}
impl IO {
impl LinuxIO {
pub fn new() -> Result<Self> {
let ring = io_uring::IoUring::new(8)?;
Ok(Self {
ring: Rc::new(RefCell::new(ring)),
})
}
}
pub fn open_file(&self, path: &str) -> Result<File> {
impl IO for LinuxIO {
fn open_file(&self, path: &str) -> Result<Box<dyn File>> {
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<RefCell<io_uring::IoUring>>,
file: std::fs::File,
}
impl File {
pub fn pread(&self, pos: usize, c: Arc<Completion>) -> Result<()> {
impl File for LinuxFile {
fn pread(&self, pos: usize, c: Arc<Completion>) -> Result<()> {
let fd = io_uring::types::Fd(self.file.as_raw_fd());
let read_e = {
let mut buf = c.buf_mut();

View File

@@ -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<Completion>) -> Result<()>;
}
pub trait IO {
fn open_file(&self, path: &str) -> Result<Box<dyn File>>;
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;
}
}

View File

@@ -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<Database> {
pub fn open_file(io: Arc<impl crate::io::IO>, path: &str) -> Result<Database> {
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<Database> {
let pager = Arc::new(Pager::open(storage)?);
pub fn open(io: Arc<impl crate::io::IO>, page_source: PageSource) -> Result<Database> {
let pager = Arc::new(Pager::open(page_source)?);
let bootstrap_schema = Arc::new(Schema::new());
let conn = Connection {
pager: pager.clone(),

View File

@@ -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<usize, Arc<Page>>,
buffer_pool: Arc<BufferPool>,
}
impl Pager {
pub fn open(storage: Storage) -> anyhow::Result<Self> {
let db_header = sqlite3_ondisk::read_database_header(&storage)?;
pub fn open(page_source: PageSource) -> anyhow::Result<Self> {
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,

View File

@@ -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<DatabaseHeader> {
pub fn read_database_header(page_source: &PageSource) -> Result<DatabaseHeader> {
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<BufferPool>,
page: Arc<Page>,
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(())
}

View File

@@ -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<dyn StorageIO>,
pub struct PageSource {
io: Arc<dyn PageIO>,
}
impl Storage {
pub fn from_io(io: Arc<dyn StorageIO>) -> Self {
impl PageSource {
pub fn from_io(io: Arc<dyn PageIO>) -> Self {
Self { io }
}
#[cfg(feature = "fs")]
pub fn from_file(file: crate::io::File) -> Self {
pub fn from_file(file: Box<dyn File>) -> 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<Completion>) -> Result<()>;
}
#[cfg(feature = "fs")]
struct FileStorage {
file: crate::io::File,
file: Box<dyn crate::io::File>,
}
#[cfg(feature = "fs")]
impl StorageIO for FileStorage {
impl PageIO for FileStorage {
fn get(&self, page_idx: usize, c: Arc<Completion>) -> 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<dyn crate::io::File>) -> Self {
Self { file }
}
}