[][src]Struct vclock::VClock

pub struct VClock<K> where
    K: Eq,
    K: Hash
{ /* fields omitted */ }

VClock encapsulates the vector clock data. Internally it's just a simple hash map containing integers.

Examples

use vclock::VClock;
let mut c1: VClock<&str>=VClock::default();
c1.incr("a");
c1.incr("a");
c1.incr("a");
c1.incr("a");
c1.incr("b");
// c1 is now a:4, b:1

Methods

impl<K> VClock<K> where
    K: Eq,
    K: Hash
[src]

pub fn new(key: K) -> VClock<K>[src]

Initialize a new vector clock with only one contributor. It is useful to avoid the new() then incr() pattern, as it performs both operations at once, without copying anything.

Examples

use vclock::VClock;
let c = VClock::new("foo"); // c is now foo:1
assert_eq!("{len:1,total:1,max:{\"foo\":1}}", format!("{}", c));

pub fn incr(&mut self, key: K)[src]

Increment a vector clock in-place.

Examples

use vclock::VClock;
let mut c = VClock::new("foo"); // c is now foo:1
c.incr("foo"); // c is now foo:2
c.incr("bar"); // c is now foo:2, bar:1
assert_eq!("{len:2,total:3,max:{\"foo\":2}}", format!("{}", c));

pub fn get(&self, key: K) -> Option<u64>[src]

Returns the counter associated to a given key.

Examples

use vclock::VClock;
let mut c = VClock::new("foo"); // c is now foo:1
c.incr("foo"); // c is now foo:2
c.incr("bar"); // c is now foo:2, bar:1
assert_eq!(2u64, c.get("foo").unwrap());
assert_eq!(1u64, c.get("bar").unwrap());
assert_eq!(None, c.get("unknown"));

pub fn len(&self) -> usize[src]

Returns the number of elements in a VClock.

Examples

use vclock::VClock;
let mut c = VClock::default();
assert_eq!(0, c.len());
c.incr("foo");
assert_eq!(1, c.len());
c.incr("foo");
assert_eq!(1, c.len());
c.incr("bar");
assert_eq!(2, c.len());

pub fn total(&self) -> u64[src]

Returns the total of all values.

This is mostly a debugging feature. You should not use this to compare clocks. If a < b then a.total() < b.total() but the reciprocity is not true. However it can be useful to have this information when auditing behavior.

Examples

use vclock::VClock;
let mut c = VClock::default();
assert_eq!(0, c.total());
c.incr("foo");
assert_eq!(1, c.total());
c.incr("foo");
assert_eq!(2, c.total());
c.incr("bar");
assert_eq!(3, c.total());

pub fn max(&self) -> Option<(&K, u64)>[src]

Returns the total of all values.

This is mostly a debugging feature. You should not use this to compare clocks. If a < b then a.total() < b.total() but the reciprocity is not true. However it can be useful to have this information when auditing behavior.

Examples

use vclock::VClock;
let mut c = VClock::default();
assert_eq!(None, c.max());
c.incr("foo");
assert_eq!(Some((&"foo",1)), c.max());
c.incr("foo");
assert_eq!(Some((&"foo",2)), c.max());
c.incr("bar");
assert_eq!(Some((&"foo",2)), c.max());

impl<K> VClock<K> where
    K: Eq,
    K: Hash,
    K: Clone
[src]

Clone trait is required for key on those methods as they actually do duplicate keys to create a new clock. While technically speaking, it might be doable to not do this, and keep references on keys, in practice it builds up interdependencies between keys and induces a lot of micro management of references and lifetimes.

pub fn next(&self, key: K) -> VClock<K>[src]

Increments a vector clock and does a fresh copy. There's no default implementation of Copy for the vector clock as, indeed, copying it can be expensive so it's not a good practice to copy it. However, when incrementing, we might want to actually get a fresh copy, as typically this incremented clock might refer to a new object.

pub fn merge(&self, other: &VClock<K>) -> VClock<K>[src]

Merge two keys, taking the max of all history points.

