aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/src/engine/megaco_stats.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/src/engine/megaco_stats.erl')
-rw-r--r--lib/megaco/src/engine/megaco_stats.erl207
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/megaco/src/engine/megaco_stats.erl b/lib/megaco/src/engine/megaco_stats.erl
new file mode 100644
index 0000000000..af180fb9d6
--- /dev/null
+++ b/lib/megaco/src/engine/megaco_stats.erl
@@ -0,0 +1,207 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2009. 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
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%-----------------------------------------------------------------
+%% Purpose: Functions for handling statistic counters
+%%-----------------------------------------------------------------
+-module(megaco_stats).
+
+
+%%-----------------------------------------------------------------
+%% Application internal exports
+%%-----------------------------------------------------------------
+
+-export([init/1, init/2]).
+
+-export([inc/2, inc/3, inc/4]).
+
+-export([get_stats/1, get_stats/2, get_stats/3,
+ reset_stats/1, reset_stats/2]).
+
+%% -include_lib("megaco/include/megaco.hrl").
+
+
+%%-----------------------------------------------------------------
+%% Func: init/1, init/2
+%% Description: Initiate the statistics. Creates the stats table
+%% and the global counters.
+%%-----------------------------------------------------------------
+init(Name) ->
+ init(Name, []).
+
+init(Name, GlobalCounters) ->
+ ets:new(Name, [public, named_table, {keypos, 1}]),
+ ets:insert(Name, {global_counters, GlobalCounters}),
+ create_global_snmp_counters(Name, GlobalCounters).
+
+
+create_global_snmp_counters(_Name, []) ->
+ ok;
+create_global_snmp_counters(Name, [Counter|Counters]) ->
+ ets:insert(Name, {Counter, 0}),
+ create_global_snmp_counters(Name, Counters).
+
+
+%%-----------------------------------------------------------------
+%% Func: inc/2, inc/3, inc/4
+%% Description: Increment counter value. Default increment is one
+%% (1).
+%%-----------------------------------------------------------------
+inc(Tab, GlobalCnt) when is_atom(GlobalCnt) ->
+ inc(Tab, GlobalCnt, 1).
+
+inc(Tab, GlobalCnt, Incr)
+ when is_atom(GlobalCnt) andalso (is_integer(Incr) andalso (Incr > 0)) ->
+ do_inc(Tab, GlobalCnt, Incr);
+inc(Tab, Handle, Cnt)
+ when is_atom(Cnt) ->
+ inc(Tab, Handle, Cnt, 1).
+
+inc(Tab, Handle, Cnt, Incr)
+ when is_atom(Cnt) andalso (is_integer(Incr) andalso (Incr > 0)) ->
+ Key = {Handle, Cnt},
+ do_inc(Tab, Key, Incr).
+
+do_inc(Tab, Key, Incr) ->
+ case (catch ets:update_counter(Tab, Key, Incr)) of
+ {'EXIT', {badarg, _Reason}} ->
+ ets:insert(Tab, {Key, Incr}),
+ Incr;
+ Val ->
+ Val
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: get_stats/1, get_stats/2, get_stats/3
+%% Description: Get statistics
+%%-----------------------------------------------------------------
+get_stats(Ets) ->
+ Handles = get_handles_and_global_counters(Ets),
+ (catch do_get_stats(Ets, Handles, [])).
+
+do_get_stats(_Ets, [], Acc) ->
+ {ok, lists:reverse(Acc)};
+do_get_stats(Ets, [Handle|Handles], Acc) ->
+ case get_stats(Ets, Handle) of
+ {ok, Stats} ->
+ do_get_stats(Ets, Handles, [{Handle, Stats}|Acc]);
+ {error, Reason} ->
+ throw({error, Reason})
+ end.
+
+get_stats(Ets, GlobalCounter) when is_atom(GlobalCounter) ->
+ case (catch ets:lookup(Ets, GlobalCounter)) of
+ [{GlobalCounter, Val}] ->
+ {ok, Val};
+ [] ->
+ {error, {no_such_counter, GlobalCounter}}
+ end;
+
+get_stats(Ets, Handle) ->
+ case (catch ets:match(Ets, {{Handle, '$1'},'$2'})) of
+ CounterVals when is_list(CounterVals) ->
+ {ok, [{Counter, Val} || [Counter, Val] <- CounterVals]};
+ Other ->
+ {error, {unexpected_result, Other}}
+ end.
+
+
+get_stats(Ets, Handle, Counter) when is_atom(Counter) ->
+ Key = {Handle, Counter},
+ case (catch ets:lookup(Ets, Key)) of
+ [{Key, Val}] ->
+ {ok, Val};
+ _ ->
+ {error, {undefined_counter, Counter}}
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Funcs: reset_stats/1, reset_stats/2
+%% Description: Reset statistics
+%%-----------------------------------------------------------------
+reset_stats(Ets) ->
+ Handles = get_handles_and_global_counters(Ets),
+ (catch do_reset_stats(Ets, Handles, [])).
+
+do_reset_stats(_Ets, [], Acc) ->
+ {ok, lists:reverse(Acc)};
+do_reset_stats(Ets, [Handle|Handles], Acc) ->
+ case reset_stats(Ets, Handle) of
+ {ok, OldStats} ->
+ do_reset_stats(Ets, Handles, [{Handle, OldStats}|Acc]);
+ {error, Reason} ->
+ throw({error, Reason})
+ end.
+
+reset_stats(Ets, GlobalCounter) when is_atom(GlobalCounter) ->
+ %% First get the current value of the counter
+ case (catch ets:lookup(Ets, GlobalCounter)) of
+ [{GlobalCounter, Val}] ->
+ ets:insert(Ets, {GlobalCounter, 0}),
+ {ok, Val};
+ [] -> %% Oooups
+ {error, {no_such_counter, GlobalCounter}}
+ end;
+
+reset_stats(Ets, Handle) ->
+ case (catch ets:match(Ets, {{Handle, '$1'},'$2'})) of
+ CounterVals when is_list(CounterVals) ->
+ CVs = [{Counter, Val} || [Counter, Val] <- CounterVals],
+ reset_stats(Ets, Handle, CVs),
+ {ok, CVs};
+ Other ->
+ {error, {unexpected_result, Other}}
+ end.
+
+reset_stats(_Ets, _Handle, []) ->
+ ok;
+reset_stats(Ets, Handle, [{Counter, _}|CVs]) ->
+ ets:insert(Ets, {{Handle, Counter}, 0}),
+ reset_stats(Ets, Handle, CVs).
+
+
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+get_handles_and_global_counters(Ets) ->
+ GlobalCounters =
+ case ets:lookup(Ets, global_counters) of
+ [{global_counters, GC}] ->
+ GC;
+ [] ->
+ []
+ end,
+ L1 = ets:match(Ets, {{'$1', '_'}, '_'}),
+ GlobalCounters ++
+ lists:sort([Handle || [Handle] <- remove_duplicates(L1, [])]).
+
+remove_duplicates([], L) ->
+ L;
+remove_duplicates([H|T], L) ->
+ case lists:member(H,T) of
+ true ->
+ remove_duplicates(T, L);
+ false ->
+ remove_duplicates(T, [H|L])
+ end.
+