Skip to main content

DoubletsStorage

Struct DoubletsStorage 

Source
pub struct DoubletsStorage<T: LinkReference, S: Doublets<T>> { /* private fields */ }
Expand description

A LinksStorage over any doublets store.

Implementations§

Source§

impl<T: LinkReference> DoubletsStorage<T, FileMappedUnitStore<T>>

Source

pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, LinkError>

Opens (or creates) a file-mapped doublets database at path without taking an advisory lock.

Source

pub fn open_shared<P: AsRef<Path>>(path: P) -> Result<Self, LinkError>

Opens the database and holds a shared advisory lock for the lifetime of the returned storage, excluding concurrent writers.

Source

pub fn open_exclusive<P: AsRef<Path>>(path: P) -> Result<Self, LinkError>

Opens the database and holds an exclusive advisory lock for the lifetime of the returned storage, excluding every other reader and writer that honours the same protocol.

Source

pub fn try_open_exclusive<P: AsRef<Path>>( path: P, ) -> Result<Option<Self>, LinkError>

Like Self::open_exclusive but returns Ok(None) instead of blocking when another holder owns a conflicting lock.

Source§

impl<T: LinkReference, S: Doublets<T>> DoubletsStorage<T, S>

Source

pub fn wrap(store: S) -> Self

Adopts a doublets store the caller already owns.

Nothing about the store is assumed: no path, no locking and no external-change detection. This is the entry point for embedding applications that open their own unit::Store<usize, _> and only want the transactions layer on top of it.

Source

pub fn wrap_at<P: AsRef<Path>>(store: S, path: P) -> Result<Self, LinkError>

Adopts a store the caller already owns while recording the path it is backed by, enabling LinksStorage::flush, LinksStorage::has_external_changes and the lock helpers.

Source

pub fn map_store<S2, F>(self, map: F) -> DoubletsStorage<T, S2>
where S2: Doublets<T>, F: FnOnce(S) -> S2,

Replaces the underlying store with map(store), keeping the path, advisory lock and change-detection fingerprint of this storage.

This is the extension point for stacking any doublets decorator (or a custom one) under the transactions and version control layers:

use doublets::decorators::DecoratorsExt;
use link_cli::storage::DoubletsStorage;

let storage = DoubletsStorage::<u32, _>::open("links.data")?
    .map_store(|store| store.with_inner_reference_existence_validation());
Source

pub fn with_automatic_uniqueness_and_usages_resolution( self, ) -> DoubletsStorage<T, AutomaticUniquenessAndUsagesResolution<T, S>>

Wraps the underlying store in the same decorator stack C# applies through ILinksExtensions.DecorateWithAutomaticUniquenessAndUsagesResolution.

After this call (source, target) pairs are unique: creating or updating a link into a pair that already exists resolves to the existing link, re-points every usage of the redundant link at the survivor and deletes the redundant link. Deleting a link cascades to its usages and resets its contents first.

use link_cli::storage::{DoubletsStorage, LinksStorage};

let mut storage = DoubletsStorage::<u32, _>::open("links.data")?
    .with_automatic_uniqueness_and_usages_resolution();
let first = storage.create_link(1, 1)?;
let second = storage.create_link(1, 1)?;
assert_eq!(first, second);
Source

pub fn path(&self) -> Option<&Path>

The database file backing this storage, when known.

Source

pub fn store(&self) -> &S

Borrows the underlying doublets store.

Source

pub fn store_mut(&mut self) -> &mut S

Mutably borrows the underlying doublets store.

Source

pub fn into_store(self) -> S

Returns the underlying doublets store, dropping any held lock.

Source

pub fn lock_shared(&self) -> Result<FileLock, LinkError>

Acquires a shared advisory lock on this database’s sidecar lock file.

Source

pub fn lock_exclusive(&self) -> Result<FileLock, LinkError>

Acquires an exclusive advisory lock on this database’s sidecar lock file.

Source

pub fn held_lock(&self) -> Option<&FileLock>

The advisory lock held for the lifetime of this storage, if any.

Trait Implementations§

Source§

impl<T: LinkReference, S: Doublets<T>> LinksStorage<T> for DoubletsStorage<T, S>

Source§

fn flush(&mut self) -> Result<(), LinkError>

fsyncs the backing file so the mapped writes survive a machine crash, and publishes them to other processes by advancing the file’s modification time. A no-op for stores adopted without a known path.

Bumping the timestamp is deliberate: the kernel only refreshes mtime when a clean page of a shared mapping is first written to, so a long-lived writer that keeps touching already-dirty pages would otherwise stay invisible to LinksStorage::has_external_changes.

Source§

fn has_external_changes(&self) -> Result<bool, LinkError>

Compares the database file’s size and mtime against the values observed when this storage was opened, reloaded or flushed.

The granularity is a published write: writers publish by calling LinksStorage::flush, which fsyncs and advances the file’s modification time. Writes that a peer has made but not yet flushed are already visible through the shared mapping, but are not reported here — take DoubletsStorage::lock_shared when an exact answer is required.

Source§

fn reload(&mut self) -> Result<(), LinkError>

Memory-mapped stores always read through to the mapping, so this only refreshes the change-detection fingerprint.

Creates a new link and returns its address.
Ensures a link exists at index, creating placeholders as needed.
Returns the link stored at index, if any.
Returns true when a link exists at index.
Repoints index at source/target, returning the previous state.
Deletes index, returning the link that was removed.
Returns every link in the store.
Returns every link matching the (optional) index/source/target pattern.
Finds the address of a link with the given source and target.
Returns the address of an existing (source, target) link, creating it when it does not exist yet.
Number of links currently stored.
Self::update_link, reporting every (before, after) change it made. Read more
Self::delete_link, reporting every (before, after) change it made. Read more

Auto Trait Implementations§

§

impl<T, S> Freeze for DoubletsStorage<T, S>
where S: Freeze, PhantomData<T>: Freeze,

§

impl<T, S> RefUnwindSafe for DoubletsStorage<T, S>

§

impl<T, S> Send for DoubletsStorage<T, S>
where PhantomData<T>: Send,

§

impl<T, S> Sync for DoubletsStorage<T, S>
where PhantomData<T>: Sync,

§

impl<T, S> Unpin for DoubletsStorage<T, S>
where S: Unpin, PhantomData<T>: Unpin,

§

impl<T, S> UnsafeUnpin for DoubletsStorage<T, S>

§

impl<T, S> UnwindSafe for DoubletsStorage<T, S>

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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.