1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(gen_event).
21
22%%%
23%%% A general event handler.
24%%% Several handlers (functions) can be added.
25%%% Each handler holds a state and will be called
26%%% for every event received of the handler.
27%%%
28
29%%% Modified by Magnus.
30%%%       Take care of fault situations and made notify asynchronous.
31%%% Re-written by Joe with new functional interface !
32%%% Modified by Martin - uses proc_lib, sys and gen!
33
34%%%
35%%% NOTE: If init_ack() return values are modified, see comment
36%%%       above monitor_return() in gen.erl!
37%%%
38
39-export([start/0, start/1, start/2,
40         start_link/0, start_link/1, start_link/2,
41         start_monitor/0, start_monitor/1, start_monitor/2,
42         stop/1, stop/3,
43	 notify/2, sync_notify/2,
44	 add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3,
45	 swap_sup_handler/3, which_handlers/1, call/3, call/4,
46         send_request/3, wait_response/2, check_response/2,
47         wake_hib/5]).
48
49-export([init_it/6,
50	 system_continue/3,
51	 system_terminate/4,
52	 system_code_change/4,
53	 system_get_state/1,
54	 system_replace_state/2,
55	 format_status/2]).
56
57%% logger callback
58-export([format_log/1, format_log/2]).
59
60-export_type([handler/0, handler_args/0, add_handler_ret/0,
61              del_handler_ret/0]).
62
63-record(handler, {module             :: atom(),
64		  id = false,
65		  state,
66		  supervised = false :: 'false' | pid()}).
67
68-include("logger.hrl").
69
70%%%=========================================================================
71%%%  API
72%%%=========================================================================
73
74%% gen_event:start(Handler) -> {ok, Pid} | {error, What}
75%%   gen_event:add_handler(Handler, Mod, Args) -> ok | Other
76%%      gen_event:notify(Handler, Event) -> ok
77%%      gen_event:call(Handler, Mod, Query) -> {ok, Val} | {error, Why}
78%%      gen_event:call(Handler, Mod, Query, Timeout) -> {ok, Val} | {error, Why}
79%%   gen_event:delete_handler(Handler, Mod, Args) -> Val
80%%   gen_event:swap_handler(Handler, {OldMod, Args1}, {NewMod, Args2}) -> ok
81%%   gen_event:which_handler(Handler) -> [Mod]
82%% gen_event:stop(Handler) -> ok
83
84-callback init(InitArgs :: term()) ->
85    {ok, State :: term()} |
86    {ok, State :: term(), hibernate} |
87    {error, Reason :: term()}.
88-callback handle_event(Event :: term(), State :: term()) ->
89    {ok, NewState :: term()} |
90    {ok, NewState :: term(), hibernate} |
91    {swap_handler, Args1 :: term(), NewState :: term(),
92     Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
93    remove_handler.
94-callback handle_call(Request :: term(), State :: term()) ->
95    {ok, Reply :: term(), NewState :: term()} |
96    {ok, Reply :: term(), NewState :: term(), hibernate} |
97    {swap_handler, Reply :: term(), Args1 :: term(), NewState :: term(),
98     Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
99    {remove_handler, Reply :: term()}.
100-callback handle_info(Info :: term(), State :: term()) ->
101    {ok, NewState :: term()} |
102    {ok, NewState :: term(), hibernate} |
103    {swap_handler, Args1 :: term(), NewState :: term(),
104     Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
105    remove_handler.
106-callback terminate(Args :: (term() | {stop, Reason :: term()} |
107                             stop | remove_handler |
108                             {error, {'EXIT', Reason :: term()}} |
109                             {error, term()}),
110                    State :: term()) ->
111    term().
112-callback code_change(OldVsn :: (term() | {down, term()}),
113                      State :: term(), Extra :: term()) ->
114    {ok, NewState :: term()}.
115-callback format_status(Opt, StatusData) -> Status when
116      Opt :: 'normal' | 'terminate',
117      StatusData :: [PDict | State],
118      PDict :: [{Key :: term(), Value :: term()}],
119      State :: term(),
120      Status :: term().
121
122-optional_callbacks(
123    [handle_info/2, terminate/2, code_change/3, format_status/2]).
124
125%%---------------------------------------------------------------------------
126
127-type handler()          :: atom() | {atom(), term()}.
128-type handler_args()     :: term().
129-type add_handler_ret()  :: ok | term() | {'EXIT',term()}.
130-type del_handler_ret()  :: ok | term() | {'EXIT',term()}.
131
132-type emgr_name() :: {'local', atom()} | {'global', term()}
133                   | {'via', atom(), term()}.
134-type debug_flag() :: 'trace' | 'log' | 'statistics' | 'debug'
135                    | {'logfile', string()}.
136-type option() :: {'timeout', timeout()}
137                | {'debug', [debug_flag()]}
138                | {'spawn_opt', [proc_lib:start_spawn_option()]}
139                | {'hibernate_after', timeout()}.
140-type emgr_ref()  :: atom() | {atom(), atom()} |  {'global', term()}
141                   | {'via', atom(), term()} | pid().
142-type start_ret() :: {'ok', pid()} | {'error', term()}.
143-type start_mon_ret() :: {'ok', {pid(),reference()}} | {'error', term()}.
144-type request_id() :: term().
145
146%%---------------------------------------------------------------------------
147
148-define(NO_CALLBACK, 'no callback module').
149
150%% -----------------------------------------------------------------
151%% Starts a generic event handler.
152%% start()
153%% start(MgrName | Options)
154%% start(MgrName, Options)
155%% start_link()
156%% start_link(MgrName | Options)
157%% start_link(MgrName, Options)
158%%    MgrName ::= {local, atom()} | {global, term()} | {via, atom(), term()}
159%%    Options ::= [{timeout, Timeout} | {debug, [Flag]} | {spawn_opt,SOpts}]
160%%       Flag ::= trace | log | {logfile, File} | statistics | debug
161%%          (debug == log && statistics)
162%% Returns: {ok, Pid} |
163%%          {error, {already_started, Pid}} |
164%%          {error, Reason}
165%% -----------------------------------------------------------------
166
167-spec start() -> start_ret().
168start() ->
169    gen:start(?MODULE, nolink, ?NO_CALLBACK, [], []).
170
171-spec start(emgr_name() | [option()]) -> start_ret().
172start(Name) when is_tuple(Name) ->
173    gen:start(?MODULE, nolink, Name, ?NO_CALLBACK, [], []);
174start(Options) when is_list(Options) ->
175    gen:start(?MODULE, nolink, ?NO_CALLBACK, [], Options).
176
177-spec start(emgr_name(), [option()]) -> start_ret().
178start(Name, Options) ->
179    gen:start(?MODULE, nolink, Name, ?NO_CALLBACK, [], Options).
180
181-spec start_link() -> start_ret().
182start_link() ->
183    gen:start(?MODULE, link, ?NO_CALLBACK, [], []).
184
185-spec start_link(emgr_name() | [option()]) -> start_ret().
186start_link(Name) when is_tuple(Name) ->
187    gen:start(?MODULE, link, Name, ?NO_CALLBACK, [], []);
188start_link(Options) when is_list(Options) ->
189    gen:start(?MODULE, link, ?NO_CALLBACK, [], Options).
190
191-spec start_link(emgr_name(), [option()]) -> start_ret().
192start_link(Name, Options) ->
193    gen:start(?MODULE, link, Name, ?NO_CALLBACK, [], Options).
194
195-spec start_monitor() -> start_mon_ret().
196start_monitor() ->
197    gen:start(?MODULE, monitor, ?NO_CALLBACK, [], []).
198
199-spec start_monitor(emgr_name() | [option()]) -> start_mon_ret().
200start_monitor(Name) when is_tuple(Name) ->
201    gen:start(?MODULE, monitor, Name, ?NO_CALLBACK, [], []);
202start_monitor(Options) when is_list(Options) ->
203    gen:start(?MODULE, monitor, ?NO_CALLBACK, [], Options).
204
205-spec start_monitor(emgr_name(), [option()]) -> start_mon_ret().
206start_monitor(Name, Options) ->
207    gen:start(?MODULE, monitor, Name, ?NO_CALLBACK, [], Options).
208
209%% -spec init_it(pid(), 'self' | pid(), emgr_name(), module(), [term()], [_]) ->
210init_it(Starter, self, Name, Mod, Args, Options) ->
211    init_it(Starter, self(), Name, Mod, Args, Options);
212init_it(Starter, Parent, Name0, _, _, Options) ->
213    process_flag(trap_exit, true),
214    Name = gen:name(Name0),
215    Debug = gen:debug_options(Name, Options),
216	HibernateAfterTimeout = gen:hibernate_after(Options),
217    proc_lib:init_ack(Starter, {ok, self()}),
218    loop(Parent, Name, [], HibernateAfterTimeout, Debug, false).
219
220-spec add_handler(emgr_ref(), handler(), term()) -> term().
221add_handler(M, Handler, Args) -> rpc(M, {add_handler, Handler, Args}).
222
223-spec add_sup_handler(emgr_ref(), handler(), term()) -> term().
224add_sup_handler(M, Handler, Args)  ->
225    rpc(M, {add_sup_handler, Handler, Args, self()}).
226
227-spec notify(emgr_ref(), term()) -> 'ok'.
228notify(M, Event) -> send(M, {notify, Event}).
229
230-spec sync_notify(emgr_ref(), term()) -> 'ok'.
231sync_notify(M, Event) -> rpc(M, {sync_notify, Event}).
232
233-spec call(emgr_ref(), handler(), term()) -> term().
234call(M, Handler, Query) -> call1(M, Handler, Query).
235
236-spec call(emgr_ref(), handler(), term(), timeout()) -> term().
237call(M, Handler, Query, Timeout) -> call1(M, Handler, Query, Timeout).
238
239-spec send_request(emgr_ref(), handler(), term()) -> request_id().
240send_request(M, Handler, Query) ->
241    gen:send_request(M, self(), {call, Handler, Query}).
242
243-spec wait_response(RequestId::request_id(), timeout()) ->
244        {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), emgr_ref()}}.
245wait_response(RequestId, Timeout) ->
246    case gen:wait_response(RequestId, Timeout) of
247        {reply, {error, _} = Err} -> Err;
248        Return -> Return
249    end.
250
251-spec check_response(Msg::term(), RequestId::request_id()) ->
252        {reply, Reply::term()} | 'no_reply' | {error, {Reason::term(), emgr_ref()}}.
253check_response(Msg, RequestId) ->
254    case gen:check_response(Msg, RequestId)  of
255        {reply, {error, _} = Err} -> Err;
256        Return -> Return
257    end.
258
259-spec delete_handler(emgr_ref(), handler(), term()) -> term().
260delete_handler(M, Handler, Args) -> rpc(M, {delete_handler, Handler, Args}).
261
262-spec swap_handler(emgr_ref(), {handler(), term()}, {handler(), term()}) ->
263	    'ok' | {'error', term()}.
264swap_handler(M, {H1, A1}, {H2, A2}) -> rpc(M, {swap_handler, H1, A1, H2, A2}).
265
266-spec swap_sup_handler(emgr_ref(), {handler(), term()}, {handler(), term()}) ->
267	    'ok' | {'error', term()}.
268swap_sup_handler(M, {H1, A1}, {H2, A2}) ->
269    rpc(M, {swap_sup_handler, H1, A1, H2, A2, self()}).
270
271-spec which_handlers(emgr_ref()) -> [handler()].
272which_handlers(M) -> rpc(M, which_handlers).
273
274-spec stop(emgr_ref()) -> 'ok'.
275stop(M) ->
276    gen:stop(M).
277
278stop(M, Reason, Timeout) ->
279    gen:stop(M, Reason, Timeout).
280
281rpc(M, Cmd) ->
282    {ok, Reply} = gen:call(M, self(), Cmd, infinity),
283    Reply.
284
285call1(M, Handler, Query) ->
286    Cmd = {call, Handler, Query},
287    try gen:call(M, self(), Cmd) of
288	{ok, Res} ->
289	    Res
290    catch
291	exit:Reason ->
292	    exit({Reason, {?MODULE, call, [M, Handler, Query]}})
293    end.
294
295call1(M, Handler, Query, Timeout) ->
296    Cmd = {call, Handler, Query},
297    try gen:call(M, self(), Cmd, Timeout) of
298	{ok, Res} ->
299	    Res
300    catch
301	exit:Reason ->
302	    exit({Reason, {?MODULE, call, [M, Handler, Query, Timeout]}})
303    end.
304
305send({global, Name}, Cmd) ->
306    catch global:send(Name, Cmd),
307    ok;
308send({via, Mod, Name}, Cmd) ->
309    catch Mod:send(Name, Cmd),
310    ok;
311send(M, Cmd) ->
312    M ! Cmd,
313    ok.
314
315loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true) ->
316     proc_lib:hibernate(?MODULE, wake_hib, [Parent, ServerName, MSL, HibernateAfterTimeout, Debug]);
317loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, _) ->
318    fetch_msg(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, false).
319
320wake_hib(Parent, ServerName, MSL, HibernateAfterTimeout, Debug) ->
321    fetch_msg(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true).
322
323fetch_msg(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib) ->
324    receive
325	{system, From, Req} ->
326	    sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
327				  [ServerName, MSL, HibernateAfterTimeout, Hib],Hib);
328	{'EXIT', Parent, Reason} ->
329	    terminate_server(Reason, Parent, MSL, ServerName);
330	Msg when Debug =:= [] ->
331	    handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, []);
332	Msg ->
333	    Debug1 = sys:handle_debug(Debug, fun print_event/3,
334				      ServerName, {in, Msg}),
335	    handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug1)
336    after HibernateAfterTimeout ->
337	    loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true)
338    end.
339
340handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug) ->
341    case Msg of
342	{notify, Event} ->
343	    {Hib,MSL1} = server_notify(Event, handle_event, MSL, ServerName),
344	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
345	{_From, Tag, {sync_notify, Event}} ->
346	    {Hib, MSL1} = server_notify(Event, handle_event, MSL, ServerName),
347	    reply(Tag, ok),
348	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
349	{'EXIT', From, Reason} ->
350	    MSL1 = handle_exit(From, Reason, MSL, ServerName),
351	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, false);
352	{_From, Tag, {call, Handler, Query}} ->
353	    {Hib, Reply, MSL1} = server_call(Handler, Query, MSL, ServerName),
354	    reply(Tag, Reply),
355	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
356	{_From, Tag, {add_handler, Handler, Args}} ->
357	    {Hib, Reply, MSL1} = server_add_handler(Handler, Args, MSL),
358	    reply(Tag, Reply),
359	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
360	{_From, Tag, {add_sup_handler, Handler, Args, SupP}} ->
361	    {Hib, Reply, MSL1} = server_add_sup_handler(Handler, Args, MSL, SupP),
362	    reply(Tag, Reply),
363	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
364	{_From, Tag, {delete_handler, Handler, Args}} ->
365	    {Reply, MSL1} = server_delete_handler(Handler, Args, MSL,
366						  ServerName),
367	    reply(Tag, Reply),
368	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, false);
369	{_From, Tag, {swap_handler, Handler1, Args1, Handler2, Args2}} ->
370	    {Hib, Reply, MSL1} = server_swap_handler(Handler1, Args1, Handler2,
371						     Args2, MSL, ServerName),
372	    reply(Tag, Reply),
373	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
374	{_From, Tag, {swap_sup_handler, Handler1, Args1, Handler2, Args2,
375		     Sup}} ->
376	    {Hib, Reply, MSL1} = server_swap_handler(Handler1, Args1, Handler2,
377						Args2, MSL, Sup, ServerName),
378	    reply(Tag, Reply),
379	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib);
380	{_From, Tag, stop} ->
381	    catch terminate_server(normal, Parent, MSL, ServerName),
382	    reply(Tag, ok);
383	{_From, Tag, which_handlers} ->
384	    reply(Tag, the_handlers(MSL)),
385	    loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, false);
386	{_From, Tag, get_modules} ->
387	    reply(Tag, get_modules(MSL)),
388	    loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, false);
389	Other  ->
390	    {Hib, MSL1} = server_notify(Other, handle_info, MSL, ServerName),
391	    loop(Parent, ServerName, MSL1, HibernateAfterTimeout, Debug, Hib)
392    end.
393
394terminate_server(Reason, Parent, MSL, ServerName) ->
395    stop_handlers(MSL, ServerName),
396    do_unlink(Parent, MSL),
397    exit(Reason).
398
399reply({From, Ref}, Msg) ->
400    From ! {Ref, Msg},
401    ok.
402
403%% unlink the supervisor process of all supervised handlers.
404%% We do not want a handler supervisor to EXIT due to the
405%% termination of the event manager (server).
406%% Do not unlink Parent !
407do_unlink(Parent, MSL) ->
408    lists:foreach(fun(Handler) when Handler#handler.supervised =:= Parent ->
409			  true;
410		     (Handler) when is_pid(Handler#handler.supervised) ->
411			  unlink(Handler#handler.supervised),
412			  true;
413		     (_) ->
414			  true
415		  end,
416		  MSL).
417
418%% First terminate the supervised (if exists) handlers and
419%% then inform other handlers.
420%% We do not know if any handler really is interested but it
421%% may be so !
422handle_exit(From, Reason, MSL, SName) ->
423    MSL1 = terminate_supervised(From, Reason, MSL, SName),
424    {_,MSL2}=server_notify({'EXIT', From, Reason}, handle_info, MSL1, SName),
425    MSL2.
426
427terminate_supervised(Pid, Reason, MSL, SName) ->
428    F = fun(Ha) when Ha#handler.supervised =:= Pid ->
429		do_terminate(Ha#handler.module,
430			     Ha,
431			     {stop,Reason},
432			     Ha#handler.state,
433			     {parent_terminated, {Pid,Reason}},
434			     SName,
435			     shutdown),
436		false;
437	   (_) ->
438		true
439	end,
440    lists:filter(F, MSL).
441
442%%-----------------------------------------------------------------
443%% Callback functions for system messages handling.
444%%-----------------------------------------------------------------
445system_continue(Parent, Debug, [ServerName, MSL, HibernateAfterTimeout, Hib]) ->
446    loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib).
447
448-spec system_terminate(_, _, _, [_]) -> no_return().
449system_terminate(Reason, Parent, _Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]) ->
450    terminate_server(Reason, Parent, MSL, ServerName).
451
452%%-----------------------------------------------------------------
453%% Module here is sent in the system msg change_code.  It specifies
454%% which module should be changed.
455%%-----------------------------------------------------------------
456system_code_change([ServerName, MSL, HibernateAfterTimeout, Hib], Module, OldVsn, Extra) ->
457    MSL1 = lists:zf(fun(H) when H#handler.module =:= Module ->
458			    {ok, NewState} =
459				Module:code_change(OldVsn,
460						   H#handler.state, Extra),
461			    {true, H#handler{state = NewState}};
462		       (_) -> true
463		    end,
464		    MSL),
465    {ok, [ServerName, MSL1, HibernateAfterTimeout, Hib]}.
466
467system_get_state([_ServerName, MSL, _HibernateAfterTimeout, _Hib]) ->
468    {ok, [{Mod,Id,State} || #handler{module=Mod, id=Id, state=State} <- MSL]}.
469
470system_replace_state(StateFun, [ServerName, MSL, HibernateAfterTimeout, Hib]) ->
471    {NMSL, NStates} =
472		lists:unzip([begin
473				 Cur = {Mod,Id,State},
474				 try
475				     NState = {Mod,Id,NS} = StateFun(Cur),
476				     {HS#handler{state=NS}, NState}
477				 catch
478				     _:_ ->
479					 {HS, Cur}
480				 end
481			     end || #handler{module=Mod, id=Id, state=State}=HS <- MSL]),
482    {ok, NStates, [ServerName, NMSL, HibernateAfterTimeout, Hib]}.
483
484%%-----------------------------------------------------------------
485%% Format debug messages.  Print them as the call-back module sees
486%% them, not as the real erlang messages.  Use trace for that.
487%%-----------------------------------------------------------------
488print_event(Dev, {in, Msg}, Name) ->
489    case Msg of
490	{notify, Event} ->
491	    io:format(Dev, "*DBG* ~tp got event ~tp~n", [Name, Event]);
492	{_,_,{call, Handler, Query}} ->
493	    io:format(Dev, "*DBG* ~tp(~tp) got call ~tp~n",
494		      [Name, Handler, Query]);
495	_ ->
496	    io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg])
497    end;
498print_event(Dev, Dbg, Name) ->
499    io:format(Dev, "*DBG* ~tp : ~tp~n", [Name, Dbg]).
500
501
502%% server_add_handler(Handler, Args, MSL) -> {Ret, MSL'}.
503%%   where MSL = [#handler{}]
504%%   Ret goes to the top level MSL' is the new internal state of the
505%%   event handler
506
507server_add_handler({Mod,Id}, Args, MSL) ->
508    Handler = #handler{module = Mod,
509		       id = Id},
510    server_add_handler(Mod, Handler, Args, MSL);
511server_add_handler(Mod, Args, MSL) ->
512    Handler = #handler{module = Mod},
513    server_add_handler(Mod, Handler, Args, MSL).
514
515server_add_handler(Mod, Handler, Args, MSL) ->
516    case catch Mod:init(Args) of
517        {ok, State} ->
518	    {false, ok, [Handler#handler{state = State}|MSL]};
519        {ok, State, hibernate} ->
520	    {true, ok, [Handler#handler{state = State}|MSL]};
521        Other ->
522            {false, Other, MSL}
523    end.
524
525%% Set up a link to the supervising process.
526%% (Ought to be unidirected links here, Erl5.0 !!)
527%% NOTE: This link will not be removed then the
528%% handler is removed in case another handler has
529%% own link to this process.
530server_add_sup_handler({Mod,Id}, Args, MSL, Parent) ->
531    link(Parent),
532    Handler = #handler{module = Mod,
533		       id = Id,
534		       supervised = Parent},
535    server_add_handler(Mod, Handler, Args, MSL);
536server_add_sup_handler(Mod, Args, MSL, Parent) ->
537    link(Parent),
538    Handler = #handler{module = Mod,
539		       supervised = Parent},
540    server_add_handler(Mod, Handler, Args, MSL).
541
542%% server_delete_handler(HandlerId, Args, MSL) -> {Ret, MSL'}
543
544server_delete_handler(HandlerId, Args, MSL, SName) ->
545    case split(HandlerId, MSL) of
546	{Mod, Handler, MSL1} ->
547	    {do_terminate(Mod, Handler, Args,
548			  Handler#handler.state, delete, SName, normal),
549	     MSL1};
550	error ->
551	    {{error, module_not_found}, MSL}
552    end.
553
554%% server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, SN) -> MSL'
555%% server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, Sup, SN) -> MSL'
556
557server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, SName) ->
558    {State2, Sup, MSL1} = split_and_terminate(Handler1, Args1, MSL,
559					      SName, Handler2, false),
560    case s_s_h(Sup, Handler2, {Args2, State2}, MSL1) of
561	{Hib, ok, MSL2} ->
562	    {Hib, ok, MSL2};
563	{Hib, What, MSL2} ->
564	    {Hib, {error, What}, MSL2}
565    end.
566
567server_swap_handler(Handler1, Args1, Handler2, Args2, MSL, Sup, SName) ->
568    {State2, _, MSL1} = split_and_terminate(Handler1, Args1, MSL,
569					    SName, Handler2, Sup),
570    case s_s_h(Sup, Handler2, {Args2, State2}, MSL1) of
571	{Hib, ok, MSL2} ->
572	    {Hib, ok, MSL2};
573	{Hib, What, MSL2} ->
574	    {Hib, {error, What}, MSL2}
575    end.
576
577s_s_h(false, Handler, Args, MSL) ->
578    server_add_handler(Handler, Args, MSL);
579s_s_h(Pid, Handler, Args, MSL) ->
580    server_add_sup_handler(Handler, Args, MSL, Pid).
581
582split_and_terminate(HandlerId, Args, MSL, SName, Handler2, Sup) ->
583    case split(HandlerId, MSL) of
584	{Mod, Handler, MSL1} ->
585	    OldSup = Handler#handler.supervised,
586	    NewSup = if
587			 not Sup -> OldSup;
588			 true    -> Sup
589		     end,
590	    {do_terminate(Mod, Handler, Args,
591			  Handler#handler.state, swapped, SName,
592			  {swapped, Handler2, NewSup}),
593	     OldSup,
594	     MSL1};
595	error ->
596            {error, false, MSL}
597    end.
598
599%% server_notify(Event, Func, MSL, SName) -> MSL'
600
601server_notify(Event, Func, [Handler|T], SName) ->
602    case server_update(Handler, Func, Event, SName) of
603	{ok, Handler1} ->
604	    {Hib, NewHandlers} = server_notify(Event, Func, T, SName),
605	    {Hib, [Handler1|NewHandlers]};
606	{hibernate, Handler1} ->
607	    {_Hib, NewHandlers} = server_notify(Event, Func, T, SName),
608	    {true, [Handler1|NewHandlers]};
609	no ->
610	    server_notify(Event, Func, T, SName)
611    end;
612server_notify(_, _, [], _) ->
613    {false, []}.
614
615%% server_update(Handler, Func, Event, ServerName) -> Handler1 | no
616
617server_update(Handler1, Func, Event, SName) ->
618    Mod1 = Handler1#handler.module,
619    State = Handler1#handler.state,
620    case catch Mod1:Func(Event, State) of
621	{ok, State1} ->
622	    {ok, Handler1#handler{state = State1}};
623	{ok, State1, hibernate} ->
624	    {hibernate, Handler1#handler{state = State1}};
625	{swap_handler, Args1, State1, Handler2, Args2} ->
626	    do_swap(Mod1, Handler1, Args1, State1, Handler2, Args2, SName);
627	remove_handler ->
628	    do_terminate(Mod1, Handler1, remove_handler, State,
629			 remove, SName, normal),
630	    no;
631        {'EXIT', {undef, [{Mod1, handle_info, [_,_], _}|_]}} ->
632            ?LOG_WARNING(#{label=>{gen_event,no_handle_info},
633                           module=>Mod1,
634                           message=>Event},
635                         #{domain=>[otp],
636                           report_cb=>fun gen_event:format_log/2,
637                           error_logger=>
638                               #{tag=>warning_msg, % warningmap??
639                                 report_cb=>fun gen_event:format_log/1}}),
640            {ok, Handler1};
641	Other ->
642	    do_terminate(Mod1, Handler1, {error, Other}, State,
643			 Event, SName, crash),
644	    no
645    end.
646
647do_swap(Mod1, Handler1, Args1, State1, Handler2, Args2, SName) ->
648    %% finalise the existing handler
649    State2 = do_terminate(Mod1, Handler1, Args1, State1,
650			  swapped, SName,
651			  {swapped, Handler2, Handler1#handler.supervised}),
652    {Mod2, Handler} = new_handler(Handler2, Handler1),
653    case catch Mod2:init({Args2, State2}) of
654	{ok, State2a} ->
655	    {ok, Handler#handler{state = State2a}};
656	Other ->
657	    report_terminate(Handler, crash, {error, Other}, SName, false),
658	    no
659    end.
660
661new_handler({Mod,Id}, Handler1) ->
662    {Mod, #handler{module = Mod,
663		   id = Id,
664		   supervised = Handler1#handler.supervised}};
665new_handler(Mod, Handler1) ->
666    {Mod, #handler{module = Mod,
667		   supervised = Handler1#handler.supervised}}.
668
669
670-spec split(handler(), [#handler{}]) ->
671	{atom(), #handler{}, [#handler{}]} | 'error'.
672
673split(Ha, MSL) -> split(Ha, MSL, []).
674
675split({Mod,Id}, [Ha|T], L) when Ha#handler.module =:= Mod,
676                                Ha#handler.id =:= Id ->
677    {Mod, Ha, lists:reverse(L, T)};
678split(Mod, [Ha|T], L) when Ha#handler.module =:= Mod,
679                           not Ha#handler.id ->
680    {Mod, Ha, lists:reverse(L, T)};
681split(Ha, [H|T], L) ->
682    split(Ha, T, [H|L]);
683split(_, [], _) ->
684    error.
685
686%% server_call(Handler, Query, MSL, ServerName) ->
687%%    {Reply, MSL1}
688
689server_call(Handler, Query, MSL, SName) ->
690    case search(Handler, MSL) of
691	{ok, Ha} ->
692	    case server_call_update(Ha, Query, SName) of
693		{no, Reply} ->
694		    {false, Reply, delete(Handler, MSL)};
695		{{ok, Ha1}, Reply} ->
696		    {false, Reply, replace(Handler, MSL, Ha1)};
697		{{hibernate, Ha1}, Reply} ->
698		    {true, Reply, replace(Handler, MSL, Ha1)}
699	    end;
700	false ->
701	    {false, {error, bad_module}, MSL}
702    end.
703
704search({Mod, Id}, [Ha|_MSL]) when Ha#handler.module =:= Mod,
705				  Ha#handler.id =:= Id ->
706    {ok, Ha};
707search(Mod, [Ha|_MSL]) when Ha#handler.module =:= Mod,
708			    not Ha#handler.id ->
709    {ok, Ha};
710search(Handler, [_|MSL]) ->
711    search(Handler, MSL);
712search(_, []) ->
713    false.
714
715delete({Mod, Id}, [Ha|MSL]) when Ha#handler.module =:= Mod,
716                                 Ha#handler.id =:= Id ->
717    MSL;
718delete(Mod, [Ha|MSL]) when Ha#handler.module =:= Mod,
719                           not Ha#handler.id ->
720    MSL;
721delete(Handler, [Ha|MSL]) ->
722    [Ha|delete(Handler, MSL)];
723delete(_, []) ->
724    [].
725
726replace({Mod, Id}, [Ha|MSL], NewHa) when Ha#handler.module =:= Mod,
727                                         Ha#handler.id =:= Id ->
728    [NewHa|MSL];
729replace(Mod, [Ha|MSL], NewHa) when Ha#handler.module =:= Mod,
730                                   not Ha#handler.id ->
731    [NewHa|MSL];
732replace(Handler, [Ha|MSL], NewHa) ->
733    [Ha|replace(Handler, MSL, NewHa)];
734replace(_, [], NewHa) ->
735    [NewHa].
736
737%% server_call_update(Handler, Query, ServerName) ->
738%%    {{Handler1, State1} | 'no', Reply}
739
740server_call_update(Handler1, Query, SName) ->
741    Mod1 = Handler1#handler.module,
742    State = Handler1#handler.state,
743    case catch Mod1:handle_call(Query, State) of
744	{ok, Reply, State1} ->
745	    {{ok, Handler1#handler{state = State1}}, Reply};
746	{ok, Reply, State1, hibernate} ->
747	    {{hibernate, Handler1#handler{state = State1}},
748	     Reply};
749	{swap_handler, Reply, Args1, State1, Handler2, Args2} ->
750	    {do_swap(Mod1,Handler1,Args1,State1,Handler2,Args2,SName), Reply};
751	{remove_handler, Reply} ->
752	    do_terminate(Mod1, Handler1, remove_handler, State,
753			 remove, SName, normal),
754	    {no, Reply};
755	Other ->
756	    do_terminate(Mod1, Handler1, {error, Other}, State,
757			 Query, SName, crash),
758	    {no, {error, Other}}
759    end.
760
761do_terminate(Mod, Handler, Args, State, LastIn, SName, Reason) ->
762    case erlang:function_exported(Mod, terminate, 2) of
763	true ->
764	    Res = (catch Mod:terminate(Args, State)),
765	    report_terminate(Handler, Reason, Args, State, LastIn, SName, Res),
766	    Res;
767	false ->
768	    report_terminate(Handler, Reason, Args, State, LastIn, SName, ok),
769	    ok
770    end.
771
772report_terminate(Handler, crash, {error, Why}, State, LastIn, SName, _) ->
773    report_terminate(Handler, Why, State, LastIn, SName);
774report_terminate(Handler, How, _, State, LastIn, SName, _) ->
775    %% How == normal | shutdown | {swapped, NewHandler, NewSupervisor}
776    report_terminate(Handler, How, State, LastIn, SName).
777
778report_terminate(Handler, Reason, State, LastIn, SName) ->
779    report_error(Handler, Reason, State, LastIn, SName),
780    case Handler#handler.supervised of
781	false ->
782	    ok;
783	Pid ->
784	    Pid ! {gen_event_EXIT,handler(Handler),Reason},
785	    ok
786    end.
787
788report_error(_Handler, normal, _, _, _)             -> ok;
789report_error(_Handler, shutdown, _, _, _)           -> ok;
790report_error(_Handler, {swapped,_,_}, _, _, _)      -> ok;
791report_error(Handler, Reason, State, LastIn, SName) ->
792    ?LOG_ERROR(#{label=>{gen_event,terminate},
793                 handler=>handler(Handler),
794                 name=>SName,
795                 last_message=>LastIn,
796                 state=>format_status(terminate,Handler#handler.module,
797                                      get(),State),
798                 reason=>Reason},
799               #{domain=>[otp],
800                 report_cb=>fun gen_event:format_log/2,
801                 error_logger=>#{tag=>error,
802                                 report_cb=>fun gen_event:format_log/1}}).
803
804%% format_log/1 is the report callback used by Logger handler
805%% error_logger only. It is kept for backwards compatibility with
806%% legacy error_logger event handlers. This function must always
807%% return {Format,Args} compatible with the arguments in this module's
808%% calls to error_logger prior to OTP-21.0.
809format_log(Report) ->
810    Depth = error_logger:get_format_depth(),
811    FormatOpts = #{chars_limit => unlimited,
812                   depth => Depth,
813                   single_line => false,
814                   encoding => utf8},
815    format_log_multi(limit_report(Report, Depth), FormatOpts).
816
817limit_report(Report, unlimited) ->
818    Report;
819limit_report(#{label:={gen_event,terminate},
820               last_message:=LastIn,
821               state:=State,
822               reason:=Reason}=Report,
823             Depth) ->
824    Report#{last_message => io_lib:limit_term(LastIn, Depth),
825            state => io_lib:limit_term(State, Depth),
826            reason => io_lib:limit_term(Reason, Depth)};
827limit_report(#{label:={gen_event,no_handle_info},
828               message:=Msg}=Report,
829             Depth) ->
830    Report#{message => io_lib:limit_term(Msg, Depth)}.
831
832%% format_log/2 is the report callback for any Logger handler, except
833%% error_logger.
834format_log(Report, FormatOpts0) ->
835    Default = #{chars_limit => unlimited,
836                depth => unlimited,
837                single_line => false,
838                encoding => utf8},
839    FormatOpts = maps:merge(Default, FormatOpts0),
840    IoOpts =
841        case FormatOpts of
842            #{chars_limit:=unlimited} ->
843                [];
844            #{chars_limit:=Limit} ->
845                [{chars_limit,Limit}]
846        end,
847    {Format,Args} = format_log_single(Report, FormatOpts),
848    io_lib:format(Format, Args, IoOpts).
849
850format_log_single(#{label:={gen_event,terminate},
851                    handler:=Handler,
852                    name:=SName,
853                    last_message:=LastIn,
854                    state:=State,
855                    reason:=Reason},
856                  #{single_line:=true, depth:=Depth}=FormatOpts) ->
857    P = p(FormatOpts),
858    Reason1 = fix_reason(Reason),
859    Format1 = lists:append(["Generic event handler ",P," crashed. "
860                            "Installed: ",P,". Last event: ",P,
861                            ". State: ",P,". Reason: ",P,"."]),
862    Args1 =
863        case Depth of
864            unlimited ->
865                [Handler,SName,Reason1,LastIn,State];
866            _ ->
867                [Handler,Depth,SName,Depth,Reason1,Depth,
868                 LastIn,Depth,State,Depth]
869        end,
870    {Format1, Args1};
871format_log_single(#{label:={gen_event,no_handle_info},
872                    module:=Mod,
873                    message:=Msg},
874                  #{single_line:=true,depth:=Depth}=FormatOpts) ->
875    P = p(FormatOpts),
876    Format = lists:append(["Undefined handle_info in ",P,
877                           ". Unhandled message: ",P,"."]),
878    Args =
879        case Depth of
880            unlimited ->
881                [Mod,Msg];
882            _ ->
883                [Mod,Depth,Msg,Depth]
884        end,
885    {Format,Args};
886format_log_single(Report,FormatOpts) ->
887    format_log_multi(Report,FormatOpts).
888
889format_log_multi(#{label:={gen_event,terminate},
890                   handler:=Handler,
891                   name:=SName,
892                   last_message:=LastIn,
893                   state:=State,
894                   reason:=Reason},
895                 #{depth:=Depth}=FormatOpts) ->
896    Reason1 = fix_reason(Reason),
897    P = p(FormatOpts),
898    Format =
899        lists:append(["** gen_event handler ",P," crashed.\n",
900                      "** Was installed in ",P,"\n",
901                      "** Last event was: ",P,"\n",
902                      "** When handler state == ",P,"\n",
903                      "** Reason == ",P,"\n"]),
904    Args =
905        case Depth of
906            unlimited ->
907                [Handler,SName,LastIn,State,Reason1];
908            _ ->
909                [Handler,Depth,SName,Depth,LastIn,Depth,State,Depth,
910                 Reason1,Depth]
911        end,
912    {Format,Args};
913format_log_multi(#{label:={gen_event,no_handle_info},
914                   module:=Mod,
915                   message:=Msg},
916                 #{depth:=Depth}=FormatOpts) ->
917    P = p(FormatOpts),
918    Format =
919        "** Undefined handle_info in ~p\n"
920        "** Unhandled message: "++P++"\n",
921    Args =
922        case Depth of
923            unlimited ->
924                [Mod,Msg];
925            _ ->
926                [Mod,Msg,Depth]
927        end,
928    {Format,Args}.
929
930fix_reason({'EXIT',{undef,[{M,F,A,_L}|_]=MFAs}=Reason}) ->
931    case code:is_loaded(M) of
932        false ->
933            {'module could not be loaded',MFAs};
934        _ ->
935            case erlang:function_exported(M, F, length(A)) of
936                true ->
937                    Reason;
938                false ->
939                    {'function not exported',MFAs}
940            end
941    end;
942fix_reason({'EXIT',Reason}) ->
943    Reason;
944fix_reason(Reason) ->
945    Reason.
946
947p(#{single_line:=Single,depth:=Depth,encoding:=Enc}) ->
948    "~"++single(Single)++mod(Enc)++p(Depth);
949p(unlimited) ->
950    "p";
951p(_Depth) ->
952    "P".
953
954single(true) -> "0";
955single(false) -> "".
956
957mod(latin1) -> "";
958mod(_) -> "t".
959
960handler(Handler) when not Handler#handler.id ->
961    Handler#handler.module;
962handler(Handler) ->
963    {Handler#handler.module, Handler#handler.id}.
964
965the_handlers(MSL) ->
966    [handler(Handler) || Handler <- MSL].
967
968%% stop_handlers(MSL, ServerName) -> []
969
970stop_handlers([Handler|T], SName) ->
971    Mod = Handler#handler.module,
972    do_terminate(Mod, Handler, stop, Handler#handler.state,
973		 stop, SName, shutdown),
974    stop_handlers(T, SName);
975stop_handlers([], _) ->
976    [].
977
978%% Message from the release_handler.
979%% The list of modules got to be a set, i.e. no duplicate elements!
980get_modules(MSL) ->
981    Mods = [Handler#handler.module || Handler <- MSL],
982    ordsets:to_list(ordsets:from_list(Mods)).
983
984%%-----------------------------------------------------------------
985%% Status information
986%%-----------------------------------------------------------------
987format_status(Opt, StatusData) ->
988    [PDict, SysState, Parent, _Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]] = StatusData,
989    Header = gen:format_status_header("Status for event handler",
990                                      ServerName),
991    FmtMSL = [MS#handler{state=format_status(Opt, Mod, PDict, State)}
992              || #handler{module = Mod, state = State} = MS <- MSL],
993    [{header, Header},
994     {data, [{"Status", SysState},
995	     {"Parent", Parent}]},
996     {items, {"Installed handlers", FmtMSL}}].
997
998format_status(Opt, Mod, PDict, State) ->
999    case erlang:function_exported(Mod, format_status, 2) of
1000        true ->
1001            Args = [PDict, State],
1002            case catch Mod:format_status(Opt, Args) of
1003                {'EXIT', _} -> State;
1004                Else -> Else
1005            end;
1006        false ->
1007            State
1008    end.
1009