If there is a parentship between a and b, merge simply returns the greater of both. Merge creates a new object with clones of all keys, so it can be a costly operation on big keys.

Examples

use vclock::VClock;
let c1 = VClock::new("a");
let c2 = VClock::new("b");
let c3 = c1.merge(&c2);
assert_eq!(1u64, c3.get("a").unwrap());
assert_eq!(1u64, c3.get("b").unwrap());

Trait Implementations

impl<K: Clone> Clone for VClock<K> where
    K: Eq,
    K: Hash
[src]

impl<K: Debug> Debug for VClock<K> where
    K: Eq,
    K: Hash
[src]

impl<K> Default for VClock<K> where
    K: Eq,
    K: Hash
[src]

fn default() -> VClock<K>[src]

Return a VClock with no history at all.

impl<'de, K> Deserialize<'de> for VClock<K> where
    K: Eq,
    K: Hash,
    K: Deserialize<'de>, 
[src]

impl<K> Display for VClock<K> where
    K: Eq,
    K: Hash,
    K: Display
[src]

fn fmt(&self, f: &mut Formatter) -> Result[src]

Pretty print the vector clock, it does not dump all the data, only a few key values.

impl<K> From<HashMap<K, u64, RandomState>> for VClock<K> where
    K: Eq,
    K: Hash
[src]

fn from(src: HashMap<K, u64>) -> VClock<K>[src]

Build a vector clock from a hash map containing u64 values.

use vclock::VClock;
use std::collections::HashMap;

let mut m = HashMap::new();
m.insert("a", 3u64);
m.insert("b", 5u64);
let c = VClock::from(m);
assert_eq!(2, c.len());
assert_eq!(3, c.get("a").unwrap());
assert_eq!(5, c.get("b").unwrap());

impl<K: PartialEq> PartialEq<VClock<K>> for VClock<K> where
    K: Eq,
    K: Hash
[src]

impl<K> PartialOrd<VClock<K>> for VClock<K> where
    K: Eq,
    K: Hash
[src]

Vector clocks are partially ordered, and this is exactly what they are useful for. If the order is explicitly returned, it means one can fast-forward or fast-rewind from one point to the other in history. If not, that is, if None is returned, it means there is a conflict, and no way to directly go to one point from the other.

fn partial_cmp(&self, other: &Self) -> Option<Ordering>[src]

Compares the vector clock with another one. Note that really, this is a partial order, if both a<=b and a>=b return false, it means there is no direct parentship link between clocks.

use vclock::VClock;
use std::cmp::Ordering;

// Two vector clocks holding same values are equal.
let mut c1 = VClock::new("a");
let mut c2 = VClock::new("a");
assert_eq!(Some(Ordering::Equal), c1.partial_cmp(&c2));
assert!(c1 <= c2);

// Two vector clocks with a direct parentship are ordered.
c2.incr("a");
assert_eq!(Some(Ordering::Less), c1.partial_cmp(&c2));
assert_eq!(Some(Ordering::Greater), c2.partial_cmp(&c1));
assert!(c1 < c2);
assert!(c2 > c1);

// Two vector clocks without a direct parentship are not ordered.
c1.incr("b");
assert_eq!(None, c1.partial_cmp(&c2));
assert_eq!(None, c2.partial_cmp(&c1));
assert!(!(c1 < c2));
assert!(!(c2 > c1));

impl<K> Serialize for VClock<K> where
    K: Eq,
    K: Hash,
    K: Serialize
[src]

impl<K> StructuralPartialEq for VClock<K> where
    K: Eq,
    K: Hash
[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for VClock<K> where
    K: RefUnwindSafe

impl<K> Send for VClock<K> where
    K: Send

impl<K> Sync for VClock<K> where
    K: Sync

impl<K> Unpin for VClock<K> where
    K: Unpin

impl<K> UnwindSafe for VClock<K> where
    K: UnwindSafe

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> DeserializeOwned for T where
    T: Deserialize<'de>, 
[src]

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

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

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T> ToString for T where
    T: Display + ?Sized
[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.