Procházet zdrojové kódy

ft: add gen_emm

master
SisMaker před 4 roky
rodič
revize
b3977d86f7
2 změnil soubory, kde provedl 426 přidání a 100 odebrání
  1. +381
    -71
      src/gen_emm.erl
  2. +45
    -29
      src/gen_ipc.erl

+ 381
- 71
src/gen_emm.erl Zobrazit soubor

@ -111,10 +111,19 @@
-type requestId() :: term().
-record(handler, {module :: atom(),
-record(handler, {
module :: atom(),
id = false,
state,
supervised = false :: 'false' | pid()}).
supervised = false :: 'false' | pid()
}).
-record(epmHer, {
epmId = undefined :: term(),
epmM :: atom(),
epmSup = undefined :: 'undefined' | pid(),
epmS :: term()
}).
-callback init(InitArgs :: term()) ->
{ok, State :: term()} |
@ -221,7 +230,7 @@ init_it(Starter, Parent, ServerRef, _, _, Options) ->
Debug = gen:debug_options(Name, Options),
HibernateAfterTimeout = gen:hibernate_after(Options),
proc_lib:init_ack(Starter, {ok, self()}),
receiveIng(Parent, Name, [], HibernateAfterTimeout, Debug, false).
receiveIng(Parent, Name, HibernateAfterTimeout, #{}, Debug, false).
-spec add_epm(serverRef(), epmHandler(), term()) -> term().
add_epm(EpmSrv, EpmHandler, Args) ->
@ -316,90 +325,391 @@ epmRequest(EpmSrv, Cmd) ->
EpmSrv ! Cmd,
ok.
loopEntry(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true) ->
proc_lib:hibernate(?MODULE, wake_hib, [Parent, ServerName, MSL, HibernateAfterTimeout, Debug]);
loopEntry(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, _) ->
receiveIng(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, false).
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, true) ->
proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug]);
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, _) ->
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, false).
wakeupFromHib(Parent, ServerName, MSL, HibernateAfterTimeout, Debug) ->
receiveIng(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true).
wakeupFromHib(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug) ->
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, true).
receiveIng(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, IsHib) ->
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, IsHib) ->
receive
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, [ServerName, MSL, HibernateAfterTimeout, IsHib], IsHib);
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, [ServerName, HibernateAfterTimeout, EpmHers, IsHib], IsHib);
{'EXIT', Parent, Reason} ->
terminate_server(Reason, Parent, MSL, ServerName);
terminate_server(Reason, Parent, ServerName, EpmHers);
{'$epm_call', From, Request} ->
epmCallMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, From, Request);
{'$epm_info', CmdOrEmpHandler, Event} ->
epmInfoMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, CmdOrEmpHandler, Event);
Msg ->
handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug)
handleMsg(Parent, ServerName, HibernateAfterTimeout,EpmHers, Debug, Msg)
after HibernateAfterTimeout ->
proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, ServerName, MSL, HibernateAfterTimeout, Debug])
proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug])
end.
epmCallMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, From, Request) ->
NewDebug = ?SYS_DEBUG(Debug, ServerName, {call, From, Request}),
case Request of
'$which_handlers' ->
reply(From, EpmHers),
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, NewDebug, false);
{'$addEpm', EpmHandler, Args} ->
{Reply, NewEpmHers, IsHib} = doAddEpm(EpmHers, EpmHandler, Args, undefined),
reply(From, Reply),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
{'$addSupEpm', EpmHandler, Args, EpmSup} ->
{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),
reply(From, Reply),
receiveIng(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, false);
{'$swapEpm', EpmId1, Args1, EpmId2, Args2} ->
{Reply, NewEpmHers, IsHib} = doSwapEpm(EpmHers, EpmId1, Args1, EpmId2, Args2),
reply(From, Reply),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
{'$swapSupEpm', EpmId1, Args1, EpmId2, Args2, SupPid} ->
{Reply, NewEpmHers, IsHib} = doSwapSupEpm(EpmHers, EpmId1, Args1, EpmId2, Args2, SupPid),
reply(From, Reply),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
{'$syncNotify', Event} ->
{NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
reply(From, ok),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
{'$epmCall', EpmHandler, Query} ->
{NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleCall, Query, From),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib)
end.
epmInfoMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, CmdOrEmpHandler, Event) ->
NewDebug = ?SYS_DEBUG(Debug, ServerName, {info, CmdOrEmpHandler, Event}),
case CmdOrEmpHandler of
'$infoNotify' ->
{NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
EpmHandler ->
{NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleInfo, Event, false),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib)
end.
handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug) ->
handleMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, Msg) ->
NewDebug = ?SYS_DEBUG(Debug, ServerName, {in, Msg}),
case Msg of
{notify, Event} ->
{Hib, MSL1} = server_notify(Event, handle_event, MSL, ServerName),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{_From, Tag, {sync_notify, Event}} ->
{Hib, MSL1} = server_notify(Event, handle_event, MSL, ServerName),
reply(Tag, ok),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{'EXIT', From, Reason} ->
MSL1 = handle_exit(From, Reason, MSL, ServerName),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, false);
{_From, Tag, {call, Handler, Query}} ->
{Hib, Reply, MSL1} = server_call(Handler, Query, MSL, ServerName),
reply(Tag, Reply),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{_From, Tag, {add_handler, Handler, Args}} ->
{Hib, Reply, MSL1} = server_add_handler(Handler, Args, MSL),
reply(Tag, Reply),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{_From, Tag, {add_sup_handler, Handler, Args, SupP}} ->
{Hib, Reply, MSL1} = server_add_sup_handler(Handler, Args, MSL, SupP),
reply(Tag, Reply),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{_From, Tag, {delete_handler, Handler, Args}} ->
{Reply, MSL1} = server_delete_handler(Handler, Args, MSL,
ServerName),
reply(Tag, Reply),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, false);
{_From, Tag, {swap_handler, Handler1, Args1, Handler2, Args2}} ->
{Hib, Reply, MSL1} = server_swap_handler(Handler1, Args1, Handler2,
Args2, MSL, ServerName),
reply(Tag, Reply),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{_From, Tag, {swap_sup_handler, Handler1, Args1, Handler2, Args2,
Sup}} ->
{Hib, Reply, MSL1} = server_swap_handler(Handler1, Args1, Handler2,
Args2, MSL, Sup, ServerName),
reply(Tag, Reply),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib);
{_From, Tag, stop} ->
catch terminate_server(normal, Parent, MSL, ServerName),
reply(Tag, ok);
{_From, Tag, which_handlers} ->
reply(Tag, the_handlers(MSL)),
loopEntry(Parent, ServerName, MSL, HibernateAfterTimeout, NewDebug, false);
{_From, Tag, get_modules} ->
reply(Tag, get_modules(MSL)),
loopEntry(Parent, ServerName, MSL, HibernateAfterTimeout, NewDebug, false);
{Hib, MSL1} = doNotify(EpmHers, handleInfo, Msg, false),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EPM inner fun
addNewEpm(InitRet, EpmHers, Module, EpmId, EpmSup) ->
case InitRet of
{ok, State} ->
EpmHer = #epmHer{epmId = EpmId, epmM = Module, epmS = State, epmSup = EpmSup},
{ok, EpmHers#{EpmId => EpmHer}, false};
{ok, State, hibernate} ->
EpmHer = #epmHer{epmId = EpmId, epmM = Module, epmS = State, epmSup = EpmSup},
{ok, EpmHers#{EpmId => EpmHer}, true};
Other ->
{Hib, MSL1} = server_notify(Other, handle_info, MSL, ServerName),
loopEntry(Parent, ServerName, MSL1, HibernateAfterTimeout, NewDebug, Hib)
{Other, EpmHers, false}
end.
terminate_server(Reason, Parent, MSL, ServerName) ->
stop_handlers(MSL, ServerName),
do_unlink(Parent, MSL),
exit(Reason).
doAddEpm(EpmHers, {Module, _SubId} = EpmId, Args, EpmSup) ->
case EpmHers of
#{EpmId := _EpmHer} ->
{{error, existed}, EpmHers, false};
_ ->
try Module:init(Args) of
Result ->
addNewEpm(Result, EpmHers, Module, EpmId, EpmSup)
catch
throw:Ret ->
addNewEpm(Ret, EpmHers, Module, EpmId, EpmSup);
C:R ->
{{error, {C, R, ?STACKTRACE()}}, EpmHers, false}
end
end;
doAddEpm(EpmHers, Module, Args, EpmSup) ->
case EpmHers of
#{Module := _EpmHer} ->
{{error, existed}, EpmHers, false};
_ ->
try Module:init(Args) of
Result ->
addNewEpm(Result, EpmHers, Module, Module, EpmSup)
catch
throw:Ret ->
addNewEpm(Ret, EpmHers, Module, Module, EpmSup);
C:R ->
{{error, {C, R, ?STACKTRACE()}}, EpmHers, false}
end
end.
doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup) ->
case doAddEpm(EpmHers, EpmHandler, Args, EpmSup) of
{ok, _, _} = Result ->
link(EpmSup),
Result;
Ret ->
Ret
end.
doSwapEpm(EpmHers, EpmId1, Args1, EpmMId, Args2) ->
case EpmHers of
#{EpmId1 := #epmHer{epmSup = EpmSup} = EpmHer} ->
State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
NewEpmHers = maps:remove(EpmId1, EpmHers),
case EpmSup of
false ->
doAddEpm(NewEpmHers, EpmMId, {Args2, State2}, undefined);
_ ->
doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup)
end;
undefined ->
doAddEpm(EpmHers, EpmMId, {Args2, undefined}, undefined)
end.
doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
case EpmHers(EpmId1) of
#{EpmId1 := EpmHer} ->
State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
NewEpmHers = maps:remove(EpmId1, EpmHers),
doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup);
undefined ->
doAddSupEpm(EpmHers, EpmMId, {Args2, undefined}, EpmSup)
end.
doNotify(EpmHers, Func, Event, _Form) ->
allNotify(maps:iterator(EpmHers), Func, Event, false, EpmHers, false).
allNotify(Iterator, Func, Event, From, TemEpmHers, IsHib) ->
case maps:next(Iterator) of
{K, _V, NextIterator} ->
{NewEpmHers, NewIsHib} = doEpmHandle(TemEpmHers, K, Func, Event, From),
allNotify(NextIterator, Func, Event, From, NewEpmHers, IsHib orelse NewIsHib);
_ ->
{TemEpmHers, IsHib}
end.
doEpmHandle(EpmHers, EpmHandler, Func, Event, From) ->
case EpmHers of
#{EpmHandler := #epmHer{epmM = EpmM, epmS = EpmS} = EpmHer} ->
try EpmM:Func(Event, EpmS) of
Result ->
handleEpmCR(Result, EpmHers, EpmHer, Event, From)
catch
throw:Ret ->
handleEpmCR(Ret, EpmHers, EpmHer, Event, From);
C:R ->
epmTerminate(EpmHer, {error, {C, R, ?STACKTRACE()}}, Event, crash),
NewEpmHers = maps:remove(EpmHandler, EpmHer),
{NewEpmHers, false}
end;
_ ->
{EpmHers, false}
end.
doDeleteEpm(EpmHers, EpmHandler, Args) ->
case EpmHers of
#{EpmHandler := EpmHer} ->
epmTerminate(EpmHer, Args, delete, normal),
{ok, maps:remove(EpmHandler, EpmHers)};
undefined ->
{{error, module_not_found}, EpmHers}
end.
%% handleEpmCallbackRet
handleEpmCR(Result, EpmHers, #epmHer{epmId = EpmId} = EpmHer, Event, From) ->
case Result of
ok ->
{EpmHers, false};
{ok, NewEpmS} ->
MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
{EpmHers#{EpmId := MewEpmHer}, false};
{ok, NewEpmS, hibernate} ->
MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
{EpmHers#{EpmId := MewEpmHer}, true};
{swapEpm, NewEpmS, Args1, EpmMId, Args2} ->
#epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
TemEpmHers = maps:remove(EpmId, EpmHers),
{_, NewEpmHers, IsHib} =
case EpmSup of
undefined ->
doAddEpm(TemEpmHers, EpmMId, {Args2, State}, undefined);
_ ->
doAddSupEpm(TemEpmHers, EpmMId, {Args2, State}, EpmSup)
end,
{NewEpmHers, IsHib};
{swapEpm, Reply, NewEpmS, Args1, EpmMId, Args2} ->
reply(From, Reply),
#epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
TemEpmHers = maps:remove(EpmId, EpmHers),
{_, NewEpmHers, IsHib} =
case EpmSup of
undefined ->
doAddEpm(TemEpmHers, EpmMId, {Args2, State}, undefined);
_ ->
doAddSupEpm(TemEpmHers, EpmMId, {Args2, State}, EpmSup)
end,
{NewEpmHers, IsHib};
removeEpm ->
epmTerminate(EpmHer, removeEpm, remove, normal),
{maps:remove(EpmId, EpmHers), false};
{removeEpm, Reply} ->
reply(From, Reply),
epmTerminate(EpmHer, removeEpm, remove, normal),
{maps:remove(EpmId, EpmHers), false};
{reply, Reply} ->
reply(From, Reply),
{EpmHers, false};
{reply, Reply, NewEpmS} ->
reply(From, Reply),
MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
{EpmHers#{EpmId := MewEpmHer}, false};
{reply, Reply, NewEpmS, hibernate} ->
reply(From, Reply),
MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
{EpmHers#{EpmId := MewEpmHer}, true};
Other ->
epmTerminate(EpmHer, {error, Other}, Event, crash),
{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}
reportTerminate(EpmHer, How, _, LastIn, _) ->
reportTerminate2(EpmHer, How, LastIn).
reportTerminate2(#epmHer{epmSup = EpmSup, epmId = EpmId, epmS = State} = EpmHer, Reason, LastIn) ->
report_error(EpmHer, Reason, State, LastIn),
case EpmSup of
undefined ->
ok;
_ ->
EpmSup ! {gen_event_EXIT, EpmId, Reason},
ok
end.
report_error(_EpmHer, normal, _, _) -> ok;
report_error(_EpmHer, shutdown, _, _) -> ok;
report_error(_EpmHer, {swapped, _, _}, _, _) -> ok;
report_error(#epmHer{epmId = EpmId, epmM = EpmM}, Reason, State, LastIn) ->
?LOG_ERROR(
#{
label => {gen_ipc, epm_terminate},
handler => {EpmId, EpmM},
name => undefined,
last_message => LastIn,
state => State,
reason => Reason
},
#{
domain => [otp],
report_cb => fun gen_ipc: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}) ->
Reason1 =
case Reason of
{'EXIT', {undef, [{M, F, A, L} | MFAs]}} ->
case code:is_loaded(M) of
false ->
{'module could not be loaded', [{M, F, A, L} | MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
{undef, [{M, F, A, L} | MFAs]};
false ->
{'function not exported', [{M, F, A, L} | MFAs]}
end
end;
{'EXIT', Why} ->
Why;
_ ->
Reason
end,
{"** gen_ipc 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}) ->
{"** Undefined handle_info in ~tp~n"
"** Unhandled message: ~tp~n", [Module, Msg]}.
epmStopAll(EpmHers) ->
allStop(maps:iterator(EpmHers)).
allStop(Iterator) ->
case maps:next(Iterator) of
{_K, V, NextIterator} ->
epmTerminate(V, stop, 'receive', shutdown),
case element(#epmHer.epmSup, V) of
undefined ->
ignore;
EpmSup ->
unlink(EpmSup)
end,
allStop(NextIterator);
none ->
ok
end.
epmStopOne(ExitEmpSup, EpmHers) ->
forStopOne(maps:iterator(EpmHers), ExitEmpSup, EpmHers).
forStopOne(Iterator, ExitEmpSup, TemEpmHers) ->
case maps:next(Iterator) of
{K, V, NextIterator} ->
case element(#epmHer.epmSup, V) =:= ExitEmpSup of
true ->
epmTerminate(V, stop, 'receive', shutdown),
forStopOne(NextIterator, ExitEmpSup, maps:remove(K, TemEpmHers));
_ ->
forStopOne(NextIterator, ExitEmpSup, TemEpmHers)
end;
none ->
TemEpmHers
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.
reply({To, Ref}, Msg) ->
To ! {Ref, Msg},
ok.
terminate_server(Reason, Parent, ServerName, EpmHers) ->
stop_handlers(EpmHers, ServerName),
do_unlink(Parent, EpmHers),
exit(Reason).
%% unlink the supervisor process of all supervised handlers.
%% We do not want a handler supervisor to EXIT due to the
%% termination of the event manager (server).
@ -446,8 +756,8 @@ system_continue(Parent, Debug, [ServerName, MSL, HibernateAfterTimeout, Hib]) ->
loopEntry(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib).
-spec system_terminate(_, _, _, [_]) -> no_return().
system_terminate(Reason, Parent, _Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]) ->
terminate_server(Reason, Parent, MSL, ServerName).
system_terminate(Reason, Parent, _Debug, [ServerName, EpmHers, _HibernateAfterTimeout, _Hib]) ->
terminate_server(Reason, Parent, ServerName, EpmHers).
%%-----------------------------------------------------------------
%% Module here is sent in the system msg change_code. It specifies

+ 45
- 29
src/gen_ipc.erl Zobrazit soubor

@ -982,13 +982,17 @@ doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
doAddSupEpm(EpmHers, EpmMId, {Args2, undefined}, EpmSup)
end.
doNotify(EpmHers, Event, Func, _Form) ->
FunFor =
fun(K, _V, {TemEpmHers, IsHib}) ->
{NewEpmHers, NewIsHib} = doEpmHandle(TemEpmHers, K, Func, Event, false),
{NewEpmHers, NewIsHib orelse IsHib}
end,
maps:fold(FunFor, {EpmHers, false}, EpmHers).
doNotify(EpmHers, Func, Event, _Form) ->
allNotify(maps:iterator(EpmHers), Func, Event, false, EpmHers, false).
allNotify(Iterator, Func, Event, From, TemEpmHers, IsHib) ->
case maps:next(Iterator) of
{K, _V, NextIterator} ->
{NewEpmHers, NewIsHib} = doEpmHandle(TemEpmHers, K, Func, Event, From),
allNotify(NextIterator, Func, Event, From, NewEpmHers, IsHib orelse NewIsHib);
_ ->
{TemEpmHers, IsHib}
end.
doEpmHandle(EpmHers, EpmHandler, Func, Event, From) ->
case EpmHers of
@ -1093,30 +1097,39 @@ epm_log(#{label := {gen_ipc, no_handle_info}, module := Module, message := Msg})
"** Unhandled message: ~tp~n", [Module, Msg]}.
epmStopAll(EpmHers) ->
FunFor =
fun(_K, V, _Ok) ->
allStop(maps:iterator(EpmHers)).
allStop(Iterator) ->
case maps:next(Iterator) of
{_K, V, NextIterator} ->
epmTerminate(V, stop, 'receive', shutdown),
case element(#epmHer.epmSup, V) of
undefined ->
ignore;
EpmSup ->
unlink(EpmSup)
end
end,
maps:fold(FunFor, ok, EpmHers).
end,
allStop(NextIterator);
none ->
ok
end.
epmStopOne(ExitEmpSup, EpmHers) ->
FunFor =
fun(K, V, TemEpmHers) ->
forStopOne(maps:iterator(EpmHers), ExitEmpSup, EpmHers).
forStopOne(Iterator, ExitEmpSup, TemEpmHers) ->
case maps:next(Iterator) of
{K, V, NextIterator} ->
case element(#epmHer.epmSup, V) =:= ExitEmpSup of
true ->
epmTerminate(V, stop, 'receive', shutdown),
maps:remove(K, TemEpmHers);
forStopOne(NextIterator, ExitEmpSup, maps:remove(K, TemEpmHers));
_ ->
EpmHers
end
end,
maps:fold(FunFor, EpmHers, EpmHers).
forStopOne(NextIterator, ExitEmpSup, TemEpmHers)
end;
none ->
TemEpmHers
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_event end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listify(Item) when is_list(Item) ->
@ -1257,7 +1270,7 @@ matchEpmCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, P
reply(From, Reply),
reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
{'$syncNotify', Event} ->
{NewEpmHers, IsHib} = doNotify(EpmHers, Event, handleEvent, false),
{NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
reply(From, ok),
startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmEvent, Request, IsHib);
{'$epmCall', EpmHandler, Query} ->
@ -1269,10 +1282,10 @@ matchEpmInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, P
NewDebug = ?SYS_DEBUG(Debug, Name, {in, {CmdOrEmpHandler, Event}, CurStatus}),
case CmdOrEmpHandler of
'$infoNotify' ->
{NewEpmHers, IsHib} = doNotify(EpmHers, Event, handleEvent, false),
{NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmEvent, Event, IsHib);
EpmHandler ->
{NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, Event, handleInfo, false),
{NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleInfo, Event, false),
startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmInfo, Event, IsHib)
end.
@ -1996,13 +2009,16 @@ cancelTimer(TimeoutType, TimerRef, Timers) ->
%% Return a list of all pending timeouts
listTimeouts(Timers) ->
{
maps:size(Timers),
maps:fold(
fun(TimeoutType, {_TimerRef, TimeoutMsg}, Acc) ->
[{TimeoutType, TimeoutMsg} | Acc]
end, [], Timers)
}.
{maps:size(Timers), allTimer(maps:iterator(Timers), [])}.
allTimer(Iterator, Acc) ->
case maps:next(Iterator) of
{TimeoutType, {_TimerRef, TimeoutMsg}, NextIterator} ->
allTimer(NextIterator, [{TimeoutType, TimeoutMsg} | Acc]);
none ->
Acc
end.
%%---------------------------------------------------------------------------
terminate(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents) ->

Načítá se…
Zrušit
Uložit