Bläddra i källkod

ft: gen_emm修改

master
SisMaker 4 år sedan
förälder
incheckning
e63d09ac2c
2 ändrade filer med 16 tillägg och 365 borttagningar
  1. +15
    -364
      src/gen_emm.erl
  2. +1
    -1
      src/gen_ipc.erl

+ 15
- 364
src/gen_emm.erl Visa fil

@ -111,13 +111,6 @@
-type requestId() :: term().
-record(handler, {
module :: atom(),
id = false,
state,
supervised = false :: 'false' | pid()
}).
-record(epmHer, {
epmId = undefined :: term(),
epmM :: atom(),
@ -238,7 +231,7 @@ add_epm(EpmSrv, EpmHandler, Args) ->
-spec add_sup_epm(serverRef(), epmHandler(), term()) -> term().
add_sup_epm(EpmSrv, EpmHandler, Args) ->
epmRpc(EpmSrv, {'$addSupEpm', EpmHandler, Args}).
epmRpc(EpmSrv, {'$addSupEpm', EpmHandler, Args, self()}).
-spec del_epm(serverRef(), epmHandler(), term()) -> term().
del_epm(EpmSrv, EpmHandler, Args) ->
@ -578,17 +571,6 @@ handleEpmCR(Result, EpmHers, #epmHer{epmId = EpmId} = EpmHer, Event, From) ->
{maps:remove(EpmId, EpmHers), false}
end.
epmTerminate(#epmHer{epmM = EpmM, epmS = State} = EpmHer, Args, LastIn, Reason) ->
case erlang:function_exported(EpmM, terminate, 2) of
true ->
Res = (catch EpmM:terminate(Args, State)),
reportTerminate(EpmHer, Reason, Args, LastIn, Res),
Res;
false ->
reportTerminate(EpmHer, Reason, Args, LastIn, ok),
ok
end.
reportTerminate(EpmHer, crash, {error, Why}, LastIn, _) ->
reportTerminate2(EpmHer, Why, LastIn);
%% How == normal | shutdown | {swapped, NewHandler, NewSupervisor}
@ -611,7 +593,7 @@ report_error(_EpmHer, {swapped, _, _}, _, _) -> ok;
report_error(#epmHer{epmId = EpmId, epmM = EpmM}, Reason, State, LastIn) ->
?LOG_ERROR(
#{
label => {gen_ipc, epm_terminate},
label => {gen_emm, epm_terminate},
handler => {EpmId, EpmM},
name => undefined,
last_message => LastIn,
@ -620,11 +602,11 @@ report_error(#epmHer{epmId = EpmId, epmM = EpmM}, Reason, State, LastIn) ->
},
#{
domain => [otp],
report_cb => fun gen_ipc:epm_log/1,
report_cb => fun gen_emm:epm_log/1,
error_logger => #{tag => error}
}).
epm_log(#{label := {gen_ipc, epm_terminate}, handler := Handler, name := SName, last_message := LastIn, state := State, reason := Reason}) ->
epm_log(#{label := {gen_emm, epm_terminate}, handler := Handler, name := SName, last_message := LastIn, state := State, reason := Reason}) ->
Reason1 =
case Reason of
{'EXIT', {undef, [{M, F, A, L} | MFAs]}} ->
@ -644,12 +626,12 @@ epm_log(#{label := {gen_ipc, epm_terminate}, handler := Handler, name := SName,
_ ->
Reason
end,
{"** gen_ipc emp handler ~p crashed.~n"
{"** gen_emm emp handler ~p crashed.~n"
"** Was installed in ~tp~n"
"** Last event was: ~tp~n"
"** When handler state == ~tp~n"
"** Reason == ~tp~n", [Handler, SName, LastIn, State, Reason1]};
epm_log(#{label := {gen_ipc, no_handle_info}, module := Module, message := Msg}) ->
epm_log(#{label := {gen_emm, no_handle_info}, module := Module, message := Msg}) ->
{"** Undefined handle_info in ~tp~n"
"** Unhandled message: ~tp~n", [Module, Msg]}.
@ -725,45 +707,22 @@ do_unlink(Parent, MSL) ->
end,
MSL).
%% First terminate the supervised (if exists) handlers and
%% then inform other handlers.
%% We do not know if any handler really is interested but it
%% may be so !
handle_exit(From, Reason, MSL, SName) ->
MSL1 = terminate_supervised(From, Reason, MSL, SName),
{_, MSL2} = server_notify({'EXIT', From, Reason}, handle_info, MSL1, SName),
MSL2.
terminate_supervised(Pid, Reason, MSL, SName) ->
F = fun(Ha) when Ha#handler.supervised =:= Pid ->
do_terminate(Ha#handler.module,
Ha,
{stop, Reason},
Ha#handler.state,
{parent_terminated, {Pid, Reason}},
SName,
shutdown),
false;
(_) ->
true
end,
lists:filter(F, MSL).
%%-----------------------------------------------------------------
%% Callback functions for system messages handling.
%%-----------------------------------------------------------------
system_continue(Parent, Debug, [ServerName, MSL, HibernateAfterTimeout, Hib]) ->
loopEntry(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib).
system_continue(Parent, Debug, [ServerName, HibernateAfterTimeout, EpmHers, Hib]) ->
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, Hib).
-spec system_terminate(_, _, _, [_]) -> no_return().
system_terminate(Reason, Parent, _Debug, [ServerName, EpmHers, _HibernateAfterTimeout, _Hib]) ->
terminate_server(Reason, Parent, ServerName, EpmHers).
system_terminate(Reason, Parent, _Debug, [ServerName, _HibernateAfterTimeout, EpmHers, _Hib]) ->
terminate_server(Reason, Parent, ServerName, EpmHers).
%%-----------------------------------------------------------------
%% Module here is sent in the system msg change_code. It specifies
%% which module should be changed.
%%-----------------------------------------------------------------
system_code_change([ServerName, MSL, HibernateAfterTimeout, Hib], Module, OldVsn, Extra) ->
system_code_change([ServerName, HibernateAfterTimeout, EpmHers, Hib], Module, OldVsn, Extra) ->
MSL1 = lists:zf(fun(H) when H#handler.module =:= Module ->
{ok, NewState} =
Module:code_change(OldVsn,
@ -808,309 +767,6 @@ print_event(Dev, {in, Msg}, Name) ->
print_event(Dev, Dbg, Name) ->
io:format(Dev, "*DBG* ~tp : ~tp~n", [Name, Dbg]).
%% server_add_handler(Handler, Args, MSL) -> {Ret, MSL'}.
%% where MSL = [#handler{}]
%% Ret goes to the top level MSL' is the new internal state of the
%% event handler
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} ->
{false, ok, [Handler#handler{state = State} | MSL]};
{ok, State, hibernate} ->
{true, ok, [Handler#handler{state = State} | MSL]};
Other ->
{false, 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
{Hib, ok, MSL2} ->
{Hib, ok, MSL2};
{Hib, What, MSL2} ->
{Hib, {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
{Hib, ok, MSL2} ->
{Hib, ok, MSL2};
{Hib, What, MSL2} ->
{Hib, {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} ->
{Hib, NewHandlers} = server_notify(Event, Func, T, SName),
{Hib, [Handler1 | NewHandlers]};
{hibernate, Handler1} ->
{_Hib, NewHandlers} = server_notify(Event, Func, T, SName),
{true, [Handler1 | NewHandlers]};
no ->
server_notify(Event, Func, T, SName)
end;
server_notify(_, _, [], _) ->
{false, []}.
%% server_update(Handler, Func, Event, ServerName) -> Handler1 | no
server_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}};
{ok, State1, hibernate} ->
{hibernate, 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;
{'EXIT', {undef, [{Mod1, handle_info, [_, _], _} | _]}} ->
?LOG_WARNING(#{label => {gen_event, no_handle_info},
module => Mod1,
message => Event},
#{domain => [otp],
report_cb => fun gen_event:format_log/2,
error_logger =>
#{tag => warning_msg, % warningmap??
report_cb => fun gen_event:format_log/1}}),
{ok, Handler1};
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(Handler, 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}}.
-spec split(handler(), [#handler{}]) ->
{atom(), #handler{}, [#handler{}]} | 'error'.
split(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} ->
{false, Reply, delete(Handler, MSL)};
{{ok, Ha1}, Reply} ->
{false, Reply, replace(Handler, MSL, Ha1)};
{{hibernate, Ha1}, Reply} ->
{true, Reply, replace(Handler, MSL, Ha1)}
end;
false ->
{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};
{ok, Reply, State1, hibernate} ->
{{hibernate, 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) ->
case erlang:function_exported(Mod, terminate, 2) of
true ->
Res = (catch Mod:terminate(Args, State)),
report_terminate(Handler, Reason, Args, State, LastIn, SName, Res),
Res;
false ->
report_terminate(Handler, Reason, Args, State, LastIn, SName, ok),
ok
end.
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) ->
?LOG_ERROR(#{label => {gen_event, terminate},
handler => handler(Handler),
name => SName,
last_message => LastIn,
state => format_status(terminate, Handler#handler.module,
get(), State),
reason => Reason},
#{domain => [otp],
report_cb => fun gen_event:format_log/2,
error_logger => #{tag => error,
report_cb => fun gen_event:format_log/1}}).
%% format_log/1 is the report callback used by Logger handler
%% error_logger only. It is kept for backwards compatibility with
%% legacy error_logger event handlers. This function must always
@ -1295,15 +951,10 @@ get_modules(MSL) ->
%% Status information
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, _Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]] = StatusData,
Header = gen:format_status_header("Status for event handler",
ServerName),
FmtMSL = [MS#handler{state = format_status(Opt, Mod, PDict, State)}
|| #handler{module = Mod, state = State} = MS <- MSL],
[{header, Header},
{data, [{"Status", SysState},
{"Parent", Parent}]},
{items, {"Installed handlers", FmtMSL}}].
[PDict, SysState, Parent, _Debug, [ServerName, _HibernateAfterTimeout, EpmHers, _Hib]] = StatusData,
Header = gen:format_status_header("Status for gen_emm handler", ServerName),
FmtMSL = [MS#handler{state = format_status(Opt, Mod, PDict, State)} || #handler{module = Mod, state = State} = MS <- MSL],
[{header, Header}, {data, [{"Status", SysState}, {"Parent", Parent}]}, {items, {"Installed handlers", FmtMSL}}].
format_status(Opt, Mod, PDict, State) ->
case erlang:function_exported(Mod, format_status, 2) of

+ 1
- 1
src/gen_ipc.erl Visa fil

@ -885,7 +885,7 @@ add_epm(EpmSrv, EpmHandler, Args) ->
-spec add_sup_epm(serverRef(), epmHandler(), term()) -> term().
add_sup_epm(EpmSrv, EpmHandler, Args) ->
epmRpc(EpmSrv, {'$addSupEpm', EpmHandler, Args}).
epmRpc(EpmSrv, {'$addSupEpm', EpmHandler, Args, self()}).
-spec del_epm(serverRef(), epmHandler(), term()) -> term().
del_epm(EpmSrv, EpmHandler, Args) ->

Laddar…
Avbryt
Spara