Skip to main content

FsStore

Struct FsStore 

Source
pub struct FsStore { /* private fields */ }
Expand description

Filesystem-based storage for Heddle objects.

Layout:

.heddle/
  objects/
    blobs/
      ab/
        cdef1234...
    trees/
      ab/
        cdef1234...
    states/
      <change_id>.state
  actions/
    <action_id>.action
  packs/
    <hash>.pack
    <hash>.idx

Implementations§

Source§

impl FsStore

Source

pub fn prune_unpaired_packs(&self) -> Result<(u64, u64)>

Remove L8 orphan packs (.pack without .idx) from this store.

Source§

impl FsStore

Source

pub fn new(root: impl AsRef<Path>) -> Self

Create a new filesystem store rooted at the given path.

The path should be the .heddle directory.

Source

pub fn with_compression( root: impl AsRef<Path>, compression: CompressionConfig, ) -> Self

Create a new filesystem store with custom compression settings.

Source

pub fn init(&self) -> Result<()>

Initialize the directory structure.

Source

pub fn root(&self) -> &Path

Get the root path.

Source

pub fn compression(&self) -> CompressionConfig

Get the compression configuration.

Source

pub fn set_compression(&mut self, compression: CompressionConfig)

Set the compression configuration.

Source

pub fn loose_object_write_mode(&self) -> LooseObjectWriteMode

Source

pub fn set_loose_object_write_mode(&mut self, mode: LooseObjectWriteMode)

Source

pub fn reload_packs(&self) -> Result<()>

Reload pack files from disk.

Runs L8 install-intent recovery first so crash windows between pack and index publish are finished or aborted before packs are loaded. Uses the default intent TTL so abandoned staging is swept.

Source

pub fn pack_manager(&self) -> &RwLock<PackManager>

Get the pack manager for pack operations.

Source

pub fn clear_recent_object_caches(&self)

Source

pub fn pack_ids(&self) -> Result<Vec<PackObjectId>>

Trait Implementations§

Source§

impl Clone for FsStore

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ObjectStore for FsStore

Source§

fn get_blob_bytes(&self, hash: &ContentHash) -> Result<Option<Bytes>>

Zero-copy pack fast path. When the blob lives in a packfile and is non-delta + uncompressed, returns a Bytes::slice view of the pack’s mmap — no decompression, no allocation, no memcpy. Compressed pack entries, delta entries, and loose blobs fall back to get_blob and wrap the result in a Bytes (the VecBytes conversion is itself zero-copy).

Source§

fn loose_blob_path(&self, hash: &ContentHash) -> Option<PathBuf>

Loose blob path safe for clonefile/copy materialization.

Returns Some(path) only when the loose file exists, is stored uncompressed, and its bytes hash to the expected content hash. Compressed blobs and pack-only blobs fall through to None; so do torn cache-mirror files (the AtomicWriteMode::NoSync write side may leave one if the host crashed during a previous promote). On the torn case the caller re-promotes from the authoritative pack copy.

Verification is amortised: a hash that passes the check once in this process is recorded in verified_loose_blobs and subsequent calls skip the read+hash. So the cost on the materialize hot path is at most one BLAKE3 over each unique blob per process lifetime — negligible for tiny blobs, bounded by working-set size for huge ones.

Source§

fn promote_to_loose_uncompressed(&self, hash: &ContentHash) -> Result<bool>

Promote a blob to its uncompressed-loose canonical path so loose_blob_path returns Some(path) and hardlink-first materialization fires.

Three cases:

  1. Already loose+uncompressed: peek the header, no-op.
  2. Loose but compressed: read+decompress, atomically rewrite the canonical path with raw bytes.
  3. Pack-only: read out of the pack via get_blob, atomically write to the canonical loose path. Pack copy is left in place — the next prune cycle will discard the loose mirror and a future materialize will re-promote.
Source§

fn clear_recent_caches(&self)

Drop any in-memory caches of decompressed blobs / trees / states. The next access to any object pays full I/O + decompression cost. No-op for stores that don’t cache (InMemoryStore is already the source of truth). Read more
Source§

fn get_blob(&self, hash: &ContentHash) -> Result<Option<Blob>>

Source§

fn put_blob(&self, blob: &Blob) -> Result<ContentHash>

Source§

fn put_blob_with_hash( &self, blob: &Blob, hash: ContentHash, ) -> Result<ContentHash>

Source§

fn put_blob_bytes_with_hash( &self, data: &[u8], hash: ContentHash, ) -> Result<ContentHash>

Source§

fn has_blob(&self, hash: &ContentHash) -> Result<bool>

Source§

fn blob_size(&self, hash: &ContentHash) -> Result<Option<u64>>

Return the uncompressed byte length of the blob identified by hash, or Ok(None) when the blob is not in the store. Read more
Source§

fn get_tree(&self, hash: &ContentHash) -> Result<Option<Tree>>

Source§

