diff --git a/core/benches/benchmark.rs b/core/benches/benchmark.rs index 3115461d0..4ca7a7752 100644 --- a/core/benches/benchmark.rs +++ b/core/benches/benchmark.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion, Throughput}; -use limbo_core::{Database, IO, PlatformIO}; +use limbo_core::{Database, PlatformIO, IO}; use pprof::criterion::{Output, PProfProfiler}; use std::rc::Rc; diff --git a/core/io/darwin.rs b/core/io/darwin.rs index 4a83400d3..69f1979cc 100644 --- a/core/io/darwin.rs +++ b/core/io/darwin.rs @@ -1,8 +1,8 @@ -use super::{Completion, File, IO}; +use super::{Completion, File, WriteCompletion, IO}; use anyhow::{Ok, Result}; use std::rc::Rc; use std::cell::RefCell; -use std::io::{Read, Seek}; +use std::io::{Read, Seek, Write}; use log::trace; pub struct DarwinIO {} @@ -43,4 +43,18 @@ impl File for DarwinFile { c.complete(); Ok(()) } + + fn pwrite( + &self, + pos: usize, + buffer: Rc>, + c: Rc, + ) -> Result<()> { + let mut file = self.file.borrow_mut(); + file.seek(std::io::SeekFrom::Start(pos as u64))?; + let buf = buffer.borrow(); + let buf = buf.as_slice(); + file.write_all(buf)?; + Ok(()) + } } diff --git a/core/io/linux.rs b/core/io/linux.rs index 8a5219fe7..dee07e040 100644 --- a/core/io/linux.rs +++ b/core/io/linux.rs @@ -1,9 +1,9 @@ -use super::{Completion, File, IO}; +use super::{Completion, File, WriteCompletion, IO}; use anyhow::Result; +use log::trace; use std::cell::RefCell; use std::os::unix::io::AsRawFd; use std::rc::Rc; -use log::trace; pub struct LinuxIO { ring: Rc>, @@ -21,7 +21,7 @@ impl LinuxIO { impl IO for LinuxIO { fn open_file(&self, path: &str) -> Result> { trace!("open_file(path = {})", path); - let file = std::fs::File::open(path)?; + let file = std::fs::File::options().read(true).write(true).open(path)?; Ok(Box::new(LinuxFile { ring: self.ring.clone(), file, @@ -59,7 +59,7 @@ impl File for LinuxFile { let len = buf.len(); let buf = buf.as_mut_ptr(); let ptr = Rc::into_raw(c.clone()); - io_uring::opcode::Read::new(fd, buf, len as u32 ) + io_uring::opcode::Read::new(fd, buf, len as u32) .offset(pos as u64) .build() .user_data(ptr as u64) @@ -72,4 +72,29 @@ impl File for LinuxFile { } Ok(()) } + + fn pwrite( + &self, + pos: usize, + buffer: Rc>, + c: Rc, + ) -> Result<()> { + let fd = io_uring::types::Fd(self.file.as_raw_fd()); + let write = { + let buf = buffer.borrow(); + let ptr = Rc::into_raw(c.clone()); + io_uring::opcode::Write::new(fd, buf.as_ptr(), buf.len() as u32) + .offset(pos as u64) + .build() + .user_data(ptr as u64) + }; + let mut ring = self.ring.borrow_mut(); + unsafe { + ring.submission() + .push(&write) + .expect("submission queue is full"); + ring.submit()?; + } + Ok(()) + } } diff --git a/core/io/mod.rs b/core/io/mod.rs index ab35295e6..9ab0db995 100644 --- a/core/io/mod.rs +++ b/core/io/mod.rs @@ -9,6 +9,8 @@ use std::{ pub trait File { fn pread(&self, pos: usize, c: Rc) -> Result<()>; + fn pwrite(&self, pos: usize, buffer: Rc>, c: Rc) + -> Result<()>; } pub trait IO { @@ -18,12 +20,17 @@ pub trait IO { } pub type Complete = dyn Fn(&Buffer); +pub type WriteComplete = dyn Fn(usize); pub struct Completion { pub buf: RefCell, pub complete: Box, } +pub struct WriteCompletion { + pub complete: Box, +} + impl Completion { pub fn new(buf: Buffer, complete: Box) -> Self { let buf = RefCell::new(buf); @@ -44,6 +51,15 @@ impl Completion { } } +impl WriteCompletion { + pub fn new(complete: Box) -> Self { + Self { complete } + } + pub fn complete(&self, bytes_written: usize) { + (self.complete)(bytes_written); + } +} + pub type BufferData = Pin>; pub type BufferDropFn = Rc; @@ -53,6 +69,15 @@ pub struct Buffer { drop: BufferDropFn, } +impl Clone for Buffer { + fn clone(&self) -> Self { + Self { + data: self.data.clone(), + drop: self.drop.clone(), + } + } +} + impl Drop for Buffer { fn drop(&mut self) { let data = unsafe { ManuallyDrop::take(&mut self.data) }; diff --git a/core/io/windows.rs b/core/io/windows.rs index ec6720ea2..53e872721 100644 --- a/core/io/windows.rs +++ b/core/io/windows.rs @@ -1,8 +1,8 @@ -use super::{Completion, File, IO}; +use super::{Completion, File, WriteCompletion, IO}; use anyhow::{Ok, Result}; use std::rc::Rc; use std::cell::RefCell; -use std::io::{Read, Seek}; +use std::io::{Read, Seek, Write}; use log::trace; pub struct WindowsIO {} @@ -43,4 +43,18 @@ impl File for WindowsFile { c.complete(); Ok(()) } + + fn pwrite( + &self, + pos: usize, + buffer: Rc>, + c: Rc, + ) -> Result<()> { + let mut file = self.file.borrow_mut(); + file.seek(std::io::SeekFrom::Start(pos as u64))?; + let buf = buffer.borrow(); + let buf = buf.as_slice(); + file.write_all(buf)?; + Ok(()) + } } diff --git a/core/vdbe.rs b/core/vdbe.rs index 8ec38b0a5..0df9d9753 100644 --- a/core/vdbe.rs +++ b/core/vdbe.rs @@ -339,7 +339,11 @@ impl Program { } } -fn make_record<'a>(registers: &'a [OwnedValue], register_end: &usize, register_start: &usize) -> Record<'a> { +fn make_record<'a>( + registers: &'a [OwnedValue], + register_end: &usize, + register_start: &usize, +) -> Record<'a> { let mut values = Vec::with_capacity(*register_end - *register_start); for i in *register_start..*register_end { values.push(crate::types::to_value(®isters[i]));