aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/diameter/src/base/diameter_stats.erl32
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl92
2 files changed, 80 insertions, 44 deletions
diff --git a/lib/diameter/src/base/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl
index 8d4b456bd2..70727d068e 100644
--- a/lib/diameter/src/base/diameter_stats.erl
+++ b/lib/diameter/src/base/diameter_stats.erl
@@ -25,8 +25,8 @@
-behaviour(gen_server).
--export([reg/1, reg/2,
- incr/1, incr/3,
+-export([reg/2, reg/1,
+ incr/3, incr/1,
read/1,
flush/1]).
@@ -96,9 +96,10 @@ reg(Ref) ->
%% ---------------------------------------------------------------------------
-spec incr(counter(), ref(), integer())
- -> integer().
+ -> integer() | false.
-incr(Ctr, Ref, N) ->
+incr(Ctr, Ref, N)
+ when is_integer(N) ->
update_counter({Ctr, Ref}, N).
incr(Ctr) ->
@@ -177,6 +178,9 @@ handle_call(state, _, State) ->
handle_call(uptime, _, #state{id = Time} = State) ->
{reply, diameter_lib:now_diff(Time), State};
+handle_call({incr, T}, _, State) ->
+ {reply, update_counter(T), State};
+
handle_call({reg, Pid, Ref}, _From, State) ->
B = ets:insert_new(?TABLE, {Pid, Ref}),
B andalso erlang:monitor(process, Pid),
@@ -193,10 +197,6 @@ handle_call(Req, From, State) ->
%% # handle_cast/2
%% ----------------------------------------------------------
-handle_cast({incr, Rec}, State) ->
- update_counter(Rec),
- {noreply, State};
-
handle_cast(Msg, State) ->
?UNEXPECTED([Msg]),
{noreply, State}.
@@ -246,21 +246,22 @@ fold(Ref, L) ->
%% update_counter/2
%%
-%% From an arbitrary process. Cast to the server process to insert a
+%% From an arbitrary process. Call to the server process to insert a
%% new element if the counter doesn't exists so that two processes
-%% don't do so simultaneously.
+%% don't insert simultaneously.
update_counter(Key, N) ->
try
ets:update_counter(?TABLE, Key, N)
catch
error: badarg ->
- cast({incr, {Key, N}})
+ call({incr, {Key, N}})
end.
%% update_counter/1
%%
-%% From the server process.
+%% From the server process, when update_counter/2 failed due to a
+%% non-existent entry.
update_counter({{_Ctr, Ref} = Key, N} = T) ->
try
@@ -268,7 +269,7 @@ update_counter({{_Ctr, Ref} = Key, N} = T) ->
catch
error: badarg ->
(not is_pid(Ref) orelse ets:member(?TABLE, Ref))
- andalso insert(T)
+ andalso begin insert(T), N end
end.
insert(T) ->
@@ -280,11 +281,6 @@ lookup(Key) ->
delete(Objs) ->
lists:foreach(fun({K,_}) -> ets:delete(?TABLE, K) end, Objs).
-%% cast/1
-
-cast(Msg) ->
- gen_server:cast(?SERVER, Msg).
-
%% call/1
call(Request) ->
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
index e7807fd360..4a93d4f748 100644
--- a/lib/diameter/test/diameter_stats_SUITE.erl
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,11 +30,12 @@
end_per_suite/1]).
%% testcases
--export([an/1,
- twa/1]).
+-export([reg/1,
+ incr/1,
+ read/1,
+ flush/1]).
-define(stat, diameter_stats).
--define(util, diameter_util).
%% ===========================================================================
@@ -49,8 +50,10 @@ groups() ->
[{all, [], tc()}].
tc() ->
- [an,
- twa].
+ [reg,
+ incr,
+ read,
+ flush].
init_per_suite(Config) ->
ok = diameter:start(),
@@ -61,25 +64,62 @@ end_per_suite(_Config) ->
%% ===========================================================================
-an(_) ->
- Ref = {'_', make_ref()},
+reg(_) ->
+ Ref = '$1',
true = ?stat:reg(Ref),
- true = ?stat:reg(Ref), %% duplicate
- ok = ?stat:incr(x),
- ok = ?stat:incr(x, Ref),
- ok = ?stat:incr(y, 2),
- ok = ?stat:incr(y, Ref),
- %% Flushing a pid flushes even stats on the registered reference.
- [{x,2},{y,3}] = lists:sort(?stat:flush()),
- [] = ?stat:flush(Ref),
- [] = ?stat:flush().
-
-twa(_) ->
+ false = ?stat:reg(Ref). %% duplicate
+
+incr(_) ->
+ Ref = '_',
+ Ctr = x,
+ false = ?stat:incr(Ctr), %% not registered,
+ 1 = ?stat:incr(Ctr, Ref, 1), %% only pids need register
+ true = ?stat:reg(Ref),
+ spawn(fun() ->
+ true = ?stat:reg(Ref),
+ 2 = ?stat:incr(Ctr, self(), 2)
+ end),
+ ok = fold(Ctr, Ref, 3), %% folded
+ ?stat:flush([self(), Ref]).
+
+read(_) ->
+ Ref = make_ref(),
+ C1 = {a,b},
+ C2 = {b,a},
+ true = ?stat:reg(Ref),
+ 1 = ?stat:incr(C1),
+ 1 = ?stat:incr(C2),
+ 2 = ?stat:incr(C1),
+ 7 = ?stat:incr(C1, Ref, 7),
+ Self = self(),
+ [{Ref, [{C1,7}]}, {Self, [{C1,2}, {C2,1}]}]
+ = lists:sort(?stat:read([self(), Ref, make_ref()])),
+ [] = ?stat:read([]),
+ [] = ?stat:read([make_ref()]),
+ ?stat:flush([self(), Ref, make_ref()]).
+
+flush(_) ->
Ref = make_ref(),
- ok = ?stat:incr(x, 8),
- ok = ?stat:incr(x, Ref, 7),
- %% Flushing a reference doesn't affect registered pids.
- [{x,7}] = ?stat:flush(Ref),
- [] = ?stat:flush(Ref),
- [{x,8}] = ?stat:flush(),
- [] = ?stat:flush().
+ Ctr = '_',
+ true = ?stat:reg(Ref),
+ 1 = ?stat:incr(Ctr),
+ 3 = ?stat:incr(Ctr, self(), 2),
+ 2 = ?stat:incr(Ctr, Ref, 2),
+ Self = self(),
+ [{Self, [{Ctr, 3}]}] = ?stat:flush([self()]),
+ 1 = ?stat:incr(Ctr),
+ [{Ref, [{Ctr, 2}]}] = ?stat:flush([Ref]),
+ [{Self, [{Ctr, 1}]}] = ?stat:flush([self()]),
+ [] = ?stat:flush([self(), Ref]).
+
+%% ===========================================================================
+
+%% Keep incremented until a fold results in the specified value.
+fold(Ctr, Ref, N) ->
+ case ?stat:incr(Ctr, Ref, 0) of
+ N ->
+ ok;
+ M when M < N ->
+ erlang:yield(),
+ fold(Ctr, Ref, N)
+ end.