fn get_tree_serialized(&self, hash: &ContentHash) -> Result<Option<Vec<u8>>>

Return the raw rmp-encoded tree body for hash. Read more
Source§

fn put_tree(&self, tree: &Tree) -> Result<ContentHash>

Source§

fn put_tree_serialized( &self, data: &[u8], hash: ContentHash, ) -> Result<ContentHash>

Source§

fn has_tree(&self, hash: &ContentHash) -> Result<bool>

Source§

fn get_state(&self, id: &ChangeId) -> Result<Option<State>>

Source§

fn put_state(&self, state: &State) -> Result<()>

Source§

fn put_state_serialized(&self, data: &[u8], id: ChangeId) -> Result<()>

Source§

fn has_state(&self, id: &ChangeId) -> Result<bool>

Source§

fn list_states(&self) -> Result<Vec<ChangeId>>

Source§

fn get_action(&self, id: &ActionId) -> Result<Option<Action>>

Source§

fn put_action(&self, action: &mut Action) -> Result<ActionId>

Source§

fn list_actions(&self) -> Result<Vec<ActionId>>

Source§

fn list_blobs(&self) -> Result<Vec<ContentHash>>

Source§

fn list_trees(&self) -> Result<Vec<ContentHash>>

Source§

fn pack_objects(&self, aggressive: bool) -> Result<(u64, u64)>

Source§

fn get_pack_object( &self, id: &PackObjectId, ) -> Result<Option<(ObjectType, Vec<u8>)>>

Source§

fn install_pack( &self, pack_data: &[u8], index_data: &[u8], ) -> Result<Vec<PackObjectId>>

Source§

fn put_blobs_packed(&self, blobs: Vec<(ContentHash, Vec<u8>)>) -> Result<()>

Bulk-write a batch of blobs as a single durable unit. The default implementation falls back to per-blob writes; backends that support packfiles (i.e. FsStore) override this to install one packfile + index — two fsyncs total instead of N. Used by the snapshot hot path so writing 1000 small files takes ~one fsync, not 1000. Read more
Source§

fn install_pack_streaming( &self, pack_path: &Path, index_path: &Path, ) -> Result<Vec<PackObjectId>>

Install a pack and its index from on-disk files (typically produced by StreamingPackBuilder). The default impl reads both files fully and delegates to install_pack, so any backend that doesn’t override this still works (at the cost of giving back the bounded-memory promise). Real fs- backed stores override this to rename(2) both files into the pack directory without ever loading them. Read more
Source§

fn prune_loose_objects(&self) -> Result<(u64, u64)>

Source§

fn begin_snapshot_write_batch(&self) -> Result<()>

Source§

fn flush_snapshot_write_batch(&self) -> Result<()>

Source§

fn abort_snapshot_write_batch(&self)

Source§

fn has_redactions_for_blob(&self, blob: &ContentHash) -> Result<bool>

Whether the store holds any redaction record for the given blob. Read more
Source§

fn get_redactions_bytes_for_blob( &self, blob: &ContentHash, ) -> Result<Option<Vec<u8>>>

Return the raw rmp-encoded RedactionsBlob bytes for the given blob, or Ok(None) if no redaction record exists. The bytes are byte-identical to what was written by put_redactions_bytes_for_blob (or by Repository::put_redaction); this is the wire-transfer payload, not a re-serialized view. Read more
Source§

fn put_redactions_bytes_for_blob( &self, blob: &ContentHash, bytes: &[u8], ) -> Result<()>

Persist the rmp-encoded RedactionsBlob bytes for the given blob. Receiver-side replay calls this after signature verification so the bytes land in the same sidecar that the sender’s Repository::put_redaction writes to. Read more
Source§

fn list_blobs_with_redactions(&self) -> Result<Vec<ContentHash>>

List every blob that has at least one redaction record. Used by the GC pin guard and by sync to enumerate redactions for the state closure. Order is unspecified; callers that need stable ordering should sort. Read more
Source§

fn has_state_visibility_for_state(&self, state: &ChangeId) -> Result<bool>

Whether the store holds any state-visibility record for state. Read more
Source§

fn get_state_visibility_bytes_for_state( &self, state: &ChangeId, ) -> Result<Option<Vec<u8>>>

Return the raw rmp-encoded StateVisibilityBlob bytes for state, or Ok(None) if no sidecar exists. The bytes are the wire-transfer payload for state visibility. Read more
Source§

fn put_state_visibility_bytes_for_state( &self, state: &ChangeId, bytes: &[u8], ) -> Result<()>

Persist raw StateVisibilityBlob bytes for state. Read more
Source§

fn list_states_with_visibility(&self) -> Result<Vec<ChangeId>>

List every state with at least one state-visibility record. Read more
Source§

fn put_action_serialized(&self, data: &[u8], id: ActionId) -> Result<()>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<S> ObjectSource for S
where S: ObjectStore + ?Sized,

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more