Remove dependency on a server
Everything just uses application vars and procdict now.
This commit is contained in:
parent
cd1faf8631
commit
bb33398614
5 changed files with 67 additions and 199 deletions
|
@ -7,6 +7,6 @@
|
||||||
kernel,
|
kernel,
|
||||||
stdlib
|
stdlib
|
||||||
]},
|
]},
|
||||||
{mod, { qdate_app, []}},
|
{modules, [qdate, qdate_srv]},
|
||||||
{env, []}
|
{env, []}
|
||||||
]}.
|
]}.
|
||||||
|
|
|
@ -95,10 +95,10 @@
|
||||||
-define(else, true).
|
-define(else, true).
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
application:start(qdate).
|
application:load(qdate).
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
application:stop(qdate).
|
ok.
|
||||||
|
|
||||||
to_string(Format) ->
|
to_string(Format) ->
|
||||||
to_string(Format, os:timestamp()).
|
to_string(Format, os:timestamp()).
|
||||||
|
@ -616,6 +616,7 @@ try_registered_parsers(RawDate) ->
|
||||||
try_parsers(_RawDate,[]) ->
|
try_parsers(_RawDate,[]) ->
|
||||||
undefined;
|
undefined;
|
||||||
try_parsers(RawDate,[{ParserKey,Parser}|Parsers]) ->
|
try_parsers(RawDate,[{ParserKey,Parser}|Parsers]) ->
|
||||||
|
io:format("Trying Parser: ~p~n", [ParserKey]),
|
||||||
try Parser(RawDate) of
|
try Parser(RawDate) of
|
||||||
{{_,_,_},{_,_,_}} = DateTime ->
|
{{_,_,_},{_,_,_}} = DateTime ->
|
||||||
{DateTime,undefined};
|
{DateTime,undefined};
|
||||||
|
@ -686,7 +687,6 @@ tz_test_() ->
|
||||||
simple_test(SetupData),
|
simple_test(SetupData),
|
||||||
compare_test(SetupData),
|
compare_test(SetupData),
|
||||||
tz_tests(SetupData),
|
tz_tests(SetupData),
|
||||||
test_process_die(SetupData),
|
|
||||||
parser_format_test(SetupData),
|
parser_format_test(SetupData),
|
||||||
test_deterministic_parser(SetupData),
|
test_deterministic_parser(SetupData),
|
||||||
test_disambiguation(SetupData),
|
test_disambiguation(SetupData),
|
||||||
|
@ -820,38 +820,6 @@ parser_format_test(_) ->
|
||||||
?_assertEqual("2/8/2008 12:00am",to_string(longdate,"20080208"))
|
?_assertEqual("2/8/2008 12:00am",to_string(longdate,"20080208"))
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
test_process_die(_) ->
|
|
||||||
TZ = "MST",
|
|
||||||
Caller = self(),
|
|
||||||
Pid = spawn(fun() ->
|
|
||||||
set_timezone(TZ),
|
|
||||||
Caller ! tz_set,
|
|
||||||
receive tz_set_ack -> ok end,
|
|
||||||
Caller ! get_timezone()
|
|
||||||
end),
|
|
||||||
|
|
||||||
PidTZFromOtherProc = receive
|
|
||||||
tz_set ->
|
|
||||||
T = get_timezone(Pid),
|
|
||||||
Pid ! tz_set_ack,
|
|
||||||
T
|
|
||||||
after 1000 -> fail
|
|
||||||
end,
|
|
||||||
ReceivedTZ = receive
|
|
||||||
TZ -> TZ
|
|
||||||
after 2000 ->
|
|
||||||
fail
|
|
||||||
end,
|
|
||||||
|
|
||||||
[
|
|
||||||
%% Verify we can read the spawned process's TZ from another proc
|
|
||||||
?_assertEqual(TZ,PidTZFromOtherProc),
|
|
||||||
%% Verify the spawned process properly set the TZ
|
|
||||||
?_assertEqual(TZ,ReceivedTZ),
|
|
||||||
%% Verify the now-dead spawned process's TZ is cleared
|
|
||||||
?_assertEqual(undefined,get_timezone(Pid))
|
|
||||||
].
|
|
||||||
|
|
||||||
arith_tests(_) ->
|
arith_tests(_) ->
|
||||||
{inorder,[
|
{inorder,[
|
||||||
?_assertEqual({{2012,2,29},{23,59,59}}, to_date(add_seconds(-1, {{2012,3,1},{0,0,0}}))),
|
?_assertEqual({{2012,2,29},{23,59,59}}, to_date(add_seconds(-1, {{2012,3,1},{0,0,0}}))),
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
% vim: ts=4 sw=4 et
|
|
||||||
% Copyright (c) 2013 Jesse Gumm
|
|
||||||
% See LICENSE for licensing information.
|
|
||||||
|
|
||||||
-module(qdate_app).
|
|
||||||
|
|
||||||
-behaviour(application).
|
|
||||||
|
|
||||||
%% Application callbacks
|
|
||||||
-export([start/2, stop/1]).
|
|
||||||
|
|
||||||
%% ===================================================================
|
|
||||||
%% Application callbacks
|
|
||||||
%% ===================================================================
|
|
||||||
|
|
||||||
start(_StartType, _StartArgs) ->
|
|
||||||
qdate_sup:start_link().
|
|
||||||
|
|
||||||
stop(_State) ->
|
|
||||||
ok.
|
|
|
@ -1,22 +1,11 @@
|
||||||
% vim: ts=4 sw=4 et
|
% vim: ts=4 sw=4 et
|
||||||
% Copyright (c) 2013 Jesse Gumm
|
% Copyright (c) 2013-2015 Jesse Gumm
|
||||||
% See LICENSE for licensing information.
|
% See LICENSE for licensing information.
|
||||||
|
|
||||||
-module(qdate_srv).
|
-module(qdate_srv).
|
||||||
-behaviour(gen_server).
|
|
||||||
|
|
||||||
-define(SRV, ?MODULE).
|
-define(SRV, ?MODULE).
|
||||||
|
|
||||||
-export([
|
|
||||||
start_link/0,
|
|
||||||
init/1,
|
|
||||||
handle_call/3,
|
|
||||||
handle_cast/2,
|
|
||||||
handle_info/2,
|
|
||||||
code_change/3,
|
|
||||||
terminate/2
|
|
||||||
]).
|
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
set_timezone/1,
|
set_timezone/1,
|
||||||
set_timezone/2,
|
set_timezone/2,
|
||||||
|
@ -37,135 +26,98 @@
|
||||||
get_formats/0
|
get_formats/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
%% Simple wrappers for unique keys
|
||||||
|
-define(BASETAG, qdate_var).
|
||||||
|
-define(KEY(Name), {?BASETAG, Name}).
|
||||||
|
|
||||||
|
-define(TZTAG, qdate_tz).
|
||||||
|
-define(TZKEY(Name), {?TZTAG, Name}).
|
||||||
|
-define(PARSERTAG, qdate_parser).
|
||||||
|
-define(PARSERKEY(Name), {?PARSERTAG, Name}).
|
||||||
|
-define(FORMATTAG, qdate_format).
|
||||||
|
-define(FORMATKEY(Name), {?FORMATTAG, Name}).
|
||||||
|
|
||||||
%% PUBLIC API FUNCTIONS
|
%% PUBLIC API FUNCTIONS
|
||||||
|
|
||||||
start_link() ->
|
|
||||||
gen_server:start_link({local, ?SRV}, ?MODULE, [], []).
|
|
||||||
|
|
||||||
set_timezone(TZ) ->
|
set_timezone(TZ) ->
|
||||||
set_timezone(self(),TZ).
|
put_pd(?TZTAG, TZ).
|
||||||
|
|
||||||
set_timezone(Key,TZ) ->
|
set_timezone(Key, TZ) ->
|
||||||
ok = gen_server:call(?SRV,{set_timezone,Key,TZ}).
|
set_env(?TZKEY(Key), TZ).
|
||||||
|
|
||||||
get_timezone() ->
|
get_timezone() ->
|
||||||
get_timezone(self()).
|
get_pd(?TZTAG).
|
||||||
|
|
||||||
get_timezone(Key) ->
|
get_timezone(Key) ->
|
||||||
gen_server:call(?SRV,{get_timezone,Key}).
|
get_env(?TZKEY(Key)).
|
||||||
|
|
||||||
clear_timezone() ->
|
clear_timezone() ->
|
||||||
clear_timezone(self()).
|
unset_pd(?TZTAG).
|
||||||
|
|
||||||
clear_timezone(Key) ->
|
clear_timezone(Key) ->
|
||||||
ok = gen_server:call(?SRV, {clear_timezone, Key}).
|
unset_env(?TZKEY(Key)).
|
||||||
|
|
||||||
register_parser(Parser) when is_function(Parser,1) ->
|
register_parser(Parser) when is_function(Parser,1) ->
|
||||||
register_parser(erlang:make_ref(),Parser).
|
register_parser(erlang:make_ref(),Parser).
|
||||||
|
|
||||||
register_parser(Key,Parser) when is_function(Parser,1) ->
|
register_parser(Key,Parser) when is_function(Parser,1) ->
|
||||||
Key = gen_server:call(?SRV,{register_parser,Key,Parser}).
|
set_env(?PARSERKEY(Key), Parser).
|
||||||
|
|
||||||
deregister_parser(Key) ->
|
deregister_parser(Key) ->
|
||||||
ok = gen_server:call(?SRV,{deregister_parser,Key}).
|
unset_env(?PARSERKEY(Key)).
|
||||||
|
|
||||||
deregister_parsers() ->
|
deregister_parsers() ->
|
||||||
ok = gen_server:call(?SRV,{deregister_parsers}).
|
[deregister_parser(Key) || {Key, _} <- get_parsers()].
|
||||||
|
|
||||||
get_parsers() ->
|
get_parsers() ->
|
||||||
gen_server:call(?SRV,get_parsers).
|
get_all_env(?PARSERTAG).
|
||||||
|
|
||||||
register_format(Key,Format) ->
|
register_format(Key, Format) ->
|
||||||
ok = gen_server:call(?SRV,{register_format,Key,Format}).
|
set_env(?FORMATKEY(Key), Format).
|
||||||
|
|
||||||
get_format(Key) ->
|
get_format(Key) ->
|
||||||
gen_server:call(?SRV,{get_format,Key}).
|
get_env(?FORMATKEY(Key)).
|
||||||
|
|
||||||
deregister_format(Key) ->
|
deregister_format(Key) ->
|
||||||
ok = gen_server:call(?SRV,{deregister_format,Key}).
|
unset_env(?FORMATKEY(Key)).
|
||||||
|
|
||||||
get_formats() ->
|
get_formats() ->
|
||||||
gen_server:call(?SRV, get_formats).
|
get_all_env(?FORMATTAG).
|
||||||
|
|
||||||
%% SERVER FUNCTIONS
|
|
||||||
|
|
||||||
-record(state, {tz, parsers, formats}).
|
|
||||||
|
|
||||||
init(_) ->
|
|
||||||
State = #state{tz=dict:new(),parsers=dict:new(),formats=dict:new()},
|
|
||||||
{ok, State}.
|
|
||||||
|
|
||||||
handle_cast(_,State) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
handle_info({'DOWN', MonitorRef, process, Pid, _Reason}, State) ->
|
|
||||||
erlang:demonitor(MonitorRef),
|
|
||||||
NewTZ = dict:erase(Pid, State#state.tz),
|
|
||||||
NewParsers = dict:erase(Pid, State#state.parsers),
|
|
||||||
NewFormats = dict:erase(Pid, State#state.formats),
|
|
||||||
NewState = State#state{tz=NewTZ, parsers=NewParsers, formats=NewFormats},
|
|
||||||
{noreply, NewState };
|
|
||||||
handle_info(_, State) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
handle_call({set_timezone,Key,TZ}, _From, State) ->
|
|
||||||
monitor_if_pid(Key),
|
|
||||||
NewTZ = dict:store(Key, TZ, State#state.tz),
|
|
||||||
NewState = State#state{tz=NewTZ},
|
|
||||||
{reply, ok, NewState};
|
|
||||||
handle_call({clear_timezone,Key},_From, State) ->
|
|
||||||
NewTZ = dict:erase(Key, State#state.tz),
|
|
||||||
NewState = State#state{tz=NewTZ},
|
|
||||||
{reply, ok, NewState};
|
|
||||||
handle_call({get_timezone,Key},_From, State) ->
|
|
||||||
Reply = case dict:find(Key, State#state.tz) of
|
|
||||||
error -> undefined;
|
|
||||||
{ok,TZ} -> TZ
|
|
||||||
end,
|
|
||||||
{reply, Reply, State};
|
|
||||||
|
|
||||||
handle_call({register_parser,Key,Parser},_From,State) ->
|
|
||||||
NewParsers = dict:store(Key, Parser, State#state.parsers),
|
|
||||||
NewState = State#state{parsers=NewParsers},
|
|
||||||
{reply, Key, NewState};
|
|
||||||
handle_call(get_parsers,_From,State) ->
|
|
||||||
Reply = dict:to_list(State#state.parsers),
|
|
||||||
{reply, Reply, State};
|
|
||||||
handle_call({deregister_parser,Key},_From,State) ->
|
|
||||||
NewParsers = dict:erase(Key, State#state.parsers),
|
|
||||||
NewState = State#state{parsers=NewParsers},
|
|
||||||
{reply, ok, NewState};
|
|
||||||
handle_call({deregister_parsers},_From,State) ->
|
|
||||||
NewState = State#state{parsers=dict:new()},
|
|
||||||
{reply, ok, NewState};
|
|
||||||
|
|
||||||
handle_call({register_format,Key,Format},_From,State) ->
|
|
||||||
NewFormats = dict:store(Key, Format, State#state.formats),
|
|
||||||
NewState = State#state{formats=NewFormats},
|
|
||||||
{reply, ok, NewState};
|
|
||||||
handle_call({get_format,Key},_From,State) ->
|
|
||||||
Reply = case dict:find(Key, State#state.formats) of
|
|
||||||
error -> undefined;
|
|
||||||
{ok, Format} -> Format
|
|
||||||
end,
|
|
||||||
{reply, Reply,State};
|
|
||||||
handle_call(get_formats,_From,State) ->
|
|
||||||
Reply = dict:to_list(State#state.formats),
|
|
||||||
{reply, Reply, State};
|
|
||||||
handle_call({deregister_format,Key},_From,State) ->
|
|
||||||
NewFormats = dict:erase(Key, State#state.formats),
|
|
||||||
NewState = State#state{formats=NewFormats},
|
|
||||||
{reply, ok, NewState}.
|
|
||||||
|
|
||||||
terminate(_Reason, _State) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
code_change(_OldVersion, State, _Extra) ->
|
|
||||||
{ok, State}.
|
|
||||||
|
|
||||||
%% PRIVATE TOOLS
|
%% PRIVATE TOOLS
|
||||||
|
|
||||||
monitor_if_pid(Key) when is_pid(Key) ->
|
%% App Vars
|
||||||
erlang:monitor(process,Key);
|
|
||||||
monitor_if_pid(_) ->
|
set_env(Key, Val) ->
|
||||||
do_nothing.
|
application:set_env(qdate, ?KEY(Key), Val).
|
||||||
|
|
||||||
|
get_env(Key) ->
|
||||||
|
get_env(Key, undefined).
|
||||||
|
|
||||||
|
get_env(Key, Default) ->
|
||||||
|
%% Soon, this can just be replaced with application:get_env/3
|
||||||
|
%% which was introduced in R16B.
|
||||||
|
case application:get_env(qdate, ?KEY(Key)) of
|
||||||
|
undefined -> Default;
|
||||||
|
{ok, Val} -> Val
|
||||||
|
end.
|
||||||
|
|
||||||
|
unset_env(Key) ->
|
||||||
|
application:unset_env(qdate, ?KEY(Key)).
|
||||||
|
|
||||||
|
get_all_env(FilterTag) ->
|
||||||
|
All = application:get_all_env(qdate),
|
||||||
|
%% Maybe this is a little nasty.
|
||||||
|
[{Key, V} || {{?BASETAG, {Tag, Key}}, V} <- All, Tag==FilterTag].
|
||||||
|
|
||||||
|
%% ProcDic Vars
|
||||||
|
|
||||||
|
get_pd(Key) ->
|
||||||
|
erlang:get(?KEY(Key)).
|
||||||
|
|
||||||
|
put_pd(Key, Val) ->
|
||||||
|
erlang:put(?KEY(Key), Val),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
unset_pd(Key) ->
|
||||||
|
put_pd(Key, undefined).
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
% vim: ts=4 sw=4 et
|
|
||||||
% Copyright (c) 2013 Jesse Gumm
|
|
||||||
% See LICENSE for licensing information.
|
|
||||||
|
|
||||||
-module(qdate_sup).
|
|
||||||
|
|
||||||
-behaviour(supervisor).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([start_link/0]).
|
|
||||||
|
|
||||||
%% Supervisor callbacks
|
|
||||||
-export([init/1]).
|
|
||||||
|
|
||||||
%% Helper macro for declaring children of supervisor
|
|
||||||
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
|
|
||||||
|
|
||||||
%% ===================================================================
|
|
||||||
%% API functions
|
|
||||||
%% ===================================================================
|
|
||||||
|
|
||||||
start_link() ->
|
|
||||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
||||||
|
|
||||||
%% ===================================================================
|
|
||||||
%% Supervisor callbacks
|
|
||||||
%% ===================================================================
|
|
||||||
|
|
||||||
init([]) ->
|
|
||||||
Server = ?CHILD(qdate_srv, worker),
|
|
||||||
{ok, { {one_for_one, 5, 10}, [Server]} }.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue