Permalink
Browse files

change some terminology

  • Loading branch information...
1 parent 373f4ae commit b1671d7014471cfcb8258b66f7b9c3b81b2fb297 @etrepum etrepum committed Jun 15, 2011
Showing with 65 additions and 55 deletions.
  1. +29 −38 src/statebox_counter.erl
  2. +36 −17 test/statebox_counter_tests.erl
View
67 src/statebox_counter.erl
@@ -1,12 +1,12 @@
%% @doc Integer counter based on an ordered list of events.
-module(statebox_counter).
--export([value/1, merge/1, compact/2, inc/3]).
--export([f_inc_compact/2, f_inc_compact/3, op_inc_compact/4]).
+-export([value/1, merge/1, accumulate/2, inc/3]).
+-export([f_inc_acc/2, f_inc_acc/3, op_inc_acc/4]).
-type op() :: statebox:op().
-type timestamp() :: statebox_clock:timestamp().
-type timedelta() :: statebox:timedelta().
--type counter_id() :: statebox_identity:entropy() | merged.
+-type counter_id() :: statebox_identity:entropy() | acc.
-type counter_key() :: {timestamp(), counter_id()}.
-type counter_op() :: {counter_key(), integer()}.
-type counter() :: [counter_op()].
@@ -21,55 +21,46 @@ value([{_Key, Value} | Rest]) ->
merge([Counter]) ->
Counter;
merge(Counters) ->
- orddict:from_list(lists:umerge(compact_heads(Counters))).
+ orddict:from_list(merge_prune(Counters)).
--spec compact(timestamp(), counter()) -> counter().
-compact(Timestamp, Counter=[{T0, merged} | _]) when Timestamp =< T0 ->
+-spec accumulate(timestamp(), counter()) -> counter().
+accumulate(Timestamp, Counter=[{{T0, acc}, _} | _]) when Timestamp =< T0 ->
Counter;
-compact(Timestamp, Counter) ->
- compact(Timestamp, Counter, 0).
+accumulate(Timestamp, Counter) ->
+ accumulate(Timestamp, Counter, 0).
-spec inc(counter_key(), integer(), counter()) -> counter().
-inc({T1, _Id1}, _Value, Counter=[{T0, merged} | _Rest]) when T1 =< T0 ->
+inc({T1, _Id1}, _Value, Counter=[{{T0, acc}, _} | _Rest]) when T1 =< T0 ->
Counter;
inc(Key, Value, Counter) ->
orddict:store(Key, Value, Counter).
--spec f_inc_compact(integer(), timedelta()) -> op().
-f_inc_compact(Value, Age) ->
+-spec f_inc_acc(integer(), timedelta()) -> op().
+f_inc_acc(Value, Age) ->
Key = {statebox_clock:timestamp(), statebox_identity:entropy()},
- f_inc_compact(Value, Age, Key).
+ f_inc_acc(Value, Age, Key).
--spec f_inc_compact(integer(), timedelta(), counter_key()) -> op().
-f_inc_compact(Value, Age, Key={Timestamp, _Id}) ->
- {fun ?MODULE:op_inc_compact/4, [Timestamp - Age, Key, Value]}.
+-spec f_inc_acc(integer(), timedelta(), counter_key()) -> op().
+f_inc_acc(Value, Age, Key={Timestamp, _Id}) ->
+ {fun ?MODULE:op_inc_acc/4, [Timestamp - Age, Key, Value]}.
%% @private
-op_inc_compact(Timestamp, Key, Value, Counter) ->
- compact(Timestamp, inc(Key, Value, Counter)).
+op_inc_acc(Timestamp, Key, Value, Counter) ->
+ accumulate(Timestamp, inc(Key, Value, Counter)).
%% Internal API
-compact(Timestamp, [{{T1, _Id}, Value} | Rest], Sum) when T1 =< Timestamp ->
- compact(Timestamp, Rest, Value + Sum);
-compact(Timestamp, Counter, Sum) ->
- [{{Timestamp, merged}, Sum} | Counter].
+merge_prune(Counters) ->
+ merge_prune(lists:umerge(Counters), []).
-compact_heads(Counters) ->
- Timestamp = max_head(Counters),
- [compact_head(Counter, Timestamp) || Counter <- Counters].
+merge_prune(L=[{{_, acc}, _} | _], Acc) ->
+ lists:reverse(Acc, L);
+merge_prune([H | T], Acc) ->
+ merge_prune(T, [H | Acc]);
+merge_prune([], Acc) ->
+ lists:reverse(Acc).
-compact_head([{{T0, _Id}, _V} | Rest], Timestamp) when Timestamp > T0 ->
- compact_head(Rest, Timestamp);
-compact_head(Counter, _Timestamp) ->
- Counter.
-
-max_head(Counter) ->
- max_head(Counter, 0).
-
-max_head([], Timestamp) ->
- Timestamp;
-max_head([{{T0, merged}, _V} | Rest], Timestamp) when T0 > Timestamp ->
- max_head(Rest, T0);
-max_head([_ | Rest], Timestamp) ->
- max_head(Rest, Timestamp).
+accumulate(Timestamp, [{{T1, _Id}, Value} | Rest], Sum) when T1 =< Timestamp ->
+ accumulate(Timestamp, Rest, Value + Sum);
+accumulate(Timestamp, Counter, Sum) ->
+ inc({Timestamp, acc}, Sum, Counter).
View
53 test/statebox_counter_tests.erl
@@ -2,7 +2,7 @@
-behaviour(proper_statem).
-export([initial_state/0, command/1,
precondition/2, postcondition/3, next_state/3]).
--export([apply_f_inc_compact/2]).
+-export([apply_f_inc_acc/3, add_sibling/0, merge_siblings/1]).
-include_lib("proper/include/proper.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -13,33 +13,52 @@ clock_step() ->
default_age() ->
10 * clock_step().
-apply_f_inc_compact(Value, Counter) ->
+apply_f_inc_acc(Value, N, Counters) ->
statebox:apply_op(
- statebox_counter:f_inc_compact(Value, default_age()),
- Counter).
+ statebox_counter:f_inc_acc(Value, default_age()),
+ lists:nth(N, Counters)).
+
+add_sibling() ->
+ ok.
+
+merge_siblings(_N) ->
+ ok.
%% statem
--record(state, {counter=[], value=[0]}).
+
+%% TODO:
+%% Generate a new sibling (add_sibling)
+%% Update existing counter (apply_f_inc_acc)
+%% Merge (up to) N siblings (merge_siblings)
+%% Expiration used will be for 20 clock cycles
+-record(state, {counters=[[]], num_counters=1, value=[]}).
initial_state() ->
#state{}.
-command(#state{counter=Counter}) ->
- oneof([{call, ?MODULE, apply_f_inc_compact, [range(-3, 3), Counter]},
- {call, statebox_counter, value, [Counter]}]).
+command(#state{counters=Counters, num_counters=N}) ->
+ oneof([{call, ?MODULE, add_sibling, []},
+ {call, ?MODULE, merge_siblings, [range(1, N)]},
+ {call, ?MODULE, apply_f_inc_acc, [range(-3, 3), range(1, N), Counters]}]).
precondition(_S, _Call) ->
true.
-postcondition(S, {call, _, value, _}, Res) ->
- lists:sum(S#state.value) =:= Res;
-postcondition(S, {call, _, apply_f_inc_compact, [Inc, _]}, Res) ->
- (Inc + lists:sum(S#state.value)) =:= statebox_counter:value(Res).
-
-next_state(S, _V, {call, _, value, _}) ->
- S;
-next_state(S, V, {call, _, apply_f_inc_compact, [Inc, _C]}) ->
- S#state{counter=V, value=[Inc | S#state.value]}.
+postcondition(S, {call, _, apply_f_inc_acc, [Inc, _]}, Res) ->
+ (Inc + lists:sum(S#state.value)) =:= statebox_counter:value(Res);
+postcondition(S, {call, _, _, _}, _Res) ->
+ lists:sum(S#state.value) =:=
+ statebox_counter:value(statebox_counter:merge(S#state.counters)).
+
+next_state(S=#state{counters=[H|T]}, _V, {call, _, add_sibling, []}) ->
+ S#state{counters=[H,H|T]};
+next_state(S=#state{counters=Counters}, _V, {call, _, merge_siblings, [N]}) ->
+ {L, T} = lists:split(N, Counters),
+ S#state{counters=[statebox_counter:merge(L) | T]};
+next_state(S=#state{counters=Counters}, V, {call, _, apply_f_inc_acc, [Inc, N, _C]}) ->
+ Counters1 = lists:sublist(Counters, N - 1) ++ [V | lists:nthtail(N, Counters)],
+ S#state{counters=Counters1,
+ value=[Inc | S#state.value]}.
%% properties

0 comments on commit b1671d7

Please sign in to comment.