use std::sync::Arc; use turso_core::{Completion, LimboError, OpenFlags}; use crate::{ database_tape::{DatabaseTape, DatabaseTapeOpts}, types::{Coro, ProtocolCommand}, Result, }; pub trait IoOperations { fn open_tape(&self, path: &str, capture: bool) -> Result; fn try_open(&self, path: &str) -> Result>>; fn create(&self, path: &str) -> Result>; fn truncate( &self, coro: &Coro, file: Arc, len: usize, ) -> impl std::future::Future>; } impl IoOperations for Arc { fn open_tape(&self, path: &str, capture: bool) -> Result { let io = self.clone(); let clean = turso_core::Database::open_file(io, path, false, true).unwrap(); let opts = DatabaseTapeOpts { cdc_table: None, cdc_mode: Some(if capture { "full" } else { "off" }.to_string()), }; tracing::debug!("initialize database tape connection: path={}", path); Ok(DatabaseTape::new_with_opts(clean, opts)) } fn try_open(&self, path: &str) -> Result>> { match self.open_file(path, OpenFlags::None, false) { Ok(file) => Ok(Some(file)), Err(LimboError::CompletionError(turso_core::CompletionError::IOError( std::io::ErrorKind::NotFound, ))) => Ok(None), Err(err) => Err(err.into()), } } fn create(&self, path: &str) -> Result> { match self.open_file(path, OpenFlags::Create, false) { Ok(file) => Ok(file), Err(err) => Err(err.into()), } } async fn truncate( &self, coro: &Coro, file: Arc, len: usize, ) -> Result<()> { let c = Completion::new_trunc(move |rc| { let Ok(rc) = rc else { return; }; tracing::debug!("file truncated: rc={}", rc); }); let c = file.truncate(len as u64, c)?; while !c.succeeded() { coro.yield_(ProtocolCommand::IO).await?; } Ok(()) } }