Module riak_dt_orswot

An OR-Set CRDT.

Behaviours: riak_dt.

References

See also: riak_dt_multi, riak_dt_vclock.

Description

An OR-Set CRDT. An OR-Set allows the adding, and removal, of elements. Should an add and remove be concurrent, the add wins. In this implementation there is a version vector for the whole set. When an element is added to the set, the version vector is incremented and the {actor(), count()} pair for that increment is stored against the element as its "birth dot". Every time the element is re-added to the set, its "birth dot" is updated to that of the {actor(), count()} version vector entry resulting from the add. When an element is removed, we simply drop it, no tombstones.

When an element exists in replica A and not replica B, is it because A added it and B has not yet seen that, or that B removed it and A has not yet seen that? Usually the presence of a tombstone arbitrates. In this implementation we compare the "birth dot" of the present element to the clock in the Set it is absent from. If the element dot is not "seen" by the Set clock, that means the other set has yet to see this add, and the item is in the merged Set. If the Set clock dominates the dot, that means the other Set has removed this element already, and the item is not in the merged Set.

Essentially we've made a dotted version vector.

Data Types

actor()

actor() = riak_dt:actor()

any_orswot()

any_orswot() = v2_orswot() | v2ord_orswot()

binary_orswot()

binary_orswot() = binary()

A binary that from_binary/1 will operate on.

deferred()

deferred() = dict(riak_dt_vclock:vclock(), [member()])

dict()

dict(_A, _B) = dict()

dot()

dot() = riak_dt:dot()

dots()

dots() = [dot()]

entries()

entries() = dict(member(), dots())

member()

member() = term()

orswot()

orswot() = v1_orswot() | v2_orswot()

orswot_op()

orswot_op() = {add, member()} | {remove, member()} | {add_all, [member()]} | {remove_all, [member()]} | {update, [orswot_op()]}

orswot_q()

orswot_q() = size | {contains, term()}

precondition_error()

precondition_error() = {error, {precondition, {not_present, member()}}}

v1_orswot()

v1_orswot() = {riak_dt_vclock:vclock(), {member(), dots()}, {riak_dt_vclock:vclock(), [member()]}}

v2_orswot()

v2_orswot() = {riak_dt_vclock:vclock(), entries(), deferred()}

v2ord_orswot()

v2ord_orswot() = {riak_dt_vclock:vclock(), orddict:orddict(), orddict:orddict()}

Function Index

equal/2
from_binary/1When the argument is a binary_orswot() produced by to_binary/1 will return the original orswot().
merge/2
new/0
parent_clock/2sets the clock in the Set to that Clock.
precondition_context/1the precondition context is a fragment of the CRDT that operations requiring certain pre-conditions can be applied with.
stat/2
stats/1
to_binary/1returns a binary representation of the provided orswot().
to_version/2
update/3take a list of Set operations and apply them to the set.
update/4
value/1
value/2

Function Details

equal/2

equal(LHS::orswot(), RHS::orswot()) -> boolean()

from_binary/1

from_binary(B::binary_orswot()) -> {ok, orswot()} | {error, unsupported_version, Vers::pos_integer()} | {error, invalid_binary}

When the argument is a binary_orswot() produced by to_binary/1 will return the original orswot().

See also: to_binary/1.

merge/2

merge(LHS::orswot(), RHS::orswot()) -> orswot()

new/0

new() -> orswot()

parent_clock/2

parent_clock(Clock::riak_dt_vclock:vclock(), Set::orswot()) -> orswot()

sets the clock in the Set to that Clock. Used by a containing Map for sub-CRDTs

precondition_context/1

precondition_context(X1::orswot()) -> orswot()

the precondition context is a fragment of the CRDT that operations requiring certain pre-conditions can be applied with. Especially useful for hybrid op/state systems where the context of an operation is needed at a replica without sending the entire state to the client. In the case of the ORSWOT the context is a version vector. When passed as an argument to update/4 the context ensures that only seen adds are removed, and that removes of unseen adds can be deferred until they're seen.

stat/2

stat(Stat::atom(), S::orswot()) -> number() | undefined

stats/1

stats(ORSWOT::orswot()) -> [{atom(), number()}]

to_binary/1

to_binary(S::orswot()) -> binary_orswot()

returns a binary representation of the provided orswot(). The resulting binary is tagged and versioned for ease of future upgrade. Calling from_binary/1 with the result of this function will return the original set. Use the application env var binary_compression to turn t2b compression on (true) and off (false)

See also: from_binary/1.

to_version/2

to_version(X1::pos_integer(), Set::any_orswot()) -> any_orswot()

update/3

update(Op::orswot_op(), Actor::actor() | dot(), V1Set::orswot()) -> {ok, orswot()} | precondition_error()

take a list of Set operations and apply them to the set. NOTE: either _all_ are applied, or _none_ are.

update/4

update(Op::orswot_op(), Actor::actor() | dot(), V1Set::orswot(), Ctx::riak_dt:context()) -> {ok, orswot()} | precondition_error()

value/1

value(X1::orswot()) -> [member()]

value/2

value(X1::orswot_q(), ORset::orswot()) -> term()


Generated by EDoc