Struct StateDirectory

Source
pub struct StateDirectory {
    dir: CheckedDir,
}
Available on crate feature state-dir only.
Expand description

The whole program’s state directory

Representation of [storage] state_dir and permissions from the Arti configuration.

This type does not embody any subpaths relating to any particular facility within Arti.

Constructing a StateDirectory may involve filesystem permissions checks, so ideally it would be created once per process for performance reasons.

Existence of a StateDirectory also does not imply exclusive access.

This type is passed to each facility’s constructor; the facility implements InstanceIdentity and calls acquire_instance.

§Use for caches

In principle this type and the methods and subtypes available would be suitable for cache data as well as state data.

However the locking scheme does not tolerate random removal of files. And cache directories are sometimes configured to point to locations with OS-supplied automatic file cleaning. That would not be correct, since the automatic file cleaner might remove an in-use lockfile, effectively unlocking the instance state even while a process exists that thinks it still has the lock.

Fields§

§dir: CheckedDir

The actual directory, including mistrust config

Implementations§

Source§

impl StateDirectory

Source

pub fn new(state_dir: impl AsRef<Path>, mistrust: &Mistrust) -> Result<Self>

Create a new StateDirectory from a directory and mistrust configuration

Source

pub fn acquire_instance<I: InstanceIdentity>( &self, identity: &I, ) -> Result<InstanceStateHandle>

Acquires (creates and locks) a storage for an instance

Ensures the existence and suitability of a subdirectory named kind/identity, and locks it for exclusive access.

Source

fn with_instance_path_pieces<T>( self: &StateDirectory, kind_str: &'static str, id_writer: &'_ dyn Fn(&mut Formatter<'_>) -> Result, call: impl FnOnce(&SlugRef, &SlugRef, &dyn Fn() -> Resource) -> Result<T>, ) -> Result<T>

Given a kind and id, obtain pieces of its path and call a “doing work” callback

This function factors out common functionality needed by StateDirectory::acquire_instance and StateDirectory::instance_peek_storage, particularly relating to instance kind and id, and errors.

kind and id are from an InstanceIdentity.

Source

pub fn list_instances<I: InstanceIdentity>( &self, ) -> impl Iterator<Item = Result<Slug>>

List the instances of a particular kind

Returns the instance identities.

(The implementation lists subdirectories named kind_*.)

Concurrency: An instance which is not being removed or created will be listed (or not) according to whether it’s present. But, in the presence of concurrent calls to acquire_instance and delete on different instances, is not guaranteed to provide a snapshot: serialisation is not guaranteed across different instances.

It is guaranteed to list each instance only once.

Source

fn list_instances_inner( &self, kind: &'static str, ) -> impl Iterator<Item = Result<Slug>>

List the instances of a kind, where the kind is supplied as a value

Used by list_instances and purge_instances.

Includes instances that exists only as a stale lockfile.

Source

pub fn purge_instances( &self, now: SystemTime, filter: &mut (dyn InstancePurgeHandler + '_), ) -> Result<()>

Delete instances according to selections made by the caller

Each instance is considered in three stages.

Firstly, it is passed to name_filter. If name_filter returns Live, further consideration is skipped and the instance is retained.

Secondly, the last time the instance was written to is determined, and passed to age_filter. Again, this might mean ensure the instance is retained.

Thirdly, the resulting InstanceStateHandle is passed to dispose. dispose may choose to call handle.delete(), or simply drop the handle.

Concurrency: In the presence of multiple concurrent calls to acquire_instance and delete: filter may be called for an instance which is being created or deleted by another task. dispose will be properly serialised with other activities on the same instance, as implied by it receiving an InstanceStateHandle.

The expiry time is reset by calls to acquire_instance, StorageHandle::store and InstanceStateHandle::raw_subdir; it may be reset by calls to StorageHandle::delete.

Instances that are currently locked by another task will not be purged, but the expiry time is not reset by unlocking an instance (dropping the last clone of an InstanceStateHandle).

§Sequencing of InstancePurgeHandler callbacks

Each instance will be processed (and callbacks made for it) at most once; and calls for different instances will not be interleaved.

During the processing of a particular instance The callbacks will be made in order, progressing monotonically through the methods in the order listed. But name_filter and age_filter might each be called more than once for the same instance.

Between each stage, the purge implementation may discover that the instance ought not to be processed further. So returning Liveness::PossiblyUnused from a filter does not guarantee that the next callback will be made.

Source

fn maybe_purge_instance( &self, now: SystemTime, kind: &SlugRef, id: &SlugRef, resource: &dyn Fn() -> Resource, filter: &mut (dyn InstancePurgeHandler + '_), ) -> Result<()>

Consider whether to purge an instance

Performs all the necessary steps, including liveness checks, passing an InstanceStateHandle to filter.dispose, and deleting stale lockfiles without associated state.

Source

pub fn instance_peek_storage<I: InstanceIdentity, T: DeserializeOwned>( &self, identity: &I, key: &(impl TryIntoSlug + ?Sized), ) -> Result<Option<T>>

Tries to peek at something written by StorageHandle::store

It is guaranteed that this will return either the T that was stored, or None if store was never called, or StorageHandle::delete was called

So the operation is atomic, but there is no further synchronisation.

Trait Implementations§

Source§

impl Clone for StateDirectory

Source§

fn clone(&self) -> StateDirectory

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for StateDirectory

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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.

§

impl<T> Instrument for T

§

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

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

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

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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