diff options
Diffstat (limited to 'lib/kernel/src')
-rw-r--r-- | lib/kernel/src/application.erl | 22 | ||||
-rw-r--r-- | lib/kernel/src/application_controller.erl | 104 | ||||
-rw-r--r-- | lib/kernel/src/logger_std_h.erl | 75 |
3 files changed, 119 insertions, 82 deletions
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl index bc6be2f8f5..5c2e981e4b 100644 --- a/lib/kernel/src/application.erl +++ b/lib/kernel/src/application.erl @@ -25,7 +25,7 @@ which_applications/0, which_applications/1, loaded_applications/0, permit/2]). -export([ensure_started/1, ensure_started/2]). --export([set_env/3, set_env/4, unset_env/2, unset_env/3]). +-export([set_env/1, set_env/2, set_env/3, set_env/4, unset_env/2, unset_env/3]). -export([get_env/1, get_env/2, get_env/3, get_all_env/0, get_all_env/1]). -export([get_key/1, get_key/2, get_all_key/0, get_all_key/1]). -export([get_application/0, get_application/1, info/0]). @@ -279,6 +279,26 @@ loaded_applications() -> info() -> application_controller:info(). +-spec set_env(Config) -> 'ok' when + Config :: [{Application, Env}], + Application :: atom(), + Env :: [{Par :: atom(), Val :: term()}]. + +set_env(Config) when is_list(Config) -> + set_env(Config, []). + +-spec set_env(Config, Opts) -> 'ok' when + Config :: [{Application, Env}], + Application :: atom(), + Env :: [{Par :: atom(), Val :: term()}], + Opts :: [{timeout, timeout()} | {persistent, boolean()}]. + +set_env(Config, Opts) when is_list(Config), is_list(Opts) -> + case application_controller:set_env(Config, Opts) of + ok -> ok; + {error, Msg} -> erlang:error({badarg, Msg}, [Config, Opts]) + end. + -spec set_env(Application, Par, Val) -> 'ok' when Application :: atom(), Par :: atom(), diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl index a074d2e74b..9a8091fb2e 100644 --- a/lib/kernel/src/application_controller.erl +++ b/lib/kernel/src/application_controller.erl @@ -26,7 +26,7 @@ control_application/1, change_application_data/2, prep_config_change/0, config_change/1, which_applications/0, which_applications/1, - loaded_applications/0, info/0, + loaded_applications/0, info/0, set_env/2, get_pid_env/2, get_env/2, get_pid_all_env/1, get_all_env/1, get_pid_key/2, get_key/2, get_pid_all_key/1, get_all_key/1, get_master/1, get_application/1, get_application_module/1, @@ -345,9 +345,6 @@ get_all_env(AppName) -> map(fun([Key, Val]) -> {Key, Val} end, ets:match(ac_tab, {{env, AppName, '$1'}, '$2'})). - - - get_pid_key(Master, Key) -> case ets:match(ac_tab, {{application_master, '$1'}, Master}) of [[AppName]] -> get_key(AppName, Key); @@ -461,6 +458,15 @@ permit_application(ApplName, Flag) -> {permit_application, ApplName, Flag}, infinity). +set_env(Config, Opts) -> + case check_conf_data(Config) of + ok -> + Timeout = proplists:get_value(timeout, Opts, 5000), + gen_server:call(?AC, {set_env, Config, Opts}, Timeout); + + {error, _} = Error -> + Error + end. set_env(AppName, Key, Val) -> gen_server:call(?AC, {set_env, AppName, Key, Val, []}). @@ -528,19 +534,17 @@ check_conf_data([]) -> check_conf_data(ConfData) when is_list(ConfData) -> [Application | ConfDataRem] = ConfData, case Application of - {kernel, List} when is_list(List) -> - case check_para_kernel(List) of - ok -> - check_conf_data(ConfDataRem); - Error1 -> - Error1 - end; {AppName, List} when is_atom(AppName), is_list(List) -> - case check_para(List, atom_to_list(AppName)) of - ok -> - check_conf_data(ConfDataRem); - Error2 -> - Error2 + case lists:keymember(AppName, 1, ConfDataRem) of + true -> + ?LOG_WARNING("duplicate application config: " ++ atom_to_list(AppName)); + false -> + ok + end, + + case check_para(List, AppName) of + ok -> check_conf_data(ConfDataRem); + Error -> Error end; {AppName, List} when is_list(List) -> ErrMsg = "application: " @@ -553,36 +557,40 @@ check_conf_data(ConfData) when is_list(ConfData) -> ++ "; parameters must be a list", {error, ErrMsg}; Else -> - ErrMsg = "invalid application name: " ++ - lists:flatten(io_lib:format(" ~tp",[Else])), + ErrMsg = "invalid application config: " + ++ lists:flatten(io_lib:format("~tp",[Else])), {error, ErrMsg} end; check_conf_data(_ConfData) -> - {error, 'configuration must be a list ended by <dot><whitespace>'}. - + {error, "configuration must be a list ended by <dot><whitespace>"}. -%% Special check of distributed parameter for kernel -check_para_kernel([]) -> + +check_para([], _AppName) -> ok; -check_para_kernel([{distributed, Apps} | ParaList]) when is_list(Apps) -> - case check_distributed(Apps) of - {error, _ErrorMsg} = Error -> - Error; - _ -> - check_para_kernel(ParaList) +check_para([{Para, Val} | ParaList], AppName) when is_atom(Para) -> + case lists:keymember(Para, 1, ParaList) of + true -> + ?LOG_WARNING("application: " ++ atom_to_list(AppName) ++ + "; duplicate parameter: " ++ atom_to_list(Para)); + false -> + ok + end, + + case check_para_value(Para, Val, AppName) of + ok -> check_para(ParaList, AppName); + {error, _} = Error -> Error end; -check_para_kernel([{distributed, _Apps} | _ParaList]) -> - {error, "application: kernel; erroneous parameter: distributed"}; -check_para_kernel([{Para, _Val} | ParaList]) when is_atom(Para) -> - check_para_kernel(ParaList); -check_para_kernel([{Para, _Val} | _ParaList]) -> - {error, "application: kernel; invalid parameter: " ++ +check_para([{Para, _Val} | _ParaList], AppName) -> + {error, "application: " ++ atom_to_list(AppName) ++ "; invalid parameter name: " ++ lists:flatten(io_lib:format("~tp",[Para]))}; -check_para_kernel(Else) -> - {error, "application: kernel; invalid parameter list: " ++ +check_para([Else | _ParaList], AppName) -> + {error, "application: " ++ atom_to_list(AppName) ++ "; invalid parameter: " ++ lists:flatten(io_lib:format("~tp",[Else]))}. - +check_para_value(distributed, Apps, kernel) -> check_distributed(Apps); +check_para_value(_Para, _Val, _AppName) -> ok. + +%% Special check of distributed parameter for kernel check_distributed([]) -> ok; check_distributed([{App, List} | Apps]) when is_atom(App), is_list(List) -> @@ -595,18 +603,6 @@ check_distributed(_Else) -> {error, "application: kernel; erroneous parameter: distributed"}. -check_para([], _AppName) -> - ok; -check_para([{Para, _Val} | ParaList], AppName) when is_atom(Para) -> - check_para(ParaList, AppName); -check_para([{Para, _Val} | _ParaList], AppName) -> - {error, "application: " ++ AppName ++ "; invalid parameter: " ++ - lists:flatten(io_lib:format("~tp",[Para]))}; -check_para([Else | _ParaList], AppName) -> - {error, "application: " ++ AppName ++ "; invalid parameter: " ++ - lists:flatten(io_lib:format("~tp",[Else]))}. - - -type calls() :: 'info' | 'prep_config_change' | 'which_applications' | {'config_change' | 'control_application' | 'load_application' | 'start_type' | 'stop_application' | @@ -863,6 +859,16 @@ handle_call(which_applications, _From, S) -> end, S#state.running), {reply, Reply, S}; +handle_call({set_env, Config, Opts}, _From, S) -> + _ = [add_env(AppName, Env) || {AppName, Env} <- Config], + + case proplists:get_value(persistent, Opts, false) of + true -> + {reply, ok, S#state{conf_data = merge_env(S#state.conf_data, Config)}}; + false -> + {reply, ok, S} + end; + handle_call({set_env, AppName, Key, Val, Opts}, _From, S) -> ets:insert(ac_tab, {{env, AppName, Key}, Val}), case proplists:get_value(persistent, Opts, false) of diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl index 0669164bb6..65f5b3876e 100644 --- a/lib/kernel/src/logger_std_h.erl +++ b/lib/kernel/src/logger_std_h.erl @@ -217,17 +217,24 @@ open_log_file(HandlerName, FileInfo) -> Error -> Error end. -do_open_log_file({file,File}) -> - do_open_log_file({file,File,[raw,append,delayed_write]}); +do_open_log_file({file,FileName}) -> + do_open_log_file({file,FileName,[raw,append,delayed_write]}); -do_open_log_file({file,File,[]}) -> - do_open_log_file({file,File,[raw,append,delayed_write]}); +do_open_log_file({file,FileName,[]}) -> + do_open_log_file({file,FileName,[raw,append,delayed_write]}); -do_open_log_file({file,File,Modes}) -> +do_open_log_file({file,FileName,Modes}) -> try - case filelib:ensure_dir(File) of + case filelib:ensure_dir(FileName) of ok -> - file:open(File, Modes); + case file:open(FileName, Modes) of + {ok, Fd} -> + {ok,#file_info{inode=INode}} = + file:read_file_info(FileName), + {ok, {Fd, INode}}; + Error -> + Error + end; Error -> Error end @@ -237,7 +244,7 @@ do_open_log_file({file,File,Modes}) -> close_log_file(Std) when Std == standard_io; Std == standard_error -> ok; -close_log_file(Fd) -> +close_log_file({Fd,_}) -> _ = file:datasync(Fd), _ = file:close(Fd). @@ -296,9 +303,9 @@ file_ctrl_init(HandlerName, FileInfo, Starter) when is_tuple(FileInfo) -> process_flag(message_queue_data, off_heap), FileName = element(2, FileInfo), case do_open_log_file(FileInfo) of - {ok,Fd} -> + {ok,File} -> Starter ! {self(),ok}, - file_ctrl_loop(Fd, FileName, false, ok, ok, HandlerName); + file_ctrl_loop(File, FileName, false, ok, ok, HandlerName); {error,Reason} -> Starter ! {self(),{error,{open_failed,FileName,Reason}}} end; @@ -306,39 +313,43 @@ file_ctrl_init(HandlerName, StdDev, Starter) -> Starter ! {self(),ok}, file_ctrl_loop(StdDev, StdDev, false, ok, ok, HandlerName). -file_ctrl_loop(Fd, DevName, Synced, +file_ctrl_loop(File, DevName, Synced, PrevWriteResult, PrevSyncResult, HandlerName) -> receive %% asynchronous event {log,Bin} -> - Fd1 = ensure(Fd, DevName), - Result = write_to_dev(Fd1, Bin, DevName, PrevWriteResult, HandlerName), - file_ctrl_loop(Fd1, DevName, false, + File1 = ensure(File, DevName), + Result = write_to_dev(File1, Bin, DevName, + PrevWriteResult, HandlerName), + file_ctrl_loop(File1, DevName, false, Result, PrevSyncResult, HandlerName); %% synchronous event {{log,Bin},{From,MRef}} -> - Fd1 = ensure(Fd, DevName), - Result = write_to_dev(Fd1, Bin, DevName, PrevWriteResult, HandlerName), + File1 = ensure(File, DevName), + Result = write_to_dev(File1, Bin, DevName, + PrevWriteResult, HandlerName), From ! {MRef,ok}, - file_ctrl_loop(Fd1, DevName, false, + file_ctrl_loop(File1, DevName, false, Result, PrevSyncResult, HandlerName); filesync -> - Fd1 = ensure(Fd, DevName), - Result = sync_dev(Fd1, DevName, Synced, PrevSyncResult, HandlerName), - file_ctrl_loop(Fd1, DevName, true, + File1 = ensure(File, DevName), + Result = sync_dev(File1, DevName, Synced, + PrevSyncResult, HandlerName), + file_ctrl_loop(File1, DevName, true, PrevWriteResult, Result, HandlerName); {filesync,{From,MRef}} -> - Fd1 = ensure(Fd, DevName), - Result = sync_dev(Fd1, DevName, Synced, PrevSyncResult, HandlerName), + File1 = ensure(File, DevName), + Result = sync_dev(File1, DevName, Synced, + PrevSyncResult, HandlerName), From ! {MRef,ok}, - file_ctrl_loop(Fd1, DevName, true, + file_ctrl_loop(File1, DevName, true, PrevWriteResult, Result, HandlerName); stop -> - _ = close_log_file(Fd), + _ = close_log_file(File), stopped end. @@ -347,16 +358,16 @@ file_ctrl_loop(Fd, DevName, Synced, %% logrotate) ensure(Fd,DevName) when is_atom(DevName) -> Fd; -ensure(Fd,FileName) -> +ensure({Fd,INode},FileName) -> case file:read_file_info(FileName) of - {ok,_} -> - Fd; + {ok,#file_info{inode=INode}} -> + {Fd,INode}; _ -> _ = file:close(Fd), _ = file:close(Fd), % delayed_write cause close not to close case do_open_log_file({file,FileName}) of - {ok,Fd1} -> - Fd1; + {ok,File} -> + File; Error -> exit({could_not_reopen_file,Error}) end @@ -365,13 +376,13 @@ ensure(Fd,FileName) -> write_to_dev(DevName, Bin, _DevName, _PrevWriteResult, _HandlerName) when is_atom(DevName) -> io:put_chars(DevName, Bin); -write_to_dev(Fd, Bin, FileName, PrevWriteResult, HandlerName) -> +write_to_dev({Fd,_}, Bin, FileName, PrevWriteResult, HandlerName) -> Result = ?file_write(Fd, Bin), maybe_notify_error(write,Result,PrevWriteResult,FileName,HandlerName). -sync_dev(_Fd, _FileName, true, PrevSyncResult, _HandlerName) -> +sync_dev(_, _FileName, true, PrevSyncResult, _HandlerName) -> PrevSyncResult; -sync_dev(Fd, FileName, false, PrevSyncResult, HandlerName) -> +sync_dev({Fd,_}, FileName, false, PrevSyncResult, HandlerName) -> Result = ?file_datasync(Fd), maybe_notify_error(filesync,Result,PrevSyncResult,FileName,HandlerName). |