Bladeren bron

ft: gen_emm修改

master
SisMaker 4 jaren geleden
bovenliggende
commit
8440ac4aad
2 gewijzigde bestanden met toevoegingen van 132 en 89 verwijderingen
  1. +117
    -84
      src/gen_emm.erl
  2. +15
    -5
      src/gen_ipc.erl

+ 117
- 84
src/gen_emm.erl Bestand weergeven

@ -5,6 +5,8 @@
-include_lib("kernel/include/logger.hrl").
-import(maps, [iterator/1, next/1]).
-export([
%% API for gen_emm
start/0, start/1, start/2, start_link/0, start_link/1, start_link/2
@ -235,7 +237,7 @@ add_sup_epm(EpmSrv, EpmHandler, Args) ->
-spec del_epm(serverRef(), epmHandler(), term()) -> term().
del_epm(EpmSrv, EpmHandler, Args) ->
epmRpc(EpmSrv, {'$deleteEpm', EpmHandler, Args}).
epmRpc(EpmSrv, {'$delEpm', EpmHandler, Args}).
-spec swap_epm(serverRef(), {epmHandler(), term()}, {epmHandler(), term()}) -> 'ok' | {'error', term()}.
swap_epm(EpmSrv, {H1, A1}, {H2, A2}) ->
@ -329,7 +331,7 @@ wakeupFromHib(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug) ->
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, IsHib) ->
receive
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, [ServerName, HibernateAfterTimeout, EpmHers, IsHib], IsHib);
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, {ServerName, HibernateAfterTimeout, EpmHers, IsHib}, IsHib);
{'EXIT', Parent, Reason} ->
terminate_server(Reason, Parent, ServerName, EpmHers);
{'$epm_call', From, Request} ->
@ -356,8 +358,8 @@ epmCallMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, From, Requ
{Reply, NewEpmHers, IsHib} = doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup),
reply(From, Reply),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
{'$deleteEpm', EpmHandler, Args} ->
{Reply, NewEpmHers} = doDeleteEpm(EpmHers, EpmHandler, Args),
{'$delEpm', EpmHandler, Args} ->
{Reply, NewEpmHers} = doDelEpm(EpmHers, EpmHandler, Args),
reply(From, Reply),
receiveIng(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, false);
{'$swapEpm', EpmId1, Args1, EpmId2, Args2} ->
@ -392,21 +394,22 @@ handleMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, Msg) ->
NewDebug = ?SYS_DEBUG(Debug, ServerName, {in, Msg}),
case Msg of
{'EXIT', From, Reason} ->
MSL1 = handle_exit(From, Reason, MSL, ServerName),
loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, false);
%% IMY-todo
NewEpmHers = epmStopOne(EpmHers, From),
receiveIng(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, false);
{_From, Tag, stop} ->
catch terminate_server(normal, Parent, MSL, ServerName),
reply(Tag, ok);
try terminate_server(normal, Parent, EpmHers, ServerName)
after
reply(Tag, ok)
end;
{_From, Tag, get_modules} ->
reply(Tag, get_modules(MSL)),
loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, false);
reply(Tag, get_modules(EpmHers)),
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, NewDebug, false);
_ ->
{Hib, MSL1} = doNotify(EpmHers, handleInfo, Msg, false),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib)
{NewEpmHers, IsHib} = doNotify(EpmHers, handleInfo, EpmHers, false),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib)
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EPM inner fun
addNewEpm(InitRet, EpmHers, Module, EpmId, EpmSup) ->
@ -477,9 +480,9 @@ doSwapEpm(EpmHers, EpmId1, Args1, EpmMId, Args2) ->
end.
doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
case EpmHers(EpmId1) of
#{EpmId1 := EpmHer} ->
State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
case EpmHers of
#{EpmId1 := #epmHer{epmSup = OldEpmSup} = EpmHer} ->
State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, OldEpmSup}),
NewEpmHers = maps:remove(EpmId1, EpmHers),
doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup);
undefined ->
@ -499,25 +502,26 @@ allNotify(Iterator, Func, Event, From, TemEpmHers, IsHib) ->
{TemEpmHers, IsHib}
end.
doEpmHandle(EpmHers, EpmHandler, Func, Event, From) ->
doEpmHandle(EpmHers, EpmId, Func, Event, From) ->
case EpmHers of
#{EpmHandler := #epmHer{epmM = EpmM, epmS = EpmS} = EpmHer} ->
#{EpmId := #epmHer{epmM = EpmM, epmS = EpmS} = EpmHer} ->
try EpmM:Func(Event, EpmS) of
Result ->
handleEpmCR(Result, EpmHers, EpmHer, Event, From)
handleEpmCR(Result, EpmHers, EpmId, EpmHer, Event, From)
catch
throw:Ret ->
handleEpmCR(Ret, EpmHers, EpmHer, Event, From);
handleEpmCR(Ret, EpmHers, EpmId, EpmHer, Event, From);
C:R ->
epmTerminate(EpmHer, {error, {C, R, ?STACKTRACE()}}, Event, crash),
NewEpmHers = maps:remove(EpmHandler, EpmHer),
NewEpmHers = maps:remove(EpmId, EpmHer),
{NewEpmHers, false}
end;
_ ->
try_reply(From, {error, bad_module}),
{EpmHers, false}
end.
doDeleteEpm(EpmHers, EpmHandler, Args) ->
doDelEpm(EpmHers, EpmHandler, Args) ->
case EpmHers of
#{EpmHandler := EpmHer} ->
epmTerminate(EpmHer, Args, delete, normal),
@ -527,7 +531,7 @@ doDeleteEpm(EpmHers, EpmHandler, Args) ->
end.
%% handleEpmCallbackRet
handleEpmCR(Result, EpmHers, #epmHer{epmId = EpmId} = EpmHer, Event, From) ->
handleEpmCR(Result, EpmHers, EpmId, EpmHer, Event, From) ->
case Result of
kpS ->
{EpmHers, false};
@ -650,9 +654,9 @@ epm_log(#{label := {gen_emm, no_handle_info}, module := Module, message := Msg})
"** Unhandled message: ~tp~n", [Module, Msg]}.
epmStopAll(EpmHers) ->
allStop(maps:iterator(EpmHers)).
forStopAll(maps:iterator(EpmHers)).
allStop(Iterator) ->
forStopAll(Iterator) ->
case maps:next(Iterator) of
{_K, V, NextIterator} ->
epmTerminate(V, stop, 'receive', shutdown),
@ -662,7 +666,7 @@ allStop(Iterator) ->
EpmSup ->
unlink(EpmSup)
end,
allStop(NextIterator);
forStopAll(NextIterator);
none ->
ok
end.
@ -696,8 +700,20 @@ epmTerminate(#epmHer{epmM = EpmM, epmS = State} = EpmHer, Args, LastIn, Reason)
end.
reply({To, Ref}, Msg) ->
To ! {Ref, Msg},
ok.
try To ! {Ref, Msg},
ok
catch _:_ ->
ok
end.
try_reply(false, _Msg) ->
ignore;
try_reply({To, Ref}, Msg) ->
try To ! {Ref, Msg},
ok
catch _:_ ->
ok
end.
terminate_server(Reason, Parent, ServerName, EpmHers) ->
stop_handlers(EpmHers, ServerName),
@ -721,65 +737,74 @@ do_unlink(Parent, MSL) ->
end,
MSL).
%%-----------------------------------------------------------------
%% Callback functions for system messages handling.
%%-----------------------------------------------------------------
system_continue(Parent, Debug, [ServerName, HibernateAfterTimeout, EpmHers, Hib]) ->
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, Hib).
system_continue(Parent, Debug, {ServerName, HibernateAfterTimeout, EpmHers, IsHib}) ->
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, IsHib).
-spec system_terminate(_, _, _, [_]) -> no_return().
system_terminate(Reason, Parent, _Debug, [ServerName, _HibernateAfterTimeout, EpmHers, _Hib]) ->
-spec system_terminate(_, _, _, _) -> no_return().
system_terminate(Reason, Parent, _Debug, {ServerName, _HibernateAfterTimeout, EpmHers, _IsHib}) ->
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, HibernateAfterTimeout, EpmHers, Hib], Module, OldVsn, Extra) ->
MSL1 = lists:zf(fun(H) when H#handler.module =:= Module ->
{ok, NewState} =
Module:code_change(OldVsn,
H#handler.state, Extra),
{true, H#handler{state = NewState}};
(_) -> true
end,
MSL),
{ok, [ServerName, MSL1, HibernateAfterTimeout, Hib]}.
system_get_state([_ServerName, MSL, _HibernateAfterTimeout, _Hib]) ->
{ok, [{Mod, Id, State} || #handler{module = Mod, id = Id, state = State} <- MSL]}.
system_replace_state(StateFun, [ServerName, MSL, HibernateAfterTimeout, Hib]) ->
{NMSL, NStates} =
lists:unzip([begin
Cur = {Mod, Id, State},
try
NState = {Mod, Id, NS} = StateFun(Cur),
{HS#handler{state = NS}, NState}
catch
_:_ ->
{HS, Cur}
end
end || #handler{module = Mod, id = Id, state = State} = HS <- MSL]),
{ok, NStates, [ServerName, NMSL, HibernateAfterTimeout, Hib]}.
system_code_change({ServerName, HibernateAfterTimeout, EpmHers, IsHib}, Module, OldVsn, Extra) ->
NewEpmHers = forCodeChange(maps:iterator(EpmHers), Module, OldVsn, Extra, EpmHers),
{ok, {ServerName, HibernateAfterTimeout, NewEpmHers, IsHib}}.
forCodeChange(Iterator, CModule, OldVsn, Extra, TemEpmHers) ->
case maps:next(Iterator) of
{K, #epmHer{epmM = Module, epmS = EpmS} = V, NextIterator} when Module =:= CModule ->
{ok, NewEpmS} = Module:code_change(OldVsn, EpmS, Extra),
forCodeChange(NextIterator, CModule, OldVsn, Extra, TemEpmHers#{K := V#epmHer{epmS = NewEpmS}});
{_, _, NextIterator} ->
forCodeChange(NextIterator, CModule, OldVsn, Extra, TemEpmHers);
none ->
TemEpmHers
end.
system_get_state({_ServerName, _HibernateAfterTimeout, EpmHers, _Hib}) ->
{ok, forGetState(maps:iterator(EpmHers), [])}.
forGetState(Iterator, Acc) ->
case maps:next(Iterator) of
{_K, #epmHer{epmId = EpmId, epmM = Module, epmS = EpmS}, NextIterator} ->
forGetState(NextIterator, [{Module, EpmId, EpmS} | Acc]);
none ->
Acc
end.
system_replace_state(StateFun, {ServerName, HibernateAfterTimeout, EpmHers, IsHib}) ->
{NewEpmHers, NStates} = forReplaceState(maps:iterator(EpmHers), StateFun, EpmHers, []),
{ok, NStates, {ServerName, HibernateAfterTimeout, NewEpmHers, IsHib}}.
forReplaceState(Iterator, StateFun, TemEpmHers, NStates) ->
case maps:next(Iterator) of
{K, #epmHer{epmId = EpmId, epmM = Module, epmS = EpmS} = V, NextIterator} ->
NState = {_, _, NewEpmS} = StateFun({Module, EpmId, EpmS}),
forCodeChange(NextIterator, TemEpmHers#{K := V#epmHer{epmS = NewEpmS}}, [NState | NStates]);
none ->
{TemEpmHers, NStates}
end.
%%-----------------------------------------------------------------
%% Format debug messages. Print them as the call-back module sees
%% them, not as the real erlang messages. Use trace for that.
%%-----------------------------------------------------------------
print_event(Dev, {in, Msg}, Name) ->
print_event(Dev, Msg, Name) ->
case Msg of
{notify, Event} ->
io:format(Dev, "*DBG* ~tp got event ~tp~n", [Name, Event]);
{_, _, {call, Handler, Query}} ->
io:format(Dev, "*DBG* ~tp(~tp) got call ~tp~n",
[Name, Handler, Query]);
{call, From, Request} ->
io:format(Dev, "*DBG* ~tp(~tp) got call ~tp from ~tp ~n", [Name, Request, From]);
{info, CmdOrEmpHandler, Event} ->
io:format(Dev, "*DBG* ~tp got info ~tp~n", [CmdOrEmpHandler, Event]);
{in, Msg} ->
io:format(Dev, "*DBG* ~tp got in ~tp~n", [Name, Msg]);
_ ->
io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg])
end;
print_event(Dev, Dbg, Name) ->
io:format(Dev, "*DBG* ~tp : ~tp~n", [Name, Dbg]).
io:format(Dev, "*DBG* ~tp : ~tp~n", [Name, Msg])
end.
%% format_log/1 is the report callback used by Logger handler
%% error_logger only. It is kept for backwards compatibility with
@ -937,14 +962,6 @@ single(false) -> "".
mod(latin1) -> "";
mod(_) -> "t".
handler(Handler) when not Handler#handler.id ->
Handler#handler.module;
handler(Handler) ->
{Handler#handler.module, Handler#handler.id}.
the_handlers(MSL) ->
[handler(Handler) || Handler <- MSL].
%% stop_handlers(MSL, ServerName) -> []
stop_handlers([Handler | T], SName) ->
@ -957,19 +974,35 @@ stop_handlers([], _) ->
%% Message from the release_handler.
%% The list of modules got to be a set, i.e. no duplicate elements!
get_modules(MSL) ->
Mods = [Handler#handler.module || Handler <- MSL],
ordsets:to_list(ordsets:from_list(Mods)).
get_modules(EpmHers) ->
allMods(maps:iterator(EpmHers), []).
allMods(Iterator, Acc) ->
case maps:next(Iterator) of
{_K, V, NextIterator} ->
allMods(NextIterator, [element(#epmHer.epmM, V) | Acc]);
none ->
lists:usort(Acc)
end.
%%-----------------------------------------------------------------
%% Status information
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, _Debug, [ServerName, _HibernateAfterTimeout, EpmHers, _Hib]] = StatusData,
[PDict, SysState, Parent, _Debug, {ServerName, _HibernateAfterTimeout, EpmHers, _IsHib}] = 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],
FmtMSL = allStateStatus(maps:iterator(EpmHers), Opt, PDict, []),
[{header, Header}, {data, [{"Status", SysState}, {"Parent", Parent}]}, {items, {"Installed handlers", FmtMSL}}].
allStateStatus(Iterator, Opt, PDict, EpmHers) ->
case maps:next(Iterator) of
{_K, #epmHer{epmM = Module, epmS = EpmS} = V, NextIterator} ->
NewEpmS = format_status(Opt, Module, PDict, EpmS),
allStateStatus(NextIterator, [V#epmHer{epmS = NewEpmS} | EpmHers]);
none ->
EpmHers
end.
format_status(Opt, Mod, PDict, State) ->
case erlang:function_exported(Mod, format_status, 2) of
true ->

+ 15
- 5
src/gen_ipc.erl Bestand weergeven

@ -827,6 +827,15 @@ reply({To, Tag}, Reply) ->
ok
end.
try_reply(false, _Msg) ->
ignore;
try_reply({To, Ref}, Msg) ->
try To ! {Ref, Msg},
ok
catch _:_ ->
ok
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_event start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
epmRequest({global, Name}, Msg) ->
@ -889,7 +898,7 @@ add_sup_epm(EpmSrv, EpmHandler, Args) ->
-spec del_epm(serverRef(), epmHandler(), term()) -> term().
del_epm(EpmSrv, EpmHandler, Args) ->
epmRpc(EpmSrv, {'$deleteEpm', EpmHandler, Args}).
epmRpc(EpmSrv, {'$delEpm', EpmHandler, Args}).
-spec swap_epm(serverRef(), {epmHandler(), term()}, {epmHandler(), term()}) -> 'ok' | {'error', term()}.
swap_epm(EpmSrv, {H1, A1}, {H2, A2}) ->
@ -973,7 +982,7 @@ doSwapEpm(EpmHers, EpmId1, Args1, EpmMId, Args2) ->
end.
doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
case EpmHers(EpmId1) of
case EpmHers of
#{EpmId1 := EpmHer} ->
State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
NewEpmHers = maps:remove(EpmId1, EpmHers),
@ -1009,10 +1018,11 @@ doEpmHandle(EpmHers, EpmHandler, Func, Event, From) ->
{NewEpmHers, false}
end;
_ ->
try_reply(From, {error, bad_module}),
{EpmHers, false}
end.
doDeleteEpm(EpmHers, EpmHandler, Args) ->
doDelEpm(EpmHers, EpmHandler, Args) ->
case EpmHers of
#{EpmHandler := EpmHer} ->
epmTerminate(EpmHer, Args, delete, normal),
@ -1257,8 +1267,8 @@ matchEpmCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, P
{Reply, NewEpmHers, IsHib} = doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup),
reply(From, Reply),
reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
{'$deleteEpm', EpmHandler, Args} ->
{Reply, NewEpmHers} = doDeleteEpm(EpmHers, EpmHandler, Args),
{'$delEpm', EpmHandler, Args} ->
{Reply, NewEpmHers} = doDelEpm(EpmHers, EpmHandler, Args),
reply(From, Reply),
receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, false);
{'$swapEpm', EpmId1, Args1, EpmId2, Args2} ->

Laden…
Annuleren
Opslaan