/config.erl
http://mailerl.googlecode.com/ · Erlang · 293 lines · 185 code · 44 blank · 64 comment · 0 complexity · bbbc24607f053e0609333e940549aafc MD5 · raw file
- %%%-------------------------------------------------------------------
- %%% File : config.erl
- %%% Author : Fyodor Ustinov <>
- %%% Description : CONFIGURATION STUB
- %%%
- %%% Created : 10 Sep 2009 by Fyodor Ustinov <>
- %%%-------------------------------------------------------------------
- -module(config).
- -define(SERVER, config).
- -behaviour(gen_server).
- %% API
- -export([start_link/0, get/1, get/2, get/3, get/4, subst/3, subst/4,
- set/2, set_node/2, set/3, save/0,
- drop/1, drop/2, drop_node/1]).
- %% gen_server callbacks
- -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
- -record(s, {
- modules = dict:new(),
- node = dict:new(),
- global = dict:new()
- }).
- %%====================================================================
- %% API
- %%====================================================================
- %%--------------------------------------------------------------------
- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
- %% Description: Starts the server
- %%--------------------------------------------------------------------
- start_link() ->
- gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
- %%====================================================================
- %% gen_server callbacks
- %%====================================================================
- %%--------------------------------------------------------------------
- %% Function: init(Args) -> {ok, State} |
- %% {ok, State, Timeout} |
- %% ignore |
- %% {stop, Reason}
- %% Description: Initiates the server
- %%--------------------------------------------------------------------
- init([]) ->
- process_flag(trap_exit, true),
- D = try
- {ok, Dict} = file:read_file("config"),
- erlang:binary_to_term(Dict)
- catch
- _:_ ->
- #s{}
- end,
- {ok, D}.
- %%--------------------------------------------------------------------
- %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
- %% {reply, Reply, State, Timeout} |
- %% {noreply, State} |
- %% {noreply, State, Timeout} |
- %% {stop, Reason, Reply, State} |
- %% {stop, Reason, State}
- %% Description: Handling call messages
- %%--------------------------------------------------------------------
- handle_call({get_module, Module, Key}, _From, S) ->
- Rc = case dict:find(Module, S#s.modules) of
- {ok , Mod} ->
- case dict:find(Key, Mod) of
- {ok, Value} ->
- Value;
- _ ->
- false
- end;
- _ ->
- false
- end,
- {reply, Rc, S}
- ;
- handle_call({get_node, Key}, _From, S) ->
- Rc = case dict:find(Key, S#s.node) of
- {ok, Value} -> Value;
- _ -> false
- end,
- {reply, Rc, S}
- ;
- handle_call({get_global, Key}, _From, S) ->
- Rc = case dict:find(Key, S#s.global) of
- {ok, Value} -> Value;
- _ -> false
- end,
- {reply, Rc, S}
- .
- %%--------------------------------------------------------------------
- %% Function: handle_cast(Msg, State) -> {noreply, State} |
- %% {noreply, State, Timeout} |
- %% {stop, Reason, State}
- %% Description: Handling cast messages
- %%--------------------------------------------------------------------
- handle_cast({set_global, Key, Value}, S) ->
- D1 = dict:store(Key, Value, S#s.global),
- {noreply, S#s{global = D1}}
- ;
- handle_cast({set_node, Key, Value}, S) ->
- D1 = dict:store(Key, Value, S#s.node),
- {noreply, S#s{node = D1}}
- ;
- handle_cast({set_module, Module, Key, Value}, S) ->
- M = case dict:find(Module, S#s.modules) of
- {ok , Mod} ->
- Mod;
- _ ->
- dict:new()
- end,
- D1 = dict:store(Key, Value, M),
- D2 = dict:store(Module, D1, S#s.modules),
- {noreply, S#s{modules = D2}}
- ;
- %% ------------------------------------------------------------------
- %%% Drop key
- %% ------------------------------------------------------------------
- handle_cast({drop_global, Key}, S) ->
- {noreply, S#s{global = dict:erase(Key, S#s.global)}}
- ;
- handle_cast({drop_node, Key}, S) ->
- {noreply, S#s{node = dict:erase(Key, S#s.node)}}
- ;
- handle_cast({drop_module, Module, Key}, S) ->
- case dict:find(Module, S#s.modules) of
- {ok , Mod} ->
- D1 = dict:erase(Key, Mod),
- {noreply, S#s{modules = dict:store(Module, D1, S#s.modules)}};
- _ ->
- {noreply, S}
- end
- ;
- handle_cast(save, S) ->
- file:write_file("config",erlang:term_to_binary(S)),
- {noreply, S}
- ;
- handle_cast(_Info, State) ->
- io:format("Cast ~p~n",[_Info]),
- {noreply, State}
- .
- %%--------------------------------------------------------------------
- %% Function: handle_info(Info, State) -> {noreply, State} |
- %% {noreply, State, Timeout} |
- %% {stop, Reason, State}
- %% Description: Handling all non call/cast messages
- %%--------------------------------------------------------------------
- handle_info(_Info, State) ->
- io:format("Info ~p~n",[_Info]),
- {noreply, State}
- .
- %%--------------------------------------------------------------------
- %% Function: terminate(Reason, State) -> void()
- %% Description: This function is called by a gen_server when it is about to
- %% terminate. It should be the opposite of Module:init/1 and do any necessary
- %% cleaning up. When it returns, the gen_server terminates with Reason.
- %% The return value is ignored.
- %%--------------------------------------------------------------------
- terminate(_Reason, S) ->
- file:write_file("config",erlang:term_to_binary(S)),
- ok
- .
- %%--------------------------------------------------------------------
- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
- %% Description: Convert process state when code is changed
- %%--------------------------------------------------------------------
- code_change(_OldVsn, State, _Extra) ->
- {ok, State}
- .
- %%--------------------------------------------------------------------
- %%% Internal functions
- %%--------------------------------------------------------------------
- drop(Key) ->
- gen_server:cast(config, {drop_global, Key})
- .
- drop(Module, Key) ->
- gen_server:cast(config, {drop_module, Module, Key})
- .
- drop_node(Key) ->
- gen_server:cast(config, {drop_node, Key})
- .
- set(Key, Val) ->
- gen_server:cast(config,{set_global, Key, Val})
- .
- set(Module, Key, Val) ->
- gen_server:cast(config,{set_module, Module, Key, Val})
- .
- set_node(Key, Val) ->
- gen_server:cast(config, {set_node, Key, Val})
- .
- get(Key) ->
- gen_server:call(config,{get_global, Key})
- .
- get(Key, Default) ->
- case gen_server:call(config,{get_global, Key}) of
- false ->
- Default;
- Else ->
- Else
- end
- .
- get(Module, Key, Default) ->
- case gen_server:call(config, {get_module, Module, Key}) of
- false ->
- case gen_server:call(config, {get_node, Key}) of
- false ->
- case gen_server:call(config, {get_global, Key}) of
- false ->
- Default;
- Else ->
- Else
- end;
- Else ->
- Else
- end;
- Else ->
- Else
- end
- .
- subst(Module, What, Where, Old) ->
- D1 = lists:ukeysort(1, config:subst(Module, What, Where)),
- lists:ukeysort(1, lists:keymerge(1, D1, Old))
- .
- subst(Module, What, Where)
- when is_atom(Where) ->
- Subst = config:get(Module, Where, []),
- subst(What, Subst)
- .
- subst(_, []) ->
- []
- ;
- subst(What, [H | T]) ->
- case mlib:match(What, erlang:element(1, H)) of
- true ->
- [_|Rc] = erlang:tuple_to_list(H),
- Rc;
- false ->
- subst(What, T)
- end
- .
- get(Subst, Module, Key, Def) ->
- case lists:keysearch(Key, 1, Subst) of
- {value, {Key, Val}} ->
- Val;
- false ->
- config:get(Module, Key, Def)
- end
- .
- save() ->
- gen_server:cast(config, save)
- .