pub struct DurableRoot { /* private fields */ }Expand description
Descriptor-pinned root for durable state owned by a database.
Every relative operation rejects .., symlinks, reparse points, and
non-regular final files. Unix operations stay descriptor-relative. Windows
keeps the root and each traversed ancestor open without delete sharing.
§Deferred fsync (batch-create) mode
Self::open_deferred produces a root whose write/mkdir/rename
operations skip their per-call fsyncs. The caller must invoke
Self::finalize_deferred_sync once to fsync the whole tree and
re-enable eager (per-call) fsync for subsequent operations. This is the
primary mechanism for amortizing fsync cost out of batch-create paths
such as crate::engine::Table::create, which would otherwise pay
~9 fsync round-trips for a fresh table. Security semantics
(descriptor-pinning, path validation) are unaffected — only durability
timing changes.
Implementations§
Source§impl DurableRoot
impl DurableRoot
pub fn try_clone(&self) -> Result<Self>
pub fn open(root: impl AsRef<Path>) -> Result<Self>
pub fn canonical_path(&self) -> &Path
Sourcepub fn file_identity(&self) -> Result<DurableFileIdentity>
pub fn file_identity(&self) -> Result<DurableFileIdentity>
Return the stable identity of the pinned directory handle.
Sourcepub fn open_deferred(root: impl AsRef<Path>) -> Result<Self>
pub fn open_deferred(root: impl AsRef<Path>) -> Result<Self>
Open the root in deferred-fsync mode: subsequent write_new,
write_atomic*, create_directory_*, replace*, and copy_new_from
operations skip their per-call fsyncs. The caller must invoke
Self::finalize_deferred_sync exactly once to make the deferred
writes durable and re-enable eager fsync for future operations.
Intended for batch-create paths (e.g. crate::engine::Table::create)
that issue many independent durable writes against a fresh tree. On a
filesystem where each fsync costs ~1 ms, this collapses ~9 fsync
round-trips per create into a single recursive pass. Security semantics
(descriptor-pinning, path validation, symlink rejection) are identical
to Self::open; only the timing of fsync changes. Calling this on
a root that will receive ongoing individual durable writes without a
matching finalize would silently lose durability — restrict it to
batch paths that finalize on every exit path.
Sourcepub fn finalize_deferred_sync(&self) -> Result<()>
pub fn finalize_deferred_sync(&self) -> Result<()>
Fsync every file and directory under this root, then re-enable eager (per-call) fsync for subsequent operations. Idempotent: a root already in eager mode returns immediately after syncing the tree once. Returns the first sync error encountered (the caller must treat the tree as untrusted if this errors).
Sourcepub fn finalize_deferred_sync_shallow(&self) -> Result<()>
pub fn finalize_deferred_sync_shallow(&self) -> Result<()>
Shallow variant of Self::finalize_deferred_sync: fsync the data of
every regular file directly under the root, then fsync the root
directory and each immediate subdirectory for entry-name durability.
Does NOT recurse into subdirectories or fsync files inside them.
This matches the pre-hardening durability contract: the manifest (and
any other root-level file) is data-durable, and all entry names in the
root and its immediate children are durable. Files inside _wal/,
_runs/, etc. rely on the OS page cache and the first commit() or
flush() to become data-durable — identical to the behavior before
the descriptor-pinned hardening pass. Used by plaintext Table::create
where the extra fsyncs of the recursive variant would dominate
batch-create cost without changing the observable crash-recovery
contract (a table is always reopened via its manifest, and the first
commit makes everything else durable).
Sourcepub fn io_path(&self) -> Result<PathBuf>
pub fn io_path(&self) -> Result<PathBuf>
Stable operational path backed by the pinned directory descriptor.
Use this for legacy path-based code while the DurableRoot stays alive.
pub fn open_directory(&self, relative: impl AsRef<Path>) -> Result<DurableRoot>
pub fn create_directory_all(&self, relative: impl AsRef<Path>) -> Result<()>
pub fn create_directory_all_pinned( &self, relative: impl AsRef<Path>, ) -> Result<DurableRoot>
pub fn create_directory_new(&self, relative: impl AsRef<Path>) -> Result<()>
pub fn open_regular(&self, relative: impl AsRef<Path>) -> Result<File>
pub fn entry_exists(&self, relative: impl AsRef<Path>) -> Result<bool>
pub fn write_new(&self, relative: impl AsRef<Path>, bytes: &[u8]) -> Result<()>
Sourcepub fn write_new_atomic(
&self,
relative: impl AsRef<Path>,
bytes: &[u8],
) -> Result<()>
pub fn write_new_atomic( &self, relative: impl AsRef<Path>, bytes: &[u8], ) -> Result<()>
Write an immutable file and publish its name only after its contents
are durable. Concurrent creators get AlreadyExists and can safely
read the complete winner.
pub fn copy_new_from( &self, relative: impl AsRef<Path>, source: &mut File, ) -> Result<u64>
pub fn write_atomic( &self, relative: impl AsRef<Path>, bytes: &[u8], ) -> Result<()>
pub fn open_lock_file(&self, relative: impl AsRef<Path>) -> Result<File>
pub fn list_regular_files( &self, relative: impl AsRef<Path>, ) -> Result<Vec<OsString>>
pub fn remove_file(&self, relative: impl AsRef<Path>) -> Result<()>
pub fn rename_directory_new( &self, source: impl AsRef<Path>, destination_root: &DurableRoot, destination: impl AsRef<Path>, ) -> Result<()>
pub fn rename_directory_new_with_after<F>(
&self,
source: impl AsRef<Path>,
destination_root: &DurableRoot,
destination: impl AsRef<Path>,
after_publish: F,
) -> Result<()>where
F: FnOnce(),
pub fn remove_directory_all(&self, relative: impl AsRef<Path>) -> Result<()>
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for DurableRoot
impl RefUnwindSafe for DurableRoot
impl Send for DurableRoot
impl Sync for DurableRoot
impl Unpin for DurableRoot
impl UnsafeUnpin for DurableRoot
impl UnwindSafe for DurableRoot
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more