[][src]Struct exonum_merkledb::migration::MigrationHelper

pub struct MigrationHelper { /* fields omitted */ }

Migration helper.

Examples

See the module docs for a basic example of usage.

Aborting migration

MigrationHelper offers AbortHandle to abort migration logic. Once aborted, MigrationHelper does not allow to merge changes to the database; the relevant methods will return MigrationError::Aborted. This is important, e.g., to prevent unnecessary writes to the database.

let db = TemporaryDB::new();
// Since `MigrationHelper` cannot be sent between threads, we instantiate it
// in a newly spawned thread and move the helper handle to the main thread.
let (tx, rx) = mpsc::channel();
let helper_thread = thread::spawn(move || {
    let (mut helper, handle) = MigrationHelper::with_handle(db, "test");
    tx.send(handle).unwrap();
    // Emulate some work...
    thread::sleep(Duration::from_millis(50));
    // Attempt to merge changes to DB.
    helper.merge()
});

let handle = rx.recv().unwrap();
// Migration is automatically aborted when the handle is dropped.
drop(handle);
let res: Result<(), MigrationError> = helper_thread.join().unwrap();
assert_matches!(res, Err(MigrationError::Aborted));

Using persistent iterators

MigrationHelper offers the iter_loop method, which allows to further simplify working with persistent iterators.

Say we want to migrate MapIndex data to a ProofMapIndex while merging changes to the DB from time to time. To do this, we use the following script:

/// Number of accounts processed per DB merge.
const CHUNK_SIZE: usize = 100;

let db = TemporaryDB::new();
let mut helper = MigrationHelper::new(db, "test");
helper.iter_loop(|helper, iters| {
    // The data before migration is stored in this map
    let old_map = helper.old_data().get_map::<_, str, u64>("wallets");
    // ...and the new data is in this merkelized map.
    let mut new_map = helper.new_data().get_proof_map::<_, str, u64>("wallets");

    // Create an iterator over the old data.
    let iter = iters.create("wallets", &old_map);
    // Take a fixed amount of records from the iterator and migrate them.
    // Since `iter` is persistent, it will not return the same record twice,
    // even if this script is restarted.
    for (name, balance) in iter.take(CHUNK_SIZE) {
        new_map.put(&name, balance);
    }
})?;
// Here, the iterator has run out of items. The script can now perform
// other actions if necessary.

Methods

impl MigrationHelper[src]

pub fn new(db: impl Into<Arc<dyn Database>>, namespace: &str) -> Self[src]

Creates a new helper.

pub fn with_handle(
    db: impl Into<Arc<dyn Database>>,
    namespace: &str
) -> (Self, AbortHandle)
[src]

Creates a new helper together with the abort handle. Unlike the MigrationHelper, the handle may be sent between threads. The handle allows to determine whether the migration helper was completed, and allows to abort the migration by preventing further writes to the database.

pub fn new_data(&self) -> Migration<&Fork>[src]

Returns full access to the new version of migrated data.

pub fn scratchpad(&self) -> Scratchpad<&Fork>[src]

Returns the scratchpad for temporary data to use during migration.

pub fn old_data(&self) -> Prefixed<ReadonlyFork>[src]

Returns readonly access to the old version of migrated data.

pub fn merge(&mut self) -> Result<(), MigrationError>[src]

Merges the changes to the migrated data and the scratchpad to the database. Returns an error if the merge has failed.

merge does not flush the migration; the migrated data remains in a separate namespace. Use flush_migration to flush the migrated data.

pub fn iter_loop(
    &mut self,
    step: impl FnMut(&Self, &mut PersistentIters<Scratchpad<&Fork>>)
) -> Result<(), MigrationError>
[src]

Executes the provided closure in a loop until all persistent iterators instantiated within the closure have ended. After each iteration, the changes in migrated data are merged to the database; an error is returned if this merge fails.

If no iterators are instantiated within the closure, a single iteration will be performed.

pub fn finish(self) -> Result<Hash, MigrationError>[src]

Merges the changes to the migrated data and the migration scratchpad to the database. Returns hash representing migrated data state, or an error if the merge has failed.

finish does not flush the migration; the migrated data remains in a separate namespace. Use flush_migration to flush the migrated data.

Trait Implementations

impl Debug for MigrationHelper[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.

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