gen_event.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 659 行 · 第 1/2 页
ERL
659 行
server_add_handler({Mod,Id}, Args, MSL) -> Handler = #handler{module = Mod, id = Id}, server_add_handler(Mod, Handler, Args, MSL);server_add_handler(Mod, Args, MSL) -> Handler = #handler{module = Mod}, server_add_handler(Mod, Handler, Args, MSL).server_add_handler(Mod, Handler, Args, MSL) -> case catch Mod:init(Args) of {ok, State} -> {ok, [Handler#handler{state = State}|MSL]}; Other -> {Other, MSL} end.%% Set up a link to the supervising process.%% (Ought to be unidirected links here, Erl5.0 !!)%% NOTE: This link will not be removed then the%% handler is removed in case another handler has%% own link to this process.server_add_sup_handler({Mod,Id}, Args, MSL, Parent) -> link(Parent), Handler = #handler{module = Mod, id = Id, supervised = Parent}, server_add_handler(Mod, Handler, Args, MSL);server_add_sup_handler(Mod, Args, MSL, Parent) -> link(Parent), Handler = #handler{module = Mod, supervised = Parent}, server_add_handler(Mod, Handler, Args, MSL).%% server_delete_handler(HandlerId, Args, MSL) -> {Ret, MSL'}server_delete_handler(HandlerId, Args, MSL, SName) -> case split(HandlerId, MSL) of {Mod, Handler, MSL1} -> {do_terminate(Mod, Handler, Args, Handler#handler.state, delete, SName, normal), MSL1}; error -> {{error, module_not_found}, MSL} end.%% server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, SN)= -> MSL'%% server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, Sup, SN)= -> MSL'server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, SName) -> {State2, Sup, MSL1} = split_and_terminate(Handler1, Args1, MSL, SName, Handler2, false), case s_s_h(Sup, Handler2, {Args2, State2}, MSL1) of {ok, MSL2} -> {ok, MSL2}; {What, MSL2} -> {{error, What}, MSL2} end.server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, Sup, SName) -> {State2, _, MSL1} = split_and_terminate(Handler1, Args1, MSL, SName, Handler2, Sup), case s_s_h(Sup, Handler2, {Args2, State2}, MSL1) of {ok, MSL2} -> {ok, MSL2}; {What, MSL2} -> {{error, What}, MSL2} end.s_s_h(false, Handler, Args, MSL) -> server_add_handler(Handler, Args, MSL);s_s_h(Pid, Handler, Args, MSL) -> server_add_sup_handler(Handler, Args, MSL, Pid).split_and_terminate(HandlerId, Args, MSL, SName, Handler2, Sup) -> case split(HandlerId, MSL) of {Mod, Handler, MSL1} -> OldSup = Handler#handler.supervised, NewSup = if not Sup -> OldSup; true -> Sup end, {do_terminate(Mod, Handler, Args, Handler#handler.state, swapped, SName, {swapped, Handler2, NewSup}), OldSup, MSL1}; error -> {error, false, MSL} end.%% server_notify(Event, Func, MSL, SName) -> MSL'server_notify(Event, Func, [Handler|T], SName) -> case server_update(Handler, Func, Event, SName) of {ok, Handler1} -> [Handler1|server_notify(Event, Func, T, SName)]; no -> server_notify(Event, Func, T, SName) end;server_notify(_, _, [], _) -> [].%% server_update(Handler, Func, Event, ServerName) -> Handler1 | noserver_update(Handler1, Func, Event, SName) -> Mod1 = Handler1#handler.module, State = Handler1#handler.state, case catch Mod1:Func(Event, State) of {ok, State1} -> {ok, Handler1#handler{state = State1}}; {swap_handler, Args1, State1, Handler2, Args2} -> do_swap(Mod1,Handler1,Args1,State1,Handler2,Args2,SName); remove_handler -> do_terminate(Mod1, Handler1, remove_handler, State, remove, SName, normal), no; Other -> do_terminate(Mod1, Handler1, {error, Other}, State, Event, SName, crash), no end.do_swap(Mod1,Handler1,Args1,State1,Handler2,Args2,SName) -> %% finalise the existing handler State2 = do_terminate(Mod1, Handler1, Args1, State1, swapped, SName, {swapped, Handler2, Handler1#handler.supervised}), {Mod2,Handler} = new_handler(Handler2, Handler1), case catch Mod2:init({Args2, State2}) of {ok, State2a} -> {ok, Handler#handler{state = State2a}}; Other -> report_terminate(Handler2, crash, {error, Other}, SName, false), no end.new_handler({Mod,Id}, Handler1) -> {Mod,#handler{module = Mod, id = Id, supervised = Handler1#handler.supervised}};new_handler(Mod, Handler1) -> {Mod,#handler{module = Mod, supervised = Handler1#handler.supervised}}.%% split(Handler, [#handler]) ->%% {Mod, #handler, [#handler]} | errorsplit(Ha, MSL) -> split(Ha, MSL, []).split({Mod,Id}, [Ha|T], L) when Ha#handler.module =:= Mod, Ha#handler.id =:= Id -> {Mod, Ha, lists:reverse(L, T)};split(Mod, [Ha|T], L) when Ha#handler.module =:= Mod, not Ha#handler.id -> {Mod, Ha, lists:reverse(L, T)};split(Ha, [H|T], L) -> split(Ha, T, [H|L]);split(_, [], _) -> error.%% server_call(Handler, Query, MSL, ServerName) ->%% {Reply, MSL1}server_call(Handler, Query, MSL, SName) -> case search(Handler, MSL) of {ok, Ha} -> case server_call_update(Ha, Query, SName) of {no, Reply} -> {Reply, delete(Handler, MSL)}; {{ok, Ha1}, Reply} -> {Reply, replace(Handler, MSL, Ha1)} end; false -> {{error, bad_module}, MSL} end.search({Mod, Id}, [Ha|_MSL]) when Ha#handler.module =:= Mod, Ha#handler.id =:= Id -> {ok, Ha};search(Mod, [Ha|_MSL]) when Ha#handler.module =:= Mod, not Ha#handler.id -> {ok, Ha};search(Handler, [_|MSL]) -> search(Handler, MSL);search(_, []) -> false.delete({Mod, Id}, [Ha|MSL]) when Ha#handler.module =:= Mod, Ha#handler.id =:= Id -> MSL;delete(Mod, [Ha|MSL]) when Ha#handler.module =:= Mod, not Ha#handler.id -> MSL;delete(Handler, [Ha|MSL]) -> [Ha|delete(Handler, MSL)];delete(_, []) -> [].replace({Mod, Id}, [Ha|MSL], NewHa) when Ha#handler.module =:= Mod, Ha#handler.id =:= Id -> [NewHa|MSL];replace(Mod, [Ha|MSL], NewHa) when Ha#handler.module =:= Mod, not Ha#handler.id -> [NewHa|MSL];replace(Handler, [Ha|MSL], NewHa) -> [Ha|replace(Handler, MSL, NewHa)];replace(_, [], NewHa) -> [NewHa].%% server_call_update(Handler, Query, ServerName) ->%% {{Handler1, State1} | no, Reply}server_call_update(Handler1, Query, SName) -> Mod1 = Handler1#handler.module, State = Handler1#handler.state, case catch Mod1:handle_call(Query, State) of {ok, Reply, State1} -> {{ok, Handler1#handler{state = State1}}, Reply}; {swap_handler, Reply, Args1, State1, Handler2, Args2} -> {do_swap(Mod1,Handler1,Args1,State1,Handler2,Args2,SName), Reply}; {remove_handler, Reply} -> do_terminate(Mod1, Handler1, remove_handler, State, remove, SName, normal), {no, Reply}; Other -> do_terminate(Mod1, Handler1, {error, Other}, State, Query, SName, crash), {no, {error, Other}}end.do_terminate(Mod, Handler, Args, State, LastIn, SName, Reason) -> Res = (catch Mod:terminate(Args, State)), report_terminate(Handler, Reason, Args, State, LastIn, SName, Res), Res.report_terminate(Handler, crash, {error, Why}, State, LastIn, SName, _) -> report_terminate(Handler, Why, State, LastIn, SName);report_terminate(Handler, How, _, State, LastIn, SName, _) -> %% How == normal | shutdown | {swapped, NewHandler, NewSupervisor} report_terminate(Handler, How, State, LastIn, SName).report_terminate(Handler, Reason, State, LastIn, SName) -> report_error(Handler, Reason, State, LastIn, SName), case Handler#handler.supervised of false -> ok; Pid -> Pid ! {gen_event_EXIT,handler(Handler),Reason}, ok end.report_error(_Handler, normal, _, _, _) -> ok;report_error(_Handler, shutdown, _, _, _) -> ok;report_error(_Handler, {swapped,_,_}, _, _, _) -> ok;report_error(Handler, Reason, State, LastIn, SName) -> Reason1 = case Reason of {'EXIT',{undef,[{M,F,A}|MFAs]}} -> case code:is_loaded(M) of false -> {'module could not be loaded',[{M,F,A}|MFAs]}; _ -> case erlang:function_exported(M, F, length(A)) of true -> {undef,[{M,F,A}|MFAs]}; false -> {'function not exported',[{M,F,A}|MFAs]} end end; {'EXIT',Why} -> Why; _ -> Reason end, error_msg("** gen_event handler ~p crashed.~n" "** Was installed in ~p~n" "** Last event was: ~p~n" "** When handler state == ~p~n" "** Reason == ~p~n", [handler(Handler),SName,LastIn,State,Reason1]).handler(Handler) when not Handler#handler.id -> Handler#handler.module;handler(Handler) -> {Handler#handler.module, Handler#handler.id}.%% stop_handlers(MSL, ServerName) -> []stop_handlers([Handler|T], SName) -> Mod = Handler#handler.module, do_terminate(Mod, Handler, stop, Handler#handler.state, stop, SName, shutdown), stop_handlers(T, SName);stop_handlers([], _) -> [].the_handlers(MSL) -> lists:map(fun(Handler) when not Handler#handler.id -> Handler#handler.module; (Handler) -> {Handler#handler.module, Handler#handler.id} end, MSL).%% Message from the release_handler.%% The list of modules got to be a set !get_modules(MSL) -> Mods = lists:map(fun(Handler) -> Handler#handler.module end, MSL), ordsets:to_list(ordsets:from_list(Mods)).%%-----------------------------------------------------------------%% Status information%%-----------------------------------------------------------------format_status(_Opt, StatusData) -> [_PDict, SysState, Parent, _Debug, [ServerName, MSL]] = StatusData, Header = lists:concat(["Status for event handler ", ServerName]), [{header, Header}, {data, [{"Status", SysState}, {"Parent", Parent}]}, {items, {"Installed handlers", MSL}}].
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?