8
8
% % @doc
9
9
% % An operation based implementation of the bounded counter CRDT.
10
10
% % This counter is able to maintain a non-negative value by
11
- % % explicitly exchanging permissions to execute decrement operations.
11
+ % % explicitly exchanging permissions to execute decrement operations.
12
12
% % All operations on this CRDT are monotonic and do not keep extra tombstones.
13
13
% % @end
14
14
27
27
to_binary /1 ,
28
28
from_binary /1 ,
29
29
is_operation /1 ,
30
- require_state_downstream /1
30
+ require_state_downstream /1 ,
31
+ generate_downstream_check /4
31
32
]).
32
33
33
34
% % API
44
45
-opaque bcounter () :: {orddict :orddict (),orddict :orddict ()}.
45
46
-type binary_bcounter () :: binary ().
46
47
-type bcounter_op () :: bcounter_anon_op () | bcounter_src_op ().
47
- -type bcounter_anon_op () :: {transfer , {pos_integer (), id (), id ()}} |
48
+ -type bcounter_anon_op () :: {transfer , {pos_integer (), id (), id ()}} |
48
49
{increment , {pos_integer (), id ()}} | {decrement , {pos_integer (), id ()}}.
49
50
-type bcounter_src_op () :: {bcounter_anon_op (), id ()}.
50
51
-opaque id () :: term . % % A replica's identifier.
@@ -56,46 +57,46 @@ new() ->
56
57
57
58
% % @doc Return the available permissions of replica `Id' in a `bcounter()'.
58
59
-spec localPermissions (id (),bcounter ()) -> non_neg_integer ().
59
- localPermissions (Id ,{P ,D }) ->
60
+ localPermissions (Id ,{P ,D }) ->
60
61
Received = lists :foldl (
61
62
fun (
62
63
{_ ,V },Acc ) ->
63
- Acc + V
64
+ Acc + V
64
65
end ,
65
66
0 , orddict :filter (
66
67
fun (
67
68
{_ ,To },_ ) when To == Id ->
68
- true ;
69
+ true ;
69
70
(_ ,_ ) ->
70
- false
71
+ false
71
72
end , P )),
72
73
Granted = lists :foldl (
73
74
fun
74
75
({_ ,V },Acc ) ->
75
- Acc + V
76
+ Acc + V
76
77
end , 0 , orddict :filter (
77
78
fun
78
79
({From ,To },_ ) when From == Id andalso To /= Id ->
79
80
true ;
80
81
(_ ,_ ) ->
81
- false
82
+ false
82
83
end , P )),
83
84
case orddict :find (Id ,D ) of
84
- {ok , Decrements } ->
85
+ {ok , Decrements } ->
85
86
Received - Granted - Decrements ;
86
- error ->
87
+ error ->
87
88
Received - Granted
88
89
end .
89
90
90
91
% % @doc Return the total available permissions in a `bcounter()'.
91
92
- spec permissions (bcounter ()) -> non_neg_integer ().
92
- permissions ({P ,D }) ->
93
+ permissions ({P ,D }) ->
93
94
TotalIncrements = orddict :fold (
94
95
fun
95
96
({K ,K },V ,Acc ) ->
96
- V + Acc ;
97
+ V + Acc ;
97
98
(_ ,_ ,Acc ) ->
98
- Acc
99
+ Acc
99
100
end , 0 , P ),
100
101
TotalDecrements = orddict :fold (
101
102
fun
@@ -146,15 +147,15 @@ update({{transfer, V,To},From}, Counter) ->
146
147
transfer (From ,To ,V ,Counter ).
147
148
148
149
% % Add a given amount of permissions to a replica.
149
- increment (Id ,V ,{P ,D }) ->
150
+ increment (Id ,V ,{P ,D }) ->
150
151
{ok ,{orddict :update_counter ({Id ,Id },V ,P ),D }}.
151
152
152
153
% % Consume a given amount of permissions from a replica.
153
- decrement (Id ,V ,{P ,D }) ->
154
+ decrement (Id ,V ,{P ,D }) ->
154
155
{ok , {P ,orddict :update_counter (Id ,V ,D )}}.
155
156
156
157
% % Transfer a given amount of permissions from one replica to another.
157
- transfer (From ,To ,V ,{P ,D }) ->
158
+ transfer (From ,To ,V ,{P ,D }) ->
158
159
{ok , {orddict :update_counter ({From ,To },V ,P ),D }}.
159
160
160
161
% % doc Return the binary representation of a `bcounter()'.
@@ -221,7 +222,7 @@ localPermisisons_test() ->
221
222
? assertEqual (10 , localPermissions (r1 ,Counter1 )),
222
223
% % Test nonexistent replica.
223
224
? assertEqual (0 , localPermissions (r2 ,Counter1 )).
224
-
225
+
225
226
% % Tests decrement operations.
226
227
decrement_test () ->
227
228
Counter0 = new (),
0 commit comments