From bbfef69d2e972279a58b6de57abaf57d2b8ffc1a Mon Sep 17 00:00:00 2001 From: Jesse Gumm Date: Wed, 30 Jun 2021 14:44:45 -0500 Subject: [PATCH] Convert qdate_srv to be an ETS server (dialyzer doesn't like using tuples as keys for application:set_env) --- src/qdate.app.src | 5 +-- src/qdate.erl | 4 +-- src/qdate_app.erl | 15 +++++++++ src/qdate_srv.erl | 77 ++++++++++++++++++++++++++++++++++++++--------- src/qdate_sup.erl | 32 ++++++++++++++++++++ 5 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 src/qdate_app.erl create mode 100644 src/qdate_sup.erl diff --git a/src/qdate.app.src b/src/qdate.app.src index c2840f6..7b85ef4 100644 --- a/src/qdate.app.src +++ b/src/qdate.app.src @@ -1,7 +1,7 @@ {application, qdate, [ {description, "Simple Date and Timezone handling for Erlang"}, - {vsn, "0.6.0"}, + {vsn, "0.7.0"}, {registered, []}, {applications, [ kernel, @@ -9,9 +9,10 @@ erlware_commons, stdlib ]}, - {modules, [qdate, qdate_srv]}, + {modules, [qdate, qdate_srv, qdate_sup, qdate_app]}, {env, []}, {maintainers, ["Jesse Gumm"]}, {licenses, ["MIT"]}, + {mod, {qdate_app, []}}, {links, [{"Github", "https://github.com/choptastic/qdate"}]} ]}. diff --git a/src/qdate.erl b/src/qdate.erl index c929e89..eeacb4e 100644 --- a/src/qdate.erl +++ b/src/qdate.erl @@ -156,7 +156,7 @@ -define(else, true). start() -> - application:load(qdate). + application:ensure_all_started(qdate). stop() -> ok. @@ -1457,7 +1457,7 @@ preserve_ms_false_tests(_) -> ]}. start_test() -> - application:start(qdate), + qdate:start(), set_timezone(?SELF_TZ), set_timezone(?SITE_KEY,?SITE_TZ), set_timezone(?USER_KEY,?USER_TZ), diff --git a/src/qdate_app.erl b/src/qdate_app.erl new file mode 100644 index 0000000..36a8289 --- /dev/null +++ b/src/qdate_app.erl @@ -0,0 +1,15 @@ +-module(qdate_app). + +-behaviour(application). + +%% Application callbacks +-export([start/2, stop/1]). + +start(_StartType, _StartArgs) -> + qdate_sup:start_link(). + + +stop(_State) -> + ok. + + diff --git a/src/qdate_srv.erl b/src/qdate_srv.erl index 6aeecc0..d09b782 100644 --- a/src/qdate_srv.erl +++ b/src/qdate_srv.erl @@ -1,12 +1,9 @@ % vim: ts=4 sw=4 et -% Copyright (c) 2013-2015 Jesse Gumm +% Copyright (c) 2013-2021 Jesse Gumm % See LICENSE for licensing information. -% -% NOTE: You'll probably notice that this isn't *actually* a server. It *used* -% to be a server, but is now instead just where we interact with the qdate -% application environment. Anyway, sorry for the confusion. -module(qdate_srv). +-behaviour(gen_server). -export([ set_timezone/1, @@ -28,6 +25,19 @@ get_formats/0 ]). + +%% API +-export([start_link/0]). + +%% gen_server callbacks +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). + + %% Simple wrappers for unique keys -define(BASETAG, qdate_var). -define(KEY(Name), {?BASETAG, Name}). @@ -39,6 +49,42 @@ -define(FORMATTAG, qdate_format). -define(FORMATKEY(Name), {?FORMATTAG, Name}). +-define(SERVER, ?MODULE). +-define(TABLE, ?MODULE). + +-record(state, {}). + +start_link() -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + +init([]) -> + error_logger:info_msg("Creating qdate ETS Table: ~p",[?TABLE]), + ?TABLE = ets:new(?TABLE, [public, {read_concurrency, true}, named_table]), + {ok, #state{}}. + +handle_call({set, Key, Val}, _From, State) -> + ets:insert(?TABLE, {Key, Val}), + {reply, ok, State}; +handle_call({unset, Key}, _From, State) -> + ets:delete(?TABLE, Key), + {reply, ok, State}; +handle_call(_, _From, State) -> + {reply, invalid_request, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + + %% PUBLIC API FUNCTIONS set_timezone(TZ) -> @@ -91,25 +137,22 @@ get_formats() -> %% App Vars set_env(Key, Val) -> - application:set_env(qdate, ?KEY(Key), Val). + gen_server:call(?SERVER, {set, ?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 + case ets:lookup(?TABLE, ?KEY(Key)) of + [{__Key, Val}] -> Val; + [] -> Default end. unset_env(Key) -> - application:unset_env(qdate, ?KEY(Key)). + gen_server:call(?SERVER, {unset, ?KEY(Key)}). get_all_env(FilterTag) -> - All = application:get_all_env(qdate), - %% Maybe this is a little nasty. + All = ets:tab2list(?TABLE), [{Key, V} || {{?BASETAG, {Tag, Key}}, V} <- All, Tag==FilterTag]. %% ProcDic Vars @@ -123,3 +166,9 @@ put_pd(Key, Val) -> unset_pd(Key) -> put_pd(Key, undefined). + + + + + + diff --git a/src/qdate_sup.erl b/src/qdate_sup.erl new file mode 100644 index 0000000..492dd8e --- /dev/null +++ b/src/qdate_sup.erl @@ -0,0 +1,32 @@ +-module(qdate_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +init([]) -> + + SupFlags = #{}, + + ChildSpec = #{ + id=>qdate_srv, + start=>{qdate_srv, start_link, []} + }, + + {ok, {SupFlags, [ChildSpec]}}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== + + +