Current section

Files

Jump to
econfig src econfig_watcher.erl
Raw

src/econfig_watcher.erl

%%% -*- erlang -*-
%%%
%%% This file is part of econfig released under the Apache 2 license.
%%% See the NOTICE for more information.
%% @hidden
-module(econfig_watcher).
-behaviour(gen_server).
-export([start_link/2, start_link/3,
pause/1, restart/1]).
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3]).
-record(watcher, {tc,
files = [],
scan_delay,
conf,
paths}).
-record(file, {path, last_mod}).
start_link(ConfName, Paths) ->
start_link(ConfName, Paths, scan_delay()).
start_link(ConfName, Paths, Delay) ->
gen_server:start_link(?MODULE, [ConfName, Paths, Delay] , []).
pause(Pid) ->
gen_server:call(Pid, pause).
restart(Pid) ->
gen_server:call(Pid, restart).
init([ConfName, Paths, Delay]) ->
Files = econfig_util:find_files(Paths, fun file_info/1),
Tc = erlang:start_timer(Delay, self(), scan),
InitState = #watcher{tc=Tc,
scan_delay=Delay,
files=Files,
conf=ConfName,
paths=Paths},
{ok, InitState}.
handle_call(pause, _From, State=#watcher{tc=Tc}) when Tc /= nil ->
erlang:cancel_timer(Tc),
{reply, ok, State#watcher{tc=nil}};
handle_call(restart, _From, State=#watcher{tc=nil, scan_delay=Delay,
paths=Paths}) ->
Files = econfig_util:find_files(Paths, fun file_info/1),
Tc = erlang:start_timer(Delay, self(), scan),
{reply, ok, State#watcher{tc=Tc, files=Files}};
handle_call(_Req, _From, State) ->
{reply, ok, State}.
handle_cast(_Event, State) ->
{noreply, State}.
handle_info({timeout, Tc, scan}, State=#watcher{tc=Tc, scan_delay=Delay,
files=OldFiles, conf=Conf,
paths=Paths}) ->
NewFiles = econfig_util:find_files(Paths, fun file_info/1),
case OldFiles -- NewFiles of
[] ->
ok;
_ ->
IniFiles = lists:map(fun(#file{path=P}) -> P end, NewFiles),
econfig_server:reload(Conf, IniFiles)
end,
{noreply, State#watcher{tc=erlang:start_timer(Delay, self(), scan),
files=NewFiles}};
handle_info(_Info, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
terminate(_Reason, _State) ->
ok.
%% --
%% internal functions
%%
scan_delay() ->
case application:get_env(econfig, scan_delay) of
undefined -> 5000;
{ok, Delay} -> Delay
end.
file_info(Path) ->
LastMod = filelib:last_modified(Path),
#file{path=Path, last_mod=LastMod}.