diff options
-rw-r--r-- | lib/diameter/src/base/diameter_stats.erl | 32 | ||||
-rw-r--r-- | lib/diameter/test/diameter_stats_SUITE.erl | 92 |
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. |