Current section

Files

Jump to
fswitch src event_log.erl
Raw

src/event_log.erl

-module(event_log).
-behaviour(gen_server).
-export([start_link/0, add/2, search/2, wait/3, wait/4, wait_now/3]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-record(state, {
wait,
log = []
}).
start_link() -> gen_server:start_link(?MODULE, [], []).
add(Id, Msg) -> gen_server:call(Id, {add, Msg}).
wait(Id, Match, Caller) -> wait(Id, Match, Caller, 2).
wait(Id, Match, Caller, Depth) -> gen_server:call(Id, {wait, Match, Caller, Depth}).
wait_now(Id, Match, Caller) -> gen_server:call(Id, {wait_now, Match, Caller}).
search(Id, Match) -> gen_server:call(Id, {search, Match}).
init([]) -> {ok, #state{
log = []
}}.
handle_call({add, Msg}, _, S=#state{ wait = undefined }) ->
{reply, ok, add_msg(Msg, S)};
handle_call({add, Msg}, _, S=#state{ wait = {Match, Caller} }) ->
case util_core:match_maps(Match, Msg) of
true -> {reply, {match, Caller, {erlang:timestamp(), Msg}}, (add_msg(Msg, S))#state{ wait = undefined }};
false -> {reply, no_match, add_msg(Msg, S)}
end;
handle_call({search, Match}, _, S=#state{log=Log}) ->
{reply, lookback(Match, Log), S};
handle_call({wait, Match, Caller, Depth}, _, S=#state{ log = Log }) ->
case lookback(Depth, Match, Log) of
{match, _, _}=Msg -> {reply, Msg, S};
_ -> {reply, no_match, S#state{ wait = {Match,Caller} } }
end;
handle_call({wait_now, Match, Caller}, _, S=#state{}) ->
{reply, no_match, S#state{ wait = {Match,Caller} } };
handle_call(_Request, _From, S=#state{}) -> {reply, {error, not_handled}, S}.
handle_cast(_Msg, S=#state{}) -> {noreply, S}.
handle_info(_Info, S=#state{}) -> {noreply, S}.
terminate(_Reason, _S) -> ok.
code_change(_OldVsn, S=#state{}, _Extra) -> {ok, S}.
lookback(0, _, _) -> no_match;
lookback(_, _, []) -> no_match;
lookback(Depth, Match, [{Ts,Msg} | Log]) ->
case util_core:match_maps(Match, Msg) of
true -> {match, Ts, Msg};
false -> lookback(Depth-1, Match, Log)
end.
lookback(_, []) -> no_match;
lookback(Match, [{Ts,Msg} | Log]) ->
case util_core:match_maps(Match, Msg) of
true -> {match, Ts, Msg};
false -> lookback(Match, Log)
end.
add_msg(Msg, S=#state{log=Log}) -> S#state{ log = [ {erlang:timestamp(), Msg} | Log ] }.