mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-07 02:04:21 +01:00
@@ -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!();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))?;
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
14
core/lib.rs
14
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<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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user