[−][src]Struct exonum_merkledb::Fork
A combination of a database snapshot and changes on top of it.
A Fork
provides both immutable and mutable operations over the database by implementing
the RawAccessMut
trait. Like Snapshot
, Fork
provides read isolation.
When mutable operations are applied to a fork, the subsequent reads act as if the changes
are applied to the database; in reality, these changes are accumulated in memory.
To apply the changes to the database, you need to convert a Fork
into a Patch
using
into_patch
and then atomically merge
it into the database. If two
conflicting forks are merged into a database, this can lead to an inconsistent state. If you
need to consistently apply several sets of changes to the same data, the next fork should be
created after the previous fork has been merged.
Fork
also supports checkpoints (flush
and rollback
methods), which allows
rolling back the latest changes. A checkpoint is created automatically after calling
the flush
method.
let db = TemporaryDB::new(); let mut fork = db.fork(); fork.get_list("list").extend(vec![1_u32, 2]); fork.flush(); fork.get_list("list").push(3_u32); fork.rollback(); // The changes after the latest `flush()` are now forgotten. let list = fork.get_list::<_, u32>("list"); assert_eq!(list.len(), 2);
In order to convert a fork into &dyn Snapshot
presentation, convert it into a Patch
and use a reference to it (Patch
implements Snapshot
). Using <Fork as RawAccess>::snapshot
for this purpose is logically incorrect and may lead to hard-to-debug errors.
Borrow checking
It is possible to create only one instance of index with the specified IndexAddress
based on a
single fork. If an additional instance is requested, the code will panic in runtime.
Hence, obtaining indexes from a Fork
functions similarly to RefCell::borrow_mut()
.
For example the code below will panic at runtime.
let db = TemporaryDB::new(); let fork = db.fork(); let index = fork.get_list::<_, u8>("index"); // This code will panic at runtime. let index2 = fork.get_list::<_, u8>("index");
To enable immutable / shared references to indexes, you may use readonly
method:
let db = TemporaryDB::new(); let fork = db.fork(); fork.get_list::<_, u8>("index").extend(vec![1, 2, 3]); let readonly = fork.readonly(); let index = readonly.get_list::<_, u8>("index"); // Works fine. let index2 = readonly.get_list::<_, u8>("index");
It is impossible to mutate index contents having a readonly access to the fork; this is checked by the Rust type system.
Shared references work like RefCell::borrow()
; it is a runtime error to try to obtain
a shared reference to an index if there is an exclusive reference to the same index,
and vice versa.
Methods
impl Fork
[src]
pub fn flush(&mut self)
[src]
Finalizes all changes that were made after previous execution of the flush
method.
If no flush
method had been called before, finalizes all changes that were
made after creation of Fork
.
pub fn rollback(&mut self)
[src]
Rolls back all changes that were made after the latest execution
of the flush
method.
pub fn into_patch(self) -> Patch
[src]
Converts the fork into Patch
consuming the fork instance.
pub fn readonly(&self) -> ReadonlyFork
[src]
Returns a readonly wrapper around the fork. Indexes created based on the readonly version cannot be modified; on the other hand, it is possible to have multiple copies of an index at the same time.
Trait Implementations
impl<'a> AsReadonly for &'a Fork
[src]
type Readonly = ReadonlyFork<'a>
Readonly version of the access.
fn as_readonly(&self) -> Self::Readonly
[src]
impl Debug for Fork
[src]
impl<'a> From<&'a Fork> for GenericRawAccess<'a>
[src]
impl<'_> From<Fork> for GenericRawAccess<'_>
[src]
impl From<Patch> for Fork
[src]
fn from(patch: Patch) -> Self
[src]
Creates a fork based on the provided patch
and snapshot
.
Note: using created fork to modify data already present in patch
may lead
to an inconsistent database state. Hence, this method is useful only if you
are sure that the fork and patch
interacted with different indexes.
impl<'a> IntoErased<'a> for &'a Fork
[src]
fn into_erased(self) -> ErasedAccess<'a>
[src]
impl<'a> RawAccess for &'a Fork
[src]
Auto Trait Implementations
impl !RefUnwindSafe for Fork
impl !Send for Fork
impl !Sync for Fork
impl Unpin for Fork
impl !UnwindSafe for Fork
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
V: MultiLane<T>,