Function merkle_search_tree::diff::diff
source · pub fn diff<'p, 'a: 'p, T, U, K>(local: T, peer: U) -> Vec<DiffRange<'p, K>>where
T: IntoIterator<Item = PageRange<'a, K>>,
U: IntoIterator<Item = PageRange<'p, K>>,
K: PartialOrd + Ord + Debug + 'p + 'a,Expand description
Compute the difference between local and peer, returning the set of
DiffRange covering the inconsistent key ranges found in peer.
use merkle_search_tree::{MerkleSearchTree, diff::diff};
// Initialise a "peer" tree.
let mut node_a = MerkleSearchTree::default();
node_a.upsert("bananas", &42);
node_a.upsert("plátanos", &42);
// Initialise the "local" tree with differing keys
let mut node_b = MerkleSearchTree::default();
node_b.upsert("donkey", &42);
// Generate the tree hashes before serialising the page ranges
node_a.root_hash();
node_b.root_hash();
// Generate the tree page bounds & hashes, and feed into the diff function
let diff_range = diff(
node_b.serialise_page_ranges().unwrap().into_iter(),
node_a.serialise_page_ranges().unwrap().into_iter(),
);
// The diff_range contains all the inclusive key intervals the "local" tree
// should fetch from the "peer" tree to converge.
assert_matches::assert_matches!(diff_range.as_slice(), [range] => {
assert_eq!(range.start(), &"bananas");
assert_eq!(range.end(), &"plátanos");
});State Convergence
To converge the state of the two trees, the key ranges in the returned
DiffRange instances should be requested from peer and used to update
the state of local.
If local is a superset of peer (contains all the keys in peer and the
values are consistent), or the two trees are identical, no DiffRange
intervals are returned.
Optimistic Page Bounds Fetching
When a page exists in peer has a key range that is a strict superset of
the key range of the same page in local, it is guaranteed to be
inconsistent. When this occurs, only the difference / missing keys are
returned in that page’s DiffRange.
This optimistically assumes the intersection of keys between the two pages
are consistent, minimising the number of keys fetched when this assumption
holds true. If false, the page will be marked fully inconsistent (inclusive
of the newly fetched keys) in the next diff() call.
This optimises for monotonic keys, recommended to minimise tree page inconsistencies / keys fetched when new keys are inserted into the tree.
Termination
A single invocation to diff() always terminates, and completes in O(n)
time and space. Inconsistent page ranges (if any) are minimised in
O(n_consistent * n_inconsistent) time and O(n) space.
In the absence of further external updates to either tree, this algorithm
terminates (leaving local and peer fully converged) and no diff is
returned within a finite number of sync rounds between the two trees.
If a one-way sync is performed (pulling inconsistent keys from peer and
updating local, but never syncing the other way around) this algorithm MAY
NOT terminate.