Module riak_dt_emcntr

A PN-Counter CRDT.

Behaviours: riak_dt.

References

See also: riak_kv_gcounter.

Description

A PN-Counter CRDT. A PN-Counter is essentially two G-Counters: one for increments and one for decrements. The value of the counter is the difference between the value of the Positive G-Counter and the value of the Negative G-Counter. However, this PN-Counter is for using embedded in a riak_dt_map. The problem with an embedded pn-counter is when the field is removed and added again. PN-Counter merge takes the max of P and N as the merged value. In the case that a field was removed and re-added P and N maybe be _lower_ than their removed values, and when merged with a replica that has not seen the remove, the remove is lost. This counter adds some causality by storing a dot with P and N. Merge takes the max event for each actor, so newer values win over old ones. The rest of the mechanics are the same.

Data Types

decrement_op()

decrement_op() = decrement | {decrement, integer()}

emcntr()

emcntr() = {riak_dt_vclock:vclock(), [entry()]}

emcntr_op()

emcntr_op() = increment_op() | decrement_op()

entry()

entry() = {Actor::riak_dt:actor(), {Event::pos_integer(), Inc::pos_integer(), Dec::pos_integer()}}

increment_op()

increment_op() = increment | {increment, integer()}

Function Index

equal/2equality of two counters internal structure, not the value/1 they produce.
from_binary/1Decode a binary encoded riak_dt_emcntr.
merge/2takes two emcntr()s and merges them into a single emcntr().
new/0
parent_clock/2embedded CRDTs most share a causal context with their parent Map, setting the internal clock to the parent clock ensures this.
stat/2generate stat for requested stat type at first argument.
stats/1generate stats for this counter.
to_binary/1produce a compact binary representation of the counter.
to_binary/2
to_version/2
update/3increment/decrement the counter.
update/4update with a context.
value/1the current integer value of the counter.
value/2query value, not implemented.

Function Details

equal/2

equal(X1::emcntr(), X2::emcntr()) -> boolean()

equality of two counters internal structure, not the value/1 they produce.

from_binary/1

from_binary(Bin::binary()) -> {ok, emcntr()} | {error, invalid_binary} | {error, unsupported_version, Vers::pos_integer()}

Decode a binary encoded riak_dt_emcntr.

See also: to_binary/1.

merge/2

merge(Cnt::emcntr(), X2::emcntr()) -> emcntr()

takes two emcntr()s and merges them into a single emcntr(). This is the Least Upper Bound of the Semi-Lattice/CRDT literature. The semantics of the emnctr() merge are explained in the module docs. In a nutshell, merges version vectors, and keeps only dots that are present on both sides, or concurrent.

new/0

new() -> emcntr()

parent_clock/2

parent_clock(Clock::riak_dt_vclock:vclock(), X2::emcntr()) -> emcntr()

embedded CRDTs most share a causal context with their parent Map, setting the internal clock to the parent clock ensures this

stat/2

stat(X1::atom(), X2::emcntr()) -> pos_integer() | undefined

generate stat for requested stat type at first argument. Only actor_count is supported at present. Return a pos_integer() for the stat requested, or undefined if stat type is unsupported.

stats/1

stats(Emcntr::emcntr()) -> [{actor_count, pos_integer()}]

generate stats for this counter. Only actor_count is produced at present.

to_binary/1

to_binary(Cntr::emcntr()) -> binary()

produce a compact binary representation of the counter.

See also: from_binary/1.

to_binary/2

to_binary(Vers::pos_integer(), Cntr::emcntr()) -> {ok, binary()} | {error, unsupported_version, Vers::pos_integer()}

to_version/2

to_version(Version::pos_integer(), Cntr::emcntr()) -> emcntr()

update/3

update(Op::emcntr_op(), Dot::riak_dt:dot(), X3::emcntr()) -> {ok, emcntr()}

increment/decrement the counter. Op is either a two tuple of {increment, By}, {decrement, By} where By is a positive integer. Or simply the atoms increment or decrement, which are equivalent to {increment | decrement, 1} Returns the updated counter.

Note: the second argument must be a riak_dt:dot(), that is a 2-tuple of {Actor :: term(), Event :: pos_integer()} as this is for embedding in a riak_dt_map

update/4

update(Op::emcntr_op(), Dot::riak_dt:dot(), Cntr::emcntr(), Ctx::riak_dt_vclock:vclock()) -> {ok, emcntr()}

update with a context. Contexts have no effect. Same as update/3

value/1

value(X1::emcntr()) -> integer()

the current integer value of the counter

value/2

value(X1::term(), Cntr::emcntr()) -> integer()

query value, not implemented. Just returns result of value/1


Generated by EDoc