Version: 0.2.0
Authors: Nyiro, Gergo (gergo.nyiro@gmail.com).
References
Interval tree clock (itc) is a good candidate for a logical clock in a distributed system where the members join and leave the cluster very often.
Itc offers the following actions:1> Tic0 = itc:seed(). {1,0}Create clock for a new cluster member:
2> [Tic1, Toc1] = itc:fork(Tic0). [{{1,0},0},{{0,1},0}]The forked clock cannot be compared to the original clock:
3> itc:leq(TicA0, TicA1). true 4> itc:leq(TicA1, TicA0). trueOnly the tic of the next event can be compared to the original clock:
5> Tic2 = itc:event(Tic1). {{1,0},{0,1,0}} 6> Toc2 = itc:event(Toc1). {{0,1},{0,0,1}}So the clocks can be ordered:
7> itc:leq(Tic0, Tic2). true 8> itc:leq(Tic2, Tic0). falseIf the cluster nodes are synchronized then the clocks can be joined
9> TicC3 = itc:join(TicA2, TicB2). {1,1} 10> itc:leq(TicA2, TicC3). trueand the new clock can be used in the syncronized nodes.
store:init/0
function:
1> EventsA0 = store:init(). [{{1,0},init}]New action can be added to the store with
store:append/2
function. (The action
can be any term in our example.)
2> EventsA1 = store:append(EventsA0, {action, 1}). [{{1,1},{action,1}},{{1,0},init}] 3> EventsA2 = store:append(EventsA0, {action, 2}). [{{1,2},{action,2}},{{1,1},{action,1}},{{1,0},init}]A new event store can be forked with the
store:fork/1
function:
4> [EventsA3, EventsB3] = store:fork(EventsA2). [[{{{1,0},2},fork}, {{1,2},{action,2}}, {{1,1},{action,1}}, {{1,0},init}], [{{{0,1},2},fork}, {{1,2},{action,2}}, {{1,1},{action,1}}, {{1,0},init}]]The event store may got separated events, but the last common time stamp can be found with the
store:get_last_seen_event_tic/2
. (Where the second
parameter is the last time stamp of the compared event store.)
5> EventsA4 = store:append(EventsA3, {action, 4}). [{{{1,0},{2,1,0}},{action,4}}, {{{1,0},2},fork}, {{1,2},{action,2}}, {{1,1},{action,1}}, {{1,0},init}] 6> EventsA5 = store:append(EventsA4, {action, 5}). [{{{1,0},{2,2,0}},{action,5}}, {{{1,0},{2,1,0}},{action,4}}, {{{1,0},2},fork}, {{1,2},{action,2}}, {{1,1},{action,1}}, {{1,0},init}] 7> EventsB4 = store:append(EventsB3, {action, 14}). [{{{0,1},{2,0,1}},{action,14}}, {{{0,1},2},fork}, {{1,2},{action,2}}, {{1,1},{action,1}}, {{1,0},init}] 8> LastTic = store:get_last_tic(EventsA5). {{1,0},{2,2,0 9> SyncFrom = store:get_last_seen_event_tic(EventsB3, LastTic). {{0,1},2}The unseen events can be selected with the
store:list_unseen_events/2
function,
where the second parameter is the last common time stamp from the
store:get_last_seen_event_tic
function. And the unseen events can be merged
into the event store with the store:merge/2
function.
10> UnseenEventsA = store:list_unseen_events(EventsA5, SyncFrom). [{{{1,0},{2,2,0}},{action,5}},{{{1,0},{2,1,0}},{action,4}}] 11> store:merge(EventsB3, UnseenEventsA). [{{1,4},merge}, {{{1,0},{2,2,0}},{action,5}}, {{{1,0},{2,1,0}},{action,4}}, {{{0,1},2},fork}, {{1,2},{action,2}}, {{1,1},{action,1}}, {{1,0},init}]As you can see the time stamp of the merge event is normalized, because the two branch of the itc is merged too.
Generated by EDoc