Implement reset counters
diff --git a/src/glc.erl b/src/glc.erl
index ff0a6e6..95e3ebf 100644
--- a/src/glc.erl
+++ b/src/glc.erl
@@ -64,7 +64,9 @@
-export([
compile/2,
handle/2,
- delete/1
+ delete/1,
+ reset_counters/1,
+ reset_counters/2
]).
-export([
@@ -184,7 +186,7 @@
%%
%% This releases all resources allocated by a compiled query. The query name
%% is expected to be associated with an existing query module. Calling this
-%% function will result in a runtime error.
+%% function will shutdown all relevant processes and purge/delete the module.
-spec delete(atom()) -> ok.
delete(Module) ->
Params = params_name(Module),
@@ -204,6 +206,19 @@
code:delete(Module),
ok.
+%% @doc Reset all counters
+%%
+%% This resets all the counters associated with a module
+-spec reset_counters(atom()) -> ok.
+reset_counters(Module) ->
+ Module:reset_counters(all).
+
+%% @doc Reset a specific counter
+%%
+%% This resets a specific counter associated with a module
+-spec reset_counters(atom(), atom()) -> ok.
+reset_counters(Module, Counter) ->
+ Module:reset_counters(Counter).
%% @private Map a query to a module data term.
-spec module_data(atom(), term()) -> {ok, #module{}}.
@@ -453,6 +468,34 @@
?assertEqual(undefined, whereis(manage_params_name(Mod))),
?assertEqual(undefined, whereis(manage_counts_name(Mod)))
end
+ },
+ {"reset counters test",
+ fun() ->
+ {compiled, Mod} = setup_query(testmod14,
+ glc:any([glc:eq(a, 1), glc:eq(b, 2)])),
+ glc:handle(Mod, gre:make([{'a', 2}], [list])),
+ glc:handle(Mod, gre:make([{'b', 1}], [list])),
+ ?assertEqual(2, Mod:info(input)),
+ ?assertEqual(2, Mod:info(filter)),
+ glc:handle(Mod, gre:make([{'a', 1}], [list])),
+ glc:handle(Mod, gre:make([{'b', 2}], [list])),
+ ?assertEqual(4, Mod:info(input)),
+ ?assertEqual(2, Mod:info(filter)),
+ ?assertEqual(2, Mod:info(output)),
+
+ glc:reset_counters(Mod, input),
+ ?assertEqual(0, Mod:info(input)),
+ ?assertEqual(2, Mod:info(filter)),
+ ?assertEqual(2, Mod:info(output)),
+ glc:reset_counters(Mod, filter),
+ ?assertEqual(0, Mod:info(input)),
+ ?assertEqual(0, Mod:info(filter)),
+ ?assertEqual(2, Mod:info(output)),
+ glc:reset_counters(Mod),
+ ?assertEqual(0, Mod:info(input)),
+ ?assertEqual(0, Mod:info(filter)),
+ ?assertEqual(0, Mod:info(output))
+ end
}
]
}.
diff --git a/src/glc_code.erl b/src/glc_code.erl
index c966e59..e3d69fa 100644
--- a/src/glc_code.erl
+++ b/src/glc_code.erl
@@ -60,6 +60,10 @@
?erl:arity_qualifier(
?erl:atom(info),
?erl:integer(1)),
+ %% reset_counters/1
+ ?erl:arity_qualifier(
+ ?erl:atom(reset_counters),
+ ?erl:integer(1)),
%% table/1
?erl:arity_qualifier(
?erl:atom(table),
@@ -76,7 +80,14 @@
[?erl:clause(
[?erl:underscore()], none,
[abstract_apply(erlang, error, [?erl:atom(badarg)])])]),
- %% table(Name) -> ets:tid().
+ %% reset_counters(Name) -> boolean().
+ ?erl:function(
+ ?erl:atom(reset_counters),
+ abstract_reset() ++
+ [?erl:clause(
+ [?erl:underscore()], none,
+ [abstract_apply(erlang, error, [?erl:atom(badarg)])])]),
+ %% table(Name) -> atom().
?erl:function(
?erl:atom(table),
abstract_tables(Tables) ++
@@ -120,6 +131,17 @@
{output, abstract_getcount(output)}
]].
+
+abstract_reset() ->
+ [?erl:clause([?erl:abstract(K)], none, V)
+ || {K, V} <- [
+ {all, abstract_resetcount([input, filter, output])},
+ {input, abstract_resetcount(input)},
+ {filter, abstract_resetcount(filter)},
+ {output, abstract_resetcount(output)}
+ ]].
+
+
%% @private Return the original query as an expression.
abstract_query({with, _, _}) ->
[?erl:abstract([])];
@@ -330,6 +352,14 @@
[abstract_apply(table, [?erl:atom(counters)]),
?erl:abstract(Counter)])].
+%% @private Return an expression to reset a counter.
+-spec abstract_resetcount(atom()) -> [syntaxTree()].
+abstract_resetcount(Counter) ->
+ [abstract_apply(gr_counter, reset_counters,
+ [abstract_apply(table, [?erl:atom(counters)]),
+ ?erl:abstract(Counter)])].
+
+
%% abstract code util functions
diff --git a/src/goldrush.app.src b/src/goldrush.app.src
index 4f482b4..06ac27f 100644
--- a/src/goldrush.app.src
+++ b/src/goldrush.app.src
@@ -1,6 +1,6 @@
{application, goldrush, [
{description, "Erlang event stream processor"},
- {vsn, "0.1.3"},
+ {vsn, "0.1.4"},
{registered, []},
{applications, [kernel, stdlib, syntax_tools, compiler]},
{mod, {gr_app, []}},
diff --git a/src/gr_counter.erl b/src/gr_counter.erl
index d2276f1..82d99e8 100644
--- a/src/gr_counter.erl
+++ b/src/gr_counter.erl
@@ -19,7 +19,7 @@
%% API
-export([start_link/1,
list/1, lookup_element/2,
- update/3]).
+ update/3, reset_counters/2]).
%% gen_server callbacks
-export([init/1,
@@ -43,6 +43,9 @@
update(Server, Counter, Value) ->
gen_server:cast(Server, {update, Counter, Value}).
+reset_counters(Server, Counter) ->
+ gen_server:call(Server, {reset_counters, Counter}).
+
%%--------------------------------------------------------------------
%% @doc
%% Starts the server
@@ -91,6 +94,15 @@
handle_call({lookup_element, Counter}, _From, State) ->
TableId = State#state.table_id,
{reply, ets:lookup_element(TableId, Counter, 2), State};
+handle_call({reset_counters, Counter}, _From, State) ->
+ TableId = State#state.table_id,
+ Reset = case Counter of
+ _ when is_list(Counter) ->
+ [{Item, 0} || Item <- Counter];
+ _ when is_atom(Counter) ->
+ [{Counter, 0}]
+ end,
+ {reply, ets:insert(TableId, Reset), State};
handle_call(_Request, _From, State) ->
Reply = {error, unhandled_message},
{reply, Reply, State}.