add is_hole / punch_hole optional methods to IO trait and remove is_hole method from Database trait

This commit is contained in:
Nikita Sivukhin
2025-11-12 12:04:42 +04:00
parent b73ff13b88
commit be12ca01aa
4 changed files with 29 additions and 22 deletions

View File

@@ -1,6 +1,6 @@
use super::{Buffer, Clock, Completion, File, OpenFlags, IO};
use crate::LimboError;
use crate::{io::clock::DefaultClock, Result};
use crate::{turso_assert, LimboError};
use crate::io::clock::Instant;
use std::{
@@ -238,23 +238,25 @@ impl File for MemoryFile {
fn has_hole(&self, pos: usize, len: usize) -> Result<bool> {
let start_page = pos / PAGE_SIZE;
let end_page = ((pos + len.max(1)) - 1) / PAGE_SIZE;
let (mut holes, mut pages) = (0, 0);
for page_no in start_page..=end_page {
match self.get_page(page_no) {
Some(_) => pages += 1,
None => holes += 1,
};
if self.get_page(page_no).is_some() {
return Ok(false);
}
}
Ok(true)
}
if holes == 0 {
Ok(false)
} else if pages == 0 {
Ok(true)
} else {
Err(LimboError::InternalError(format!(
"ambigous has_hole result: pos={pos}, len={len}, pages={pages}, holes={holes}"
)))
fn punch_hole(&self, pos: usize, len: usize) -> Result<()> {
turso_assert!(
pos % PAGE_SIZE == 0 && len % PAGE_SIZE == 0,
"hole must be page aligned"
);
let start_page = pos / PAGE_SIZE;
let end_page = ((pos + len.max(1)) - 1) / PAGE_SIZE;
for page_no in start_page..=end_page {
unsafe { (*self.pages.get()).remove(&page_no) };
}
Ok(())
}
}

View File

@@ -92,10 +92,22 @@ pub trait File: Send + Sync {
}
fn size(&self) -> Result<u64>;
fn truncate(&self, len: u64, c: Completion) -> Result<Completion>;
/// Optional method implemented by the IO which supports "partial" files (e.g. file with "holes")
/// This method is used in sync engine only for now (in partial sync mode) and never used in the core database code
///
/// The hole is the contiguous file region which is not allocated by the file-system
/// If there is a single byte which is allocated within a given range - method must return false in this case
// todo: need to add custom completion type?
fn has_hole(&self, _pos: usize, _len: usize) -> Result<bool> {
panic!("has_hole is not supported for the given IO implementation")
}
/// Optional method implemented by the IO which supports "partial" files (e.g. file with "holes")
/// This method is used in sync engine only for now (in partial sync mode) and never used in the core database code
// todo: need to add custom completion type?
fn punch_hole(&self, _pos: usize, _len: usize) -> Result<()> {
panic!("punch_hole is not supported for the given IO implementation")
}
}
#[derive(Debug, Copy, Clone, PartialEq)]

View File

@@ -10,7 +10,7 @@ mod functions;
mod incremental;
pub mod index_method;
mod info;
mod io;
pub mod io;
#[cfg(feature = "json")]
mod json;
pub mod mvcc;

View File

@@ -85,8 +85,6 @@ pub trait DatabaseStorage: Send + Sync {
fn sync(&self, c: Completion) -> Result<Completion>;
fn size(&self) -> Result<u64>;
fn truncate(&self, len: usize, c: Completion) -> Result<Completion>;
// todo: need to add custom completion type?
fn has_hole(&self, pos: usize, len: usize) -> Result<bool>;
}
#[derive(Clone)]
@@ -261,11 +259,6 @@ impl DatabaseStorage for DatabaseFile {
let c = self.file.truncate(len as u64, c)?;
Ok(c)
}
#[instrument(skip_all, level = Level::INFO)]
fn has_hole(&self, pos: usize, len: usize) -> Result<bool> {
self.file.has_hole(pos, len)
}
}
#[cfg(feature = "fs")]