pub struct State<ID: TreeId, TM: TreeMeta, A: Actor> { /* private fields */ }
Expand description
Holds Tree CRDT state and implements the core algorithm.
State
is not tied to any actor/peer and should be equal on any
two replicas where each has applied the same operations.
State
may be instantiated to manipulate a CRDT Tree or
alternatively the higher level TreeReplica
may be used.
For usage/examples, see: tests/tree.rs
This code aims to be an accurate implementation of the tree crdt algorithm described in:
“A highly-available move operation for replicated trees and distributed filesystems” [1] by Martin Klepmann, et al.
[1] https://martin.kleppmann.com/papers/move-op.pdf
Implementations§
Source§impl<ID: TreeId, TM: TreeMeta, A: Actor> State<ID, TM, A>
impl<ID: TreeId, TM: TreeMeta, A: Actor> State<ID, TM, A>
Sourcepub fn tree_mut(&mut self) -> &mut Tree<ID, TM>
pub fn tree_mut(&mut self) -> &mut Tree<ID, TM>
returns mutable Tree reference
Warning: this is dangerous. Normally the Tree
should
not be mutated directly.
See the demo_move_to_trash in examples/demo.rs for a use-case, only after log truncation has been performed.
Sourcepub fn log(&self) -> &Vec<LogOpMove<ID, TM, A>>
pub fn log(&self) -> &Vec<LogOpMove<ID, TM, A>>
returns log reference
Examples found in repository?
211fn demo_truncate_log() {
212 let mut replicas: Vec<TreeReplica<TypeId, TypeMeta, TypeActor>> = Vec::new();
213 let num_replicas = 5;
214
215 // start some replicas.
216 for _i in 0..num_replicas {
217 // pass true flag to enable causally stable threshold tracking
218 let r: TreeReplica<TypeId, TypeMeta, TypeActor> = TreeReplica::new(new_id());
219 replicas.push(r);
220 }
221
222 let root_id = new_id();
223
224 // Generate initial tree state.
225 let mut opmoves = vec![replicas[0].opmove(0, "root", root_id)];
226
227 println!("generating move operations...");
228
229 // generate some initial ops from all replicas.
230 for r in replicas.iter_mut() {
231 let finaldepth = rand::thread_rng().gen_range(3, 6);
232 let mut ops = vec![];
233 mktree_ops(&mut ops, r, root_id, 2, finaldepth);
234 opmoves.extend(r.opmoves(ops));
235 }
236
237 // apply all ops to all replicas
238 println!(
239 "applying {} operations to all {} replicas...\n",
240 opmoves.len(),
241 replicas.len()
242 );
243 apply_ops_to_replicas(&mut replicas, &opmoves);
244
245 #[derive(Debug)]
246 #[allow(dead_code)]
247 struct Stat {
248 pub replica: TypeActor,
249 pub ops_before_truncate: usize,
250 pub ops_after_truncate: usize,
251 }
252
253 let mut stats: Vec<Stat> = Vec::new();
254 for r in replicas.iter_mut() {
255 println!("truncating log of replica {}...", r.id());
256 println!(
257 "causally stable threshold: {:?}\n",
258 r.causally_stable_threshold()
259 );
260 let ops_b4 = r.state().log().len();
261 r.truncate_log();
262 let ops_after = r.state().log().len();
263 stats.push(Stat {
264 replica: *r.id(),
265 ops_before_truncate: ops_b4,
266 ops_after_truncate: ops_after,
267 });
268 }
269
270 println!("-- Stats -- ");
271 println!("\n{:#?}", stats);
272}
Sourcepub fn add_log_entry(&mut self, entry: LogOpMove<ID, TM, A>)
pub fn add_log_entry(&mut self, entry: LogOpMove<ID, TM, A>)
add_log_entry
Sourcepub fn truncate_log_before(&mut self, timestamp: &Clock<A>) -> bool
pub fn truncate_log_before(&mut self, timestamp: &Clock<A>) -> bool
removes log entries before a given timestamp. not part of crdt-tree algo.
Sourcepub fn do_op(&mut self, op: OpMove<ID, TM, A>) -> LogOpMove<ID, TM, A>
pub fn do_op(&mut self, op: OpMove<ID, TM, A>) -> LogOpMove<ID, TM, A>
The do_op function performs the actual work of applying a move operation.
This function takes as argument a pair consisting of a Move operation and the current tree and it returns a pair consisting of a LogMove operation (which will be added to the log) and an updated tree.
Sourcepub fn redo_op(&mut self, log: LogOpMove<ID, TM, A>)
pub fn redo_op(&mut self, log: LogOpMove<ID, TM, A>)
redo_op uses do_op to perform an operation
again and recomputes the LogMove
record (which
might have changed due to the effect of the new operation)
Sourcepub fn apply_op(&mut self, op1: OpMove<ID, TM, A>)
pub fn apply_op(&mut self, op1: OpMove<ID, TM, A>)
See general description of apply/undo/redo above.
The apply_op func takes two arguments:
a Move
operation to apply and the current replica
state; and it returns the new replica state.
The constrains t::{linorder} in the type signature indicates that timestamps
t are instance if linorder
type class, and they can therefore be compared with the
< operator during a linear (or total) order.
Sourcepub fn apply_ops_into(&mut self, ops: Vec<OpMove<ID, TM, A>>)
pub fn apply_ops_into(&mut self, ops: Vec<OpMove<ID, TM, A>>)
applies a list of operations and consume them. (no cloning)
Trait Implementations§
Source§impl<ID: TreeId, TM: TreeMeta, A: Actor> CmRDT for State<ID, TM, A>
impl<ID: TreeId, TM: TreeMeta, A: Actor> CmRDT for State<ID, TM, A>
Source§type Op = OpMove<ID, TM, A>
type Op = OpMove<ID, TM, A>
Source§impl<'de, ID, TM, A> Deserialize<'de> for State<ID, TM, A>
impl<'de, ID, TM, A> Deserialize<'de> for State<ID, TM, A>
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<ID: TreeId, A: Actor, TM: TreeMeta> From<(Vec<LogOpMove<ID, TM, A>>, Tree<ID, TM>)> for State<ID, TM, A>
impl<ID: TreeId, A: Actor, TM: TreeMeta> From<(Vec<LogOpMove<ID, TM, A>>, Tree<ID, TM>)> for State<ID, TM, A>
Source§impl<ID: TreeId, TM: TreeMeta, A: Actor> IntoIterator for State<ID, TM, A>
Implement IntoIterator
for State
. This is useful for
walking all Nodes in a tree without knowing a starting point.
impl<ID: TreeId, TM: TreeMeta, A: Actor> IntoIterator for State<ID, TM, A>
Implement IntoIterator
for State
. This is useful for
walking all Nodes in a tree without knowing a starting point.
Source§impl<ID: PartialEq + TreeId, TM: PartialEq + TreeMeta, A: PartialEq + Actor> PartialEq for State<ID, TM, A>
impl<ID: PartialEq + TreeId, TM: PartialEq + TreeMeta, A: PartialEq + Actor> PartialEq for State<ID, TM, A>
impl<ID: Eq + TreeId, TM: Eq + TreeMeta, A: Eq + Actor> Eq for State<ID, TM, A>
impl<ID: TreeId, TM: TreeMeta, A: Actor> StructuralPartialEq for State<ID, TM, A>
Auto Trait Implementations§
impl<ID, TM, A> Freeze for State<ID, TM, A>
impl<ID, TM, A> RefUnwindSafe for State<ID, TM, A>
impl<ID, TM, A> Send for State<ID, TM, A>
impl<ID, TM, A> Sync for State<ID, TM, A>
impl<ID, TM, A> Unpin for State<ID, TM, A>
impl<ID, TM, A> UnwindSafe for State<ID, TM, A>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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