Struct Store

Source
pub struct Store<C> { /* private fields */ }
Expand description

Persists an append-only list of changesets (C) to a single file.

⚠ This is a development/testing database. It does not natively support backwards compatible BDK version upgrades so should not be used in production.

Implementations§

Source§

impl<C> Store<C>

Source

pub fn create<P>(magic: &[u8], file_path: P) -> Result<Self, StoreError>
where P: AsRef<Path>,

Create a new Store file in write-only mode; error if the file exists.

magic is the prefixed bytes to write to the new file. This will be checked when loading the Store in the future with load.

Source

pub fn load<P>( magic: &[u8], file_path: P, ) -> Result<(Self, Option<C>), StoreErrorWithDump<C>>
where P: AsRef<Path>,

Load an existing Store.

Use create to create a new Store.

§Errors

If the prefixed bytes of the loaded file do not match the provided magic, a StoreErrorWithDump will be returned with the StoreError::InvalidMagicBytes error variant in its error field and changeset field set to Option::None

If there exist changesets in the file, load will try to aggregate them in a single changeset to verify their integrity. If aggregation fails StoreErrorWithDump will be returned with the StoreError::Bincode error variant in its error field and the aggregated changeset so far in the changeset field.

To get a new working file store from this error use Store::create and Store::append to add the aggregated changeset obtained from StoreErrorWithDump.

To analyze the causes of the problem in the original database do not recreate the Store using the same file path. Not changing the file path will overwrite previous file without being able to recover its original data.

§Examples
use bdk_file_store::{Store, StoreErrorWithDump};

let (mut new_store, _aggregate_changeset) =
    match Store::<TestChangeSet>::load(&MAGIC_BYTES, &file_path) {
        Ok((store, changeset)) => (store, changeset),
        Err(StoreErrorWithDump { changeset, .. }) => {
            let new_file_path = file_path.with_extension("backup");
            let mut new_store =
                Store::create(&MAGIC_BYTES, &new_file_path).expect("must create new file");
            if let Some(aggregated_changeset) = changeset {
                new_store.append(&aggregated_changeset)?;
            }
            // The following will overwrite the original file. You will loose the corrupted
            // portion of the original file forever.
            drop(new_store);
            std::fs::rename(&new_file_path, &file_path)?;
            Store::load(&MAGIC_BYTES, &file_path).expect("must load new file")
        }
    };
Source

pub fn dump(&mut self) -> Result<Option<C>, StoreErrorWithDump<C>>

Dump the aggregate of all changesets in Store.

§Errors

If there exist changesets in the file, dump will try to aggregate them in a single changeset. If aggregation fails StoreErrorWithDump will be returned with the StoreError::Bincode error variant in its error field and the aggregated changeset so far in the changeset field.

Source

pub fn load_or_create<P>( magic: &[u8], file_path: P, ) -> Result<(Self, Option<C>), StoreErrorWithDump<C>>
where P: AsRef<Path>,

Attempt to load existing Store file; create it if the file does not exist.

Internally, this calls either load or create.

Source

pub fn append(&mut self, changeset: &C) -> Result<(), Error>

Append a new changeset to the file. Does nothing if the changeset is empty. Truncation is not needed because file pointer is always moved to the end of the last decodable data from beginning to end.

If multiple garbage writes are produced on the file, the next load will only retrieve the first chunk of valid changesets.

If garbage data is written and then valid changesets, the next load will still only retrieve the first chunk of valid changesets. The recovery of those valid changesets after the garbage data is responsibility of the user.

Trait Implementations§

Source§

impl<C: Debug> Debug for Store<C>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<C> Freeze for Store<C>

§

impl<C> RefUnwindSafe for Store<C>
where C: RefUnwindSafe,

§

impl<C> Send for Store<C>
where C: Send,

§

impl<C> Sync for Store<C>
where C: Sync,

§

impl<C> Unpin for Store<C>
where C: Unpin,

§

impl<C> UnwindSafe for Store<C>
where C: UnwindSafe,

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 = 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.