erlang自动编译与加载
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2520 lines
112 KiB

  1. -module(es_gen_ipc).
  2. -compile(inline).
  3. -compile({inline_size, 128}).
  4. -include_lib("kernel/include/logger.hrl").
  5. -export([
  6. %% API for gen_server or gen_statem behaviour
  7. start/3, start/4, start_link/3, start_link/4
  8. , start_monitor/3, start_monitor/4
  9. , stop/1, stop/3
  10. , cast/2, send/2
  11. , abcast/2, abcast/3
  12. , call/2, call/3
  13. , send_request/2, wait_response/1, wait_response/2, receive_response/1, receive_response/2, check_response/2
  14. , multi_call/2, multi_call/3, multi_call/4
  15. , enter_loop/4, enter_loop/5, enter_loop/6
  16. , reply/1, reply/2
  17. %% API for gen_event behaviour
  18. , send_request/3
  19. , info_notify/2, call_notify/2
  20. , epm_call/3, epm_call/4, epm_info/3
  21. , add_epm/3, del_epm/3, add_sup_epm/3
  22. , swap_epm/3, swap_sup_epm/3
  23. , which_epm/1
  24. %% gen callbacks
  25. , init_it/6
  26. %% sys callbacks
  27. , system_continue/3
  28. , system_terminate/4
  29. , system_code_change/4
  30. , system_get_state/1
  31. , system_replace_state/2
  32. , format_status/2
  33. %% Internal callbacks
  34. , wakeupFromHib/12
  35. %% logger callback
  36. , format_log/1
  37. , format_log/2
  38. , epm_log/1
  39. ]).
  40. % 简写备注**********************************
  41. % isPostpone isPos
  42. % isHibernate isHib
  43. % nextEvent nextE
  44. % nextStatus nextS
  45. % keepStatus kpS
  46. % keepStatusState kpS_S
  47. % repeatStatus reS
  48. % repeatStatusState reS_S
  49. % *****************************************
  50. % %% timeout相关宏定义
  51. % -define(REL_TIMEOUT(T), ((is_integer(T) andalso (T) >= 0) orelse (T) =:= infinity)).
  52. % -define(ABS_TIMEOUT(T), (is_integer(T) orelse (T) =:= infinity)).
  53. -define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))).
  54. -define(CB_FORM_ENTER, 1). %% 从enter 回调返回
  55. -define(CB_FORM_AFTER, 2). %% 从after 回调返回
  56. -define(CB_FORM_EVENT, 3). %% 从event 回调返回
  57. %% debug 调试相关宏定义
  58. -define(NOT_DEBUG, []).
  59. -define(SYS_DEBUG(Debug, Name, SystemEvent),
  60. case Debug of
  61. ?NOT_DEBUG ->
  62. Debug;
  63. _ ->
  64. sys:handle_debug(Debug, fun print_event/3, Name, SystemEvent)
  65. end).
  66. %%%==========================================================================
  67. %%% Interface functions.
  68. %%%==========================================================================
  69. %% gen:call 发送消息来源进程格式类型
  70. -type from() :: {To :: pid(), Tag :: term()}.
  71. -type requestId() :: term().
  72. %% 事件类型
  73. -type eventType() :: externalEventType() | timeoutEventType() | {'onevent', Subtype :: term()}.
  74. -type externalEventType() :: {'call', From :: from()} | 'cast' | 'info'.
  75. -type timeoutEventType() :: GTimeoutName :: term() | 'eTimeout' | 'sTimeout'. %% 前面的GTimeoutName这个是通用超时标识名
  76. %% 是否捕捉信号 gen_event管理进程需要设置该参数为true
  77. -type isTrapExit() :: boolean().
  78. %% 是否允许进入enter 回调
  79. -type isEnter() :: boolean().
  80. %% 如果为 "true" 则推迟当前事件,并在状态更改时重试(=/=)
  81. -type isPos() :: boolean().
  82. %% 如果为 "true" 则使服务器休眠而不是进入接收状态
  83. -type isHib() :: boolean().
  84. %% 定时器相关
  85. -type timeouts() :: Time :: timeout() | integer().
  86. -type timeoutOption() :: {abs, Abs :: boolean()}.
  87. % gen_event模式下回调模块的标识
  88. -type epmHandler() :: atom() | {atom(), term()}.
  89. %% 在状态更改期间:
  90. %% NextStatus and NewData are set.
  91. %% 按照出现的顺序处理 actions()列表
  92. %% 这些action() 按包含列表中的出现顺序执行。设置选项的选项将覆盖任何以前的选项,因此每种类型的最后一种将获胜。
  93. %% 如果设置了enter 则进入enter回调
  94. %% 如果设置了doAfter 则进入after回调
  95. %% 如果 "postpone" 为 "true",则推迟当前事件。
  96. %% 如果设置了“超时”,则开始状态超时。 零超时事件将会插入到待处理事件的前面 先执行
  97. %% 如果有postponed 事件则 事件执行顺序为 超时添加和更新 + 零超时 + 当前事件 + 反序的Postpone事件 + LeftEvent
  98. %% 处理待处理的事件,或者如果没有待处理的事件,则服务器进入接收或休眠状态(当“hibernate”为“ true”时)
  99. -type initAction() ::
  100. {trap_exit, Bool :: isTrapExit()} | % 设置是否捕捉信息 主要用于gen_event模式下
  101. eventAction().
  102. -type eventAction() ::
  103. {'doAfter', Args :: term()} | % 设置执行某事件后是否回调 handleAfter
  104. {'isPos', Bool :: isPos()} | % 设置推迟选项
  105. {'nextE', EventType :: eventType(), EventContent :: term()} | % 插入事件作为下一个处理
  106. commonAction().
  107. -type afterAction() ::
  108. {'nextE', EventType :: eventType(), EventContent :: term()} | % 插入事件作为下一个处理
  109. commonAction().
  110. -type enterAction() ::
  111. {'isPos', false} | % 虽然enter action 不能设置postpone 但是可以取消之前event的设置
  112. commonAction().
  113. -type commonAction() ::
  114. {'isEnter', Bool :: isEnter()} |
  115. {'isHib', Bool :: isHib()} |
  116. timeoutAction() |
  117. replyAction().
  118. -type timeoutAction() ::
  119. timeoutNewAction() |
  120. timeoutCancelAction() |
  121. timeoutUpdateAction().
  122. -type timeoutNewAction() ::
  123. {'eTimeout', Time :: timeouts(), EventContent :: term()} | % Set the event_timeout option
  124. {'eTimeout', Time :: timeouts(), EventContent :: term(), Options :: ([timeoutOption()])} | % Set the event_timeout option
  125. {'sTimeout', Time :: timeouts(), EventContent :: term()} | % Set the status_timeout option
  126. {'sTimeout', Time :: timeouts(), EventContent :: term(), Options :: ([timeoutOption()])} | % Set the status_timeout option
  127. {'gTimeout', Name :: term(), Time :: timeouts(), EventContent :: term()} | % Set the generic_timeout option
  128. {'gTimeout', Name :: term(), Time :: timeouts(), EventContent :: term(), Options :: ([timeoutOption()])}. % Set the generic_timeout option
  129. -type timeoutCancelAction() ::
  130. 'c_eTimeout' | % 不可能也不需要更新此超时,因为任何其他事件都会自动取消它。
  131. 'c_sTimeout' |
  132. {'c_gTimeout', Name :: term()}.
  133. -type timeoutUpdateAction() ::
  134. {'u_eTimeout', EventContent :: term()} | % 不可能也不需要取消此超时,因为任何其他事件都会自动取消它。
  135. {'u_sTimeout', EventContent :: term()} |
  136. {'u_gTimeout', Name :: term(), EventContent :: term()}.
  137. -type actions(ActionType) ::
  138. ActionType |
  139. [ActionType, ...].
  140. -type replyAction() ::
  141. {'reply', From :: from(), Reply :: term()}.
  142. -type eventCallbackResult() ::
  143. {'reply', Reply :: term(), NewState :: term()} | % 用作gen_server模式时快速响应进入消息接收
  144. {'sreply', Reply :: term(), NextStatus :: term(), NewState :: term()} | % 用作gen_ipc模式便捷式返回reply 而不用把reply放在actions列表中
  145. {'noreply', NewState :: term()} | % 用作gen_server模式时快速响应进入消息接收
  146. {'reply', Reply :: term(), NewState :: term(), Options :: hibernate | {doAfter, Args}} | % 用作gen_server模式时快速响应进入消息接收
  147. {'sreply', Reply :: term(), NextStatus :: term(), NewState :: term(), Actions :: actions(eventAction())} | % 用作gen_ipc模式便捷式返回reply 而不用把reply放在actions列表中
  148. {'noreply', NewState :: term(), Options :: hibernate | {doAfter, Args}} | % 用作gen_server模式时快速响应进入循环
  149. {'nextS', NextStatus :: term(), NewState :: term()} | % {next_status,NextS,NewData,[]}
  150. {'nextS', NextStatus :: term(), NewState :: term(), Actions :: actions(eventAction())} | % Status transition, maybe to the same status
  151. commonCallbackResult(eventAction()).
  152. -type afterCallbackResult() ::
  153. {'nextS', NextStatus :: term(), NewState :: term()} | % {next_status,NextS,NewData,[]}
  154. {'nextS', NextStatus :: term(), NewState :: term(), Actions :: actions(afterAction())} | % Status transition, maybe to the same status
  155. {'noreply', NewState :: term()} | % 用作gen_server模式时快速响应进入消息接收
  156. {'noreply', NewState :: term(), Options :: hibernate} | % 用作gen_server模式时快速响应进入消息接收
  157. commonCallbackResult(afterAction()).
  158. -type enterCallbackResult() ::
  159. commonCallbackResult(enterAction()).
  160. -type commonCallbackResult(ActionType) ::
  161. {'kpS', NewState :: term()} | % {keep_status,NewData,[]}
  162. {'kpS', NewState :: term(), Actions :: actions(ActionType)} | % Keep status, change data
  163. 'kpS_S' | % {keep_status_and_data,[]}
  164. {'kpS_S', Actions :: [ActionType]} | % Keep status and data -> only actions
  165. {'reS', NewState :: term()} | % {repeat_status,NewData,[]}
  166. {'reS', NewState :: term(), Actions :: actions(ActionType)} | % Repeat status, change data
  167. 'reS_S' | % {repeat_status_and_data,[]}
  168. {'reS_S', Actions :: actions(ActionType)} | % Repeat status and data -> only actions
  169. 'stop' | % {stop,normal}
  170. {'stop', Reason :: term()} | % Stop the server
  171. {'stop', Reason :: term(), NewState :: term()} | % Stop the server
  172. {'stopReply', Reason :: term(), Replies :: replyAction() | [replyAction(), ...] | term()} | % Reply then stop the server
  173. {'stopReply', Reason :: term(), Replies :: replyAction() | [replyAction(), ...] | term(), NewState :: term()}. % Reply then stop the server
  174. %% 状态机的初始化功能函数
  175. %% 如果要模拟gen_server init返回定时时间 可以在Actions返回定时动作
  176. %% 如果要把改进程当做gen_event管理进程需要在actions列表包含 {trap_exit, true} 设置该进程捕捉异常
  177. -callback init(Args :: term()) ->
  178. 'ignore' |
  179. {'stop', Reason :: term()} |
  180. {'ok', State :: term()} |
  181. {'ok', Status :: term(), State :: term()} |
  182. {'ok', Status :: term(), State :: term(), Actions :: actions(initAction())}.
  183. %% 当 enter call 回调函数
  184. -callback handleEnter(OldStatus :: term(), CurStatus :: term(), State :: term()) ->
  185. enterCallbackResult().
  186. %% 当 init返回actions包含 doAfter 的时候会在 enter调用后 调用该函数 或者
  187. %% 在事件回调函数返回后 enter调用后调用该函数
  188. %% 该回调函数相当于 gen_server 的 handle_continue回调 但是在综合模式时 也可以生效
  189. -callback handleAfter(AfterArgs :: term(), Status :: term(), State :: term()) ->
  190. afterCallbackResult().
  191. %% call 所以状态的回调函数
  192. -callback handleCall(EventContent :: term(), Status :: term(), State :: term(), From :: {pid(), Tag :: term()}) ->
  193. eventCallbackResult().
  194. %% cast 回调函数
  195. -callback handleCast(EventContent :: term(), Status :: term(), State :: term()) ->
  196. eventCallbackResult().
  197. %% info 回调函数
  198. -callback handleInfo(EventContent :: term(), Status :: term(), State :: term()) ->
  199. eventCallbackResult().
  200. %% 内部事件 Onevent 包括actions 设置的定时器超时产生的事件 和 nextE产生的超时事件 但是不是 call cast info 回调函数 以及其他自定义定时事件 的回调函数
  201. %% 并且这里需要注意 其他erlang:start_timer生成超时事件发送的消息 不能和gen_ipc定时器关键字重合 有可能会导致一些问题
  202. -callback handleOnevent(EventType :: term(), EventContent :: term(), Status :: term(), State :: term()) ->
  203. eventCallbackResult().
  204. %% 在gen_event模式下 扩展了下面三个回调函数 考虑场景是:
  205. %% 比如游戏里的公会 有时候一个公会一个进程来管理可能开销比较高 只用一个进程来管理所以公会有可能一个进程处理不过来
  206. %% 这个时候可以考虑用gen_ipc来分组管理 一个gen_ipc进程管理 N 个公会 但是管理进程需要做一些数据保存什么 或者定时 就可能会用到下面的这些函数
  207. %% gen_event模式时 notify 有可能需要回调该管理进程的该函数
  208. -callback handleEpmEvent(EventContent :: term(), Status :: term(), State :: term()) ->
  209. eventCallbackResult().
  210. %% gen_event模式时 call请求 有可能需要回调该管理进程的该函数
  211. -callback handleEpmCall(EventContent :: term(), Status :: term(), State :: term()) ->
  212. eventCallbackResult().
  213. %% gen_event模式时 info消息 有可能需要回调该管理进程的该函数
  214. -callback handleEpmInfo(EventContent :: term(), Status :: term(), State :: term()) ->
  215. eventCallbackResult().
  216. %% 在服务器终止之前进行清理。
  217. -callback terminate(Reason :: 'normal' | 'shutdown' | {'shutdown', term()} | term(), Status :: term(), State :: term()) ->
  218. any().
  219. %% 代码更新回调函数
  220. -callback code_change(OldVsn :: term() | {'down', term()}, OldStatus :: term(), OldState :: term(), Extra :: term()) ->
  221. {ok, NewStatus :: term(), NewData :: term()} |
  222. (Reason :: term()).
  223. %% 以一种通常被精简的方式来格式化回调模块状态。
  224. %% 对于StatusOption =:= 'normal',首选返回 term 是[{data,[{"Status",FormattedStatus}]}]
  225. %% 对于StatusOption =:= 'terminate',它只是FormattedStatus
  226. -callback formatStatus(StatusOption, [PDict | term()]) ->
  227. Status :: term() when
  228. StatusOption :: 'normal' | 'terminate',
  229. PDict :: [{Key :: term(), Value :: term()}].
  230. -optional_callbacks([
  231. formatStatus/2
  232. , terminate/3
  233. , code_change/4
  234. , handleEnter/3
  235. , handleAfter/3
  236. , handleOnevent/4
  237. , handleEpmEvent/3
  238. , handleEpmCall/3
  239. , handleEpmInfo/3
  240. ]).
  241. -record(epmHer, {
  242. epmId = undefined :: term(),
  243. epmM :: atom(),
  244. epmSup = undefined :: 'undefined' | pid(),
  245. epmS :: term()
  246. }).
  247. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start stop API start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  248. -type serverName() ::
  249. {'local', atom()} |
  250. {'global', GlobalName :: term()} |
  251. {'via', RegMod :: module(), Name :: term()}.
  252. -type serverRef() ::
  253. pid() |
  254. (LocalName :: atom()) |
  255. {Name :: atom(), Node :: atom()} |
  256. {'global', GlobalName :: term()} |
  257. {'via', RegMod :: module(), ViaName :: term()}.
  258. -type startOpt() ::
  259. {'timeout', Time :: timeout()} |
  260. {'spawn_opt', [proc_lib:spawn_option()]} |
  261. enterLoopOpt().
  262. -type enterLoopOpt() ::
  263. {'debug', Debugs :: [sys:debug_option()]} |
  264. {'hibernate_after', HibernateAfterTimeout :: timeout()}.
  265. -type startRet() ::
  266. 'ignore' |
  267. {'ok', pid()} |
  268. {'ok', {pid(), reference()}} |
  269. {'error', term()}.
  270. -spec start(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  271. start(Module, Args, Opts) ->
  272. gen:start(?MODULE, nolink, Module, Args, Opts).
  273. -spec start(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  274. start(ServerName, Module, Args, Opts) ->
  275. gen:start(?MODULE, nolink, ServerName, Module, Args, Opts).
  276. -spec start_link(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  277. start_link(Module, Args, Opts) ->
  278. gen:start(?MODULE, link, Module, Args, Opts).
  279. -spec start_link(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  280. start_link(ServerName, Module, Args, Opts) ->
  281. gen:start(?MODULE, link, ServerName, Module, Args, Opts).
  282. %% Start and monitor
  283. -spec start_monitor(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  284. start_monitor(Module, Args, Opts) ->
  285. gen:start(?MODULE, monitor, Module, Args, Opts).
  286. -spec start_monitor(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  287. start_monitor(ServerName, Module, Args, Opts) ->
  288. gen:start(?MODULE, monitor, ServerName, Module, Args, Opts).
  289. -spec stop(ServerRef :: serverRef()) -> ok.
  290. stop(ServerRef) ->
  291. gen:stop(ServerRef).
  292. -spec stop(ServerRef :: serverRef(), Reason :: term(), Timeout :: timeout()) -> ok.
  293. stop(ServerRef, Reason, Timeout) ->
  294. gen:stop(ServerRef, Reason, Timeout).
  295. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start stop API end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  296. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen callbacks start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  297. doModuleInit(Module, Args) ->
  298. try
  299. Module:init(Args)
  300. catch
  301. throw:Ret -> Ret;
  302. Class:Reason:Stacktrace -> {'EXIT', Class, Reason, Stacktrace}
  303. end.
  304. init_it(Starter, self, ServerRef, Module, Args, Opts) ->
  305. init_it(Starter, self(), ServerRef, Module, Args, Opts);
  306. init_it(Starter, Parent, ServerRef, Module, Args, Opts) ->
  307. Name = gen:name(ServerRef),
  308. Debug = gen:debug_options(Name, Opts),
  309. HibernateAfterTimeout = gen:hibernate_after(Opts),
  310. case doModuleInit(Module, Args) of
  311. {ok, State} ->
  312. proc_lib:init_ack(Starter, {ok, self()}),
  313. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, undefined, State, []);
  314. {ok, Status, State} ->
  315. proc_lib:init_ack(Starter, {ok, self()}),
  316. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, Status, State, []);
  317. {ok, Status, State, Actions} ->
  318. proc_lib:init_ack(Starter, {ok, self()}),
  319. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, Status, State, listify(Actions));
  320. {stop, Reason} ->
  321. gen:unregister_name(ServerRef),
  322. proc_lib:init_ack(Starter, {error, Reason}),
  323. exit(Reason);
  324. ignore ->
  325. gen:unregister_name(ServerRef),
  326. proc_lib:init_ack(Starter, ignore),
  327. exit(normal);
  328. {'EXIT', Class, Reason, Stacktrace} ->
  329. gen:unregister_name(ServerRef),
  330. proc_lib:init_ack(Starter, {error, Reason}),
  331. error_info(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, fasle, #{}, [], #{}, '$un_init', '$un_init', Debug, []),
  332. erlang:raise(Class, Reason, Stacktrace);
  333. _Ret ->
  334. gen:unregister_name(ServerRef),
  335. Error = {'init_bad_return', _Ret},
  336. proc_lib:init_ack(Starter, {error, Error}),
  337. error_info(error, Error, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, fasle, #{}, [], #{}, '$un_init', '$un_init', Debug, []),
  338. exit(Error)
  339. end.
  340. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen callbacks end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  341. %% 进入循环 调用该进程必须使用proc_lib启动 且已经初始化状态和数据 包括注册名称
  342. %% 可以通过使用与从init / 1返回的参数相同的参数,而不是通过start / 3,4或start_link / 3,4启动状态机,而将当前由proc_lib启动的进程转换为状态机。
  343. -spec enter_loop(Module :: module(), Status :: term(), State :: term(), Opts :: [enterLoopOpt()]) -> no_return().
  344. enter_loop(Module, Status, State, Opts) ->
  345. enter_loop(Module, Status, State, Opts, self(), []).
  346. -spec enter_loop(Module :: module(), Status :: term(), State :: term(), Opts :: [enterLoopOpt()], ServerOrActions :: serverName() | pid() | actions(eventAction())) -> no_return().
  347. enter_loop(Module, Status, State, Opts, ServerOrActions) ->
  348. if
  349. is_list(ServerOrActions) ->
  350. enter_loop(Module, Status, State, Opts, self(), ServerOrActions);
  351. true ->
  352. enter_loop(Module, Status, State, Opts, ServerOrActions, [])
  353. end.
  354. -spec enter_loop(Module :: module(), Status :: term(), State :: term(), Opts :: [enterLoopOpt()], Server :: serverName() | pid(), Actions :: actions(eventAction())) -> no_return().
  355. enter_loop(Module, Status, State, Opts, ServerName, Actions) ->
  356. is_atom(Module) orelse error({atom, Module}),
  357. Parent = gen:get_parent(),
  358. Name = gen:get_proc_name(ServerName),
  359. Debug = gen:debug_options(Name, Opts),
  360. HibernateAfterTimeout = gen:hibernate_after(Opts),
  361. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, Status, State, Actions).
  362. %% 这里的 init_it/6 和 enter_loop/5,6,7 函数汇聚
  363. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, CurStatus, CurState, Actions) ->
  364. %% 如果该进程用于 gen_event 或者该进程需要捕捉退出信号 和 捕捉supervisor进程树的退出信息 则需要设置 process_flag(trap_exit, true) 需要在Actions返回 {trap_exit, true}
  365. MewActions =
  366. case lists:keyfind(trap_exit, 1, Actions) of
  367. false ->
  368. Actions;
  369. {trap_exit, true} ->
  370. process_flag(trap_exit, true),
  371. lists:keydelete(trap_exit, 1, Actions);
  372. _ ->
  373. lists:keydelete(trap_exit, 1, Actions)
  374. end,
  375. NewDebug = ?SYS_DEBUG(Debug, Name, {enter, CurStatus}),
  376. %% 强制执行{postpone,false}以确保我们的假事件被丢弃
  377. LastActions = MewActions ++ [{isPos, false}],
  378. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, false, #{}, [], #{}, CurStatus, CurState, CurStatus, NewDebug, [{onevent, init_status}], true, LastActions, ?CB_FORM_EVENT).
  379. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  380. system_continue(Parent, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}) ->
  381. if
  382. IsHib ->
  383. proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib]);
  384. true ->
  385. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib)
  386. end.
  387. system_terminate(Reason, Parent, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, _IsHib}) ->
  388. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, []).
  389. system_code_change({Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}, _Mod, OldVsn, Extra) ->
  390. case
  391. try Module:code_change(OldVsn, CurStatus, CurState, Extra)
  392. catch
  393. throw:Result -> Result;
  394. _C:_R -> {_R, _R}
  395. end
  396. of
  397. {ok, NewStatus, NewState} ->
  398. {ok, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, NewStatus, NewState, IsHib}};
  399. Error ->
  400. Error
  401. end.
  402. system_get_state({_Parent, _Name, _Module, _HibernateAfterTimeout, _IsEnter, _EpmHers, _Postponed, _Timers, CurStatus, CurState, _IsHib}) ->
  403. {ok, {CurStatus, CurState}}.
  404. system_replace_state(StatusFun, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}) ->
  405. {NewStatus, NewState} = StatusFun(CurStatus, CurState),
  406. {ok, {NewStatus, NewState}, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, NewStatus, NewState, IsHib}}.
  407. format_status(Opt, [PDict, SysStatus, Parent, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, _IsHib}]) ->
  408. Header = gen:format_status_header("Status for es_gen_ipc", Name),
  409. Log = sys:get_log(Debug),
  410. [
  411. {header, Header},
  412. {data,
  413. [
  414. {"Status", SysStatus},
  415. {"Parent", Parent},
  416. {"Time-outs", listTimeouts(Timers)},
  417. {"Logged Events", Log},
  418. {"Postponed", Postponed}
  419. ]
  420. } |
  421. case format_status(Opt, PDict, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState) of
  422. L when is_list(L) -> L;
  423. T -> [T]
  424. end
  425. ].
  426. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  427. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  428. -spec call(ServerRef :: serverRef(), Request :: term()) -> Reply :: term().
  429. call(ServerRef, Request) ->
  430. try gen:call(ServerRef, '$gen_call', Request) of
  431. {ok, Reply} ->
  432. Reply
  433. catch Class:Reason ->
  434. erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE())
  435. end.
  436. -spec call(ServerRef :: serverRef(), Request :: term(), Timeout :: timeout() |{'clean_timeout', T :: timeout()} | {'dirty_timeout', T :: timeout()}) -> Reply :: term().
  437. call(ServerRef, Request, infinity) ->
  438. try gen:call(ServerRef, '$gen_call', Request, infinity) of
  439. {ok, Reply} ->
  440. Reply
  441. catch Class:Reason ->
  442. erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request, infinity]}}, ?STACKTRACE())
  443. end;
  444. call(ServerRef, Request, {dirty_timeout, T} = Timeout) ->
  445. try gen:call(ServerRef, '$gen_call', Request, T) of
  446. {ok, Reply} ->
  447. Reply
  448. catch Class:Reason ->
  449. erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request, Timeout]}}, ?STACKTRACE())
  450. end;
  451. call(ServerRef, Request, {clean_timeout, T} = Timeout) ->
  452. callClean(ServerRef, Request, Timeout, T);
  453. call(ServerRef, Request, {_, _} = Timeout) ->
  454. erlang:error(badarg, [ServerRef, Request, Timeout]);
  455. call(ServerRef, Request, Timeout) ->
  456. callClean(ServerRef, Request, Timeout, Timeout).
  457. callClean(ServerRef, Request, Timeout, T) ->
  458. %% 通过代理过程呼叫服务器以躲避任何较晚的答复
  459. Ref = make_ref(),
  460. Self = self(),
  461. Pid = spawn(
  462. fun() ->
  463. Self !
  464. try gen:call(ServerRef, '$gen_call', Request, T) of
  465. Result ->
  466. {Ref, Result}
  467. catch Class:Reason ->
  468. {Ref, Class, Reason, ?STACKTRACE()}
  469. end
  470. end),
  471. Mref = monitor(process, Pid),
  472. receive
  473. {Ref, Result} ->
  474. demonitor(Mref, [flush]),
  475. case Result of
  476. {ok, Reply} ->
  477. Reply
  478. end;
  479. {Ref, Class, Reason, Stacktrace} ->
  480. demonitor(Mref, [flush]),
  481. erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request, Timeout]}}, Stacktrace);
  482. {'DOWN', Mref, _, _, Reason} ->
  483. %% 从理论上讲,有可能在try-of和!之间杀死代理进程。因此,在这种情况下
  484. exit(Reason)
  485. end.
  486. multi_call(Name, Request) when is_atom(Name) ->
  487. do_multi_call([node() | nodes()], Name, Request, infinity).
  488. multi_call(Nodes, Name, Request) when is_list(Nodes), is_atom(Name) ->
  489. do_multi_call(Nodes, Name, Request, infinity).
  490. multi_call(Nodes, Name, Request, infinity) ->
  491. do_multi_call(Nodes, Name, Request, infinity);
  492. multi_call(Nodes, Name, Request, Timeout) when is_list(Nodes), is_atom(Name), is_integer(Timeout), Timeout >= 0 ->
  493. do_multi_call(Nodes, Name, Request, Timeout).
  494. do_multi_call(Nodes, Name, Request, infinity) ->
  495. Tag = make_ref(),
  496. Monitors = send_nodes(Nodes, Name, Tag, Request),
  497. rec_nodes(Tag, Monitors, Name, undefined);
  498. do_multi_call(Nodes, Name, Request, Timeout) ->
  499. Tag = make_ref(),
  500. Caller = self(),
  501. Receiver = spawn(
  502. fun() ->
  503. process_flag(trap_exit, true),
  504. Mref = erlang:monitor(process, Caller),
  505. receive
  506. {Caller, Tag} ->
  507. Monitors = send_nodes(Nodes, Name, Tag, Request),
  508. TimerId = erlang:start_timer(Timeout, self(), ok),
  509. Result = rec_nodes(Tag, Monitors, Name, TimerId),
  510. exit({self(), Tag, Result});
  511. {'DOWN', Mref, _, _, _} ->
  512. exit(normal)
  513. end
  514. end
  515. ),
  516. Mref = erlang:monitor(process, Receiver),
  517. Receiver ! {self(), Tag},
  518. receive
  519. {'DOWN', Mref, _, _, {Receiver, Tag, Result}} ->
  520. Result;
  521. {'DOWN', Mref, _, _, Reason} ->
  522. exit(Reason)
  523. end.
  524. -spec cast(ServerRef :: serverRef(), Msg :: term()) -> ok.
  525. cast({global, Name}, Msg) ->
  526. try global:send(Name, {'$gen_cast', Msg}),
  527. ok
  528. catch _:_ -> ok
  529. end;
  530. cast({via, RegMod, Name}, Msg) ->
  531. try RegMod:send(Name, {'$gen_cast', Msg}),
  532. ok
  533. catch _:_ -> ok
  534. end;
  535. cast({Name, Node} = Dest, Msg) when is_atom(Name), is_atom(Node) ->
  536. try erlang:send(Dest, {'$gen_cast', Msg}),
  537. ok
  538. catch _:_ -> ok
  539. end;
  540. cast(Dest, Msg) ->
  541. try erlang:send(Dest, {'$gen_cast', Msg}),
  542. ok
  543. catch _:_ -> ok
  544. end.
  545. -spec send(ServerRef :: serverRef(), Msg :: term()) -> ok.
  546. send({global, Name}, Msg) ->
  547. try global:send(Name, Msg),
  548. ok
  549. catch _:_ -> ok
  550. end;
  551. send({via, RegMod, Name}, Msg) ->
  552. try RegMod:send(Name, Msg),
  553. ok
  554. catch _:_ -> ok
  555. end;
  556. send({Name, Node} = Dest, Msg) when is_atom(Name), is_atom(Node) ->
  557. try erlang:send(Dest, Msg),
  558. ok
  559. catch _:_ -> ok
  560. end;
  561. send(Dest, Msg) ->
  562. try erlang:send(Dest, Msg),
  563. ok
  564. catch _:_ -> ok
  565. end.
  566. %% 异步广播,不返回任何内容,只是发送“ n”祈祷
  567. abcast(Name, Msg) when is_atom(Name) ->
  568. doAbcast([node() | nodes()], Name, Msg).
  569. abcast(Nodes, Name, Msg) when is_list(Nodes), is_atom(Name) ->
  570. doAbcast(Nodes, Name, Msg).
  571. doAbcast(Nodes, Name, Msg) ->
  572. [
  573. begin
  574. try erlang:send({Name, Node}, {'$gen_cast', Msg}),
  575. ok
  576. catch
  577. _:_ -> ok
  578. end
  579. end || Node <- Nodes
  580. ],
  581. ok.
  582. -spec send_request(ServerRef :: serverRef(), Request :: term()) -> RequestId :: requestId().
  583. send_request(Name, Request) ->
  584. gen:send_request(Name, '$gen_call', Request).
  585. %% gen_event send_request/3
  586. -spec send_request(ServerRef :: serverRef(), epmHandler(), term()) -> requestId().
  587. send_request(Name, Handler, Query) ->
  588. gen:send_request(Name, self(), {call, Handler, Query}).
  589. -spec wait_response(RequestId :: requestId()) -> {reply, Reply :: term()} | {error, {term(), serverRef()}}.
  590. wait_response(RequestId) ->
  591. gen:wait_response(RequestId, infinity).
  592. -spec wait_response(RequestId :: requestId(), timeout()) -> {reply, Reply :: term()} | 'timeout' | {error, {term(), serverRef()}}.
  593. wait_response(RequestId, Timeout) ->
  594. gen:wait_response(RequestId, Timeout).
  595. -spec receive_response(RequestId::serverRef()) -> {reply, Reply::term()} | {error, {term(), serverRef()}}.
  596. receive_response(RequestId) ->
  597. gen:receive_response(RequestId, infinity).
  598. -spec receive_response(RequestId::requestId(), timeout()) -> {reply, Reply::term()} | 'timeout' | {error, {term(), serverRef()}}.
  599. receive_response(RequestId, Timeout) ->
  600. gen:receive_response(RequestId, Timeout).
  601. -spec check_response(Msg :: term(), RequestId :: requestId()) ->
  602. {reply, Reply :: term()} | 'no_reply' | {error, {term(), serverRef()}}.
  603. check_response(Msg, RequestId) ->
  604. gen:check_response(Msg, RequestId).
  605. send_nodes(Nodes, Name, Tag, Request) ->
  606. [
  607. begin
  608. Monitor = start_monitor(Node, Name),
  609. try {Name, Node} ! {'$gen_call', {self(), {Tag, Node}}, Request},
  610. ok
  611. catch _:_ -> ok
  612. end,
  613. Monitor
  614. end || Node <- Nodes, is_atom(Node)
  615. ].
  616. rec_nodes(Tag, Nodes, Name, TimerId) ->
  617. rec_nodes(Tag, Nodes, Name, [], [], 2000, TimerId).
  618. rec_nodes(Tag, [{N, R} | Tail], Name, BadNodes, Replies, Time, TimerId) ->
  619. receive
  620. {'DOWN', R, _, _, _} ->
  621. rec_nodes(Tag, Tail, Name, [N | BadNodes], Replies, Time, TimerId);
  622. {{Tag, N}, Reply} ->
  623. erlang:demonitor(R, [flush]),
  624. rec_nodes(Tag, Tail, Name, BadNodes,
  625. [{N, Reply} | Replies], Time, TimerId);
  626. {timeout, TimerId, _} ->
  627. erlang:demonitor(R, [flush]),
  628. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  629. end;
  630. rec_nodes(Tag, [N | Tail], Name, BadNodes, Replies, Time, TimerId) ->
  631. receive
  632. {nodedown, N} ->
  633. monitor_node(N, false),
  634. rec_nodes(Tag, Tail, Name, [N | BadNodes], Replies, 2000, TimerId);
  635. {{Tag, N}, Reply} ->
  636. receive {nodedown, N} -> ok after 0 -> ok end,
  637. monitor_node(N, false),
  638. rec_nodes(Tag, Tail, Name, BadNodes,
  639. [{N, Reply} | Replies], 2000, TimerId);
  640. {timeout, TimerId, _} ->
  641. receive {nodedown, N} -> ok after 0 -> ok end,
  642. monitor_node(N, false),
  643. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  644. after Time ->
  645. case erpc:call(N, erlang, whereis, [Name]) of
  646. Pid when is_pid(Pid) ->
  647. rec_nodes(Tag, [N | Tail], Name, BadNodes,
  648. Replies, infinity, TimerId);
  649. _ ->
  650. receive {nodedown, N} -> ok after 0 -> ok end,
  651. monitor_node(N, false),
  652. rec_nodes(Tag, Tail, Name, [N | BadNodes],
  653. Replies, 2000, TimerId)
  654. end
  655. end;
  656. rec_nodes(_, [], _, BadNodes, Replies, _, TimerId) ->
  657. case catch erlang:cancel_timer(TimerId) of
  658. false ->
  659. receive
  660. {timeout, TimerId, _} -> ok
  661. after 0 ->
  662. ok
  663. end;
  664. _ ->
  665. ok
  666. end,
  667. {Replies, BadNodes}.
  668. rec_nodes_rest(Tag, [{N, R} | Tail], Name, BadNodes, Replies) ->
  669. receive
  670. {'DOWN', R, _, _, _} ->
  671. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies);
  672. {{Tag, N}, Reply} ->
  673. erlang:demonitor(R, [flush]),
  674. rec_nodes_rest(Tag, Tail, Name, BadNodes, [{N, Reply} | Replies])
  675. after 0 ->
  676. erlang:demonitor(R, [flush]),
  677. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  678. end;
  679. rec_nodes_rest(Tag, [N | Tail], Name, BadNodes, Replies) ->
  680. receive
  681. {nodedown, N} ->
  682. monitor_node(N, false),
  683. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies);
  684. {{Tag, N}, Reply} ->
  685. receive {nodedown, N} -> ok after 0 -> ok end,
  686. monitor_node(N, false),
  687. rec_nodes_rest(Tag, Tail, Name, BadNodes, [{N, Reply} | Replies])
  688. after 0 ->
  689. receive {nodedown, N} -> ok after 0 -> ok end,
  690. monitor_node(N, false),
  691. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  692. end;
  693. rec_nodes_rest(_Tag, [], _Name, BadNodes, Replies) ->
  694. {Replies, BadNodes}.
  695. start_monitor(Node, Name) when is_atom(Node), is_atom(Name) ->
  696. if node() =:= nonode@nohost, Node =/= nonode@nohost ->
  697. Ref = make_ref(),
  698. self() ! {'DOWN', Ref, process, {Name, Node}, noconnection},
  699. {Node, Ref};
  700. true ->
  701. case catch erlang:monitor(process, {Name, Node}) of
  702. {'EXIT', _} ->
  703. monitor_node(Node, true),
  704. Node;
  705. Ref when is_reference(Ref) ->
  706. {Node, Ref}
  707. end
  708. end.
  709. %% Reply from a status machine callback to whom awaits in call/2
  710. -spec reply([replyAction(), ...] | replyAction()) -> ok.
  711. reply({reply, {To, Tag}, Reply}) ->
  712. try To ! {Tag, Reply},
  713. ok
  714. catch _:_ ->
  715. ok
  716. end;
  717. reply(Replies) when is_list(Replies) ->
  718. [
  719. begin
  720. try To ! {Tag, Reply},
  721. ok
  722. catch _:_ ->
  723. ok
  724. end
  725. end || {reply, {To, Tag}, Reply} <- Replies
  726. ],
  727. ok.
  728. -spec reply(From :: from(), Reply :: term()) -> ok.
  729. reply({_To, [alias|Alias] = Tag}, Reply) ->
  730. Alias ! {Tag, Reply},
  731. ok;
  732. reply({To, Tag}, Reply) ->
  733. try To ! {Tag, Reply},
  734. ok
  735. catch _:_ ->
  736. ok
  737. end.
  738. try_reply(false, _Msg) ->
  739. ignore;
  740. try_reply({To, Ref}, Msg) ->
  741. try To ! {Ref, Msg},
  742. ok
  743. catch _:_ ->
  744. ok
  745. end.
  746. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  747. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_event start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  748. epmRequest({global, Name}, Msg) ->
  749. try global:send(Name, Msg),
  750. ok
  751. catch _:_ -> ok
  752. end;
  753. epmRequest({via, RegMod, Name}, Msg) ->
  754. try RegMod:send(Name, Msg),
  755. ok
  756. catch _:_ -> ok
  757. end;
  758. epmRequest(EpmSrv, Cmd) ->
  759. EpmSrv ! Cmd,
  760. ok.
  761. -spec epm_info(serverRef(), epmHandler(), term()) -> term().
  762. epm_info(EpmSrv, EpmHandler, Msg) ->
  763. epmRequest(EpmSrv, {'$epm_info', EpmHandler, Msg}).
  764. -spec info_notify(serverRef(), term()) -> 'ok'.
  765. info_notify(EpmSrv, Event) ->
  766. epmRequest(EpmSrv, {'$epm_info', '$infoNotify', Event}).
  767. epmRpc(EpmSrv, Cmd) ->
  768. try gen:call(EpmSrv, '$epm_call', Cmd, infinity) of
  769. {ok, Reply} ->
  770. Reply
  771. catch Class:Reason ->
  772. erlang:raise(Class, {Reason, {?MODULE, call, [EpmSrv, Cmd, infinity]}}, ?STACKTRACE())
  773. end.
  774. epmRpc(EpmSrv, Cmd, Timeout) ->
  775. try gen:call(EpmSrv, '$epm_call', Cmd, Timeout) of
  776. {ok, Reply} ->
  777. Reply
  778. catch Class:Reason ->
  779. erlang:raise(Class, {Reason, {?MODULE, call, [EpmSrv, Cmd, Timeout]}}, ?STACKTRACE())
  780. end.
  781. -spec call_notify(serverRef(), term()) -> 'ok'.
  782. call_notify(EpmSrv, Event) ->
  783. epmRpc(EpmSrv, {'$syncNotify', Event}).
  784. -spec epm_call(serverRef(), epmHandler(), term()) -> term().
  785. epm_call(EpmSrv, EpmHandler, Query) ->
  786. epmRpc(EpmSrv, {'$epmCall', EpmHandler, Query}).
  787. -spec epm_call(serverRef(), epmHandler(), term(), timeout()) -> term().
  788. epm_call(EpmSrv, EpmHandler, Query, Timeout) ->
  789. epmRpc(EpmSrv, {'$epmCall', EpmHandler, Query}, Timeout).
  790. -spec add_epm(serverRef(), epmHandler(), term()) -> term().
  791. add_epm(EpmSrv, EpmHandler, Args) ->
  792. epmRpc(EpmSrv, {'$addEpm', EpmHandler, Args}).
  793. -spec add_sup_epm(serverRef(), epmHandler(), term()) -> term().
  794. add_sup_epm(EpmSrv, EpmHandler, Args) ->
  795. epmRpc(EpmSrv, {'$addSupEpm', EpmHandler, Args, self()}).
  796. -spec del_epm(serverRef(), epmHandler(), term()) -> term().
  797. del_epm(EpmSrv, EpmHandler, Args) ->
  798. epmRpc(EpmSrv, {'$delEpm', EpmHandler, Args}).
  799. -spec swap_epm(serverRef(), {epmHandler(), term()}, {epmHandler(), term()}) -> 'ok' | {'error', term()}.
  800. swap_epm(EpmSrv, {H1, A1}, {H2, A2}) ->
  801. epmRpc(EpmSrv, {'$swapEpm', H1, A1, H2, A2}).
  802. -spec swap_sup_epm(serverRef(), {epmHandler(), term()}, {epmHandler(), term()}) -> 'ok' | {'error', term()}.
  803. swap_sup_epm(EpmSrv, {H1, A1}, {H2, A2}) ->
  804. epmRpc(EpmSrv, {'$swapSupEpm', H1, A1, H2, A2, self()}).
  805. -spec which_epm(serverRef()) -> [epmHandler()].
  806. which_epm(EpmSrv) ->
  807. epmRpc(EpmSrv, '$which_handlers').
  808. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  809. %% EPM inner fun
  810. addNewEpm(InitRet, EpmHers, Module, EpmId, EpmSup) ->
  811. case InitRet of
  812. {ok, State} ->
  813. EpmHer = #epmHer{epmId = EpmId, epmM = Module, epmS = State, epmSup = EpmSup},
  814. {ok, EpmHers#{EpmId => EpmHer}, false};
  815. {ok, State, hibernate} ->
  816. EpmHer = #epmHer{epmId = EpmId, epmM = Module, epmS = State, epmSup = EpmSup},
  817. {ok, EpmHers#{EpmId => EpmHer}, true};
  818. Other ->
  819. {Other, EpmHers, false}
  820. end.
  821. doAddEpm(EpmHers, {Module, _SubId} = EpmId, Args, EpmSup) ->
  822. case EpmHers of
  823. #{EpmId := _EpmHer} ->
  824. {{error, existed}, EpmHers, false};
  825. _ ->
  826. try Module:init(Args) of
  827. Result ->
  828. addNewEpm(Result, EpmHers, Module, EpmId, EpmSup)
  829. catch
  830. throw:Ret ->
  831. addNewEpm(Ret, EpmHers, Module, EpmId, EpmSup);
  832. C:R:S ->
  833. {{error, {C, R, S}}, EpmHers, false}
  834. end
  835. end;
  836. doAddEpm(EpmHers, Module, Args, EpmSup) ->
  837. case EpmHers of
  838. #{Module := _EpmHer} ->
  839. {{error, existed}, EpmHers, false};
  840. _ ->
  841. try Module:init(Args) of
  842. Result ->
  843. addNewEpm(Result, EpmHers, Module, Module, EpmSup)
  844. catch
  845. throw:Ret ->
  846. addNewEpm(Ret, EpmHers, Module, Module, EpmSup);
  847. C:R:S ->
  848. {{error, {C, R, S}}, EpmHers, false}
  849. end
  850. end.
  851. doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup) ->
  852. case doAddEpm(EpmHers, EpmHandler, Args, EpmSup) of
  853. {ok, _, _} = Result ->
  854. link(EpmSup),
  855. Result;
  856. Ret ->
  857. Ret
  858. end.
  859. doSwapEpm(EpmHers, EpmId1, Args1, EpmMId, Args2) ->
  860. case EpmHers of
  861. #{EpmId1 := #epmHer{epmSup = EpmSup} = EpmHer} ->
  862. State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
  863. NewEpmHers = maps:remove(EpmId1, EpmHers),
  864. case EpmSup of
  865. false ->
  866. doAddEpm(NewEpmHers, EpmMId, {Args2, State2}, undefined);
  867. _ ->
  868. doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup)
  869. end;
  870. undefined ->
  871. doAddEpm(EpmHers, EpmMId, {Args2, undefined}, undefined)
  872. end.
  873. doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
  874. case EpmHers of
  875. #{EpmId1 := EpmHer} ->
  876. State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
  877. NewEpmHers = maps:remove(EpmId1, EpmHers),
  878. doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup);
  879. undefined ->
  880. doAddSupEpm(EpmHers, EpmMId, {Args2, undefined}, EpmSup)
  881. end.
  882. doNotify(EpmHers, Func, Event, _Form) ->
  883. allNotify(maps:iterator(EpmHers), Func, Event, false, EpmHers, false).
  884. allNotify(Iterator, Func, Event, From, TemEpmHers, IsHib) ->
  885. case maps:next(Iterator) of
  886. {K, _V, NextIterator} ->
  887. {NewEpmHers, NewIsHib} = doEpmHandle(TemEpmHers, K, Func, Event, From),
  888. allNotify(NextIterator, Func, Event, From, NewEpmHers, IsHib orelse NewIsHib);
  889. _ ->
  890. {TemEpmHers, IsHib}
  891. end.
  892. doEpmHandle(EpmHers, EpmHandler, Func, Event, From) ->
  893. case EpmHers of
  894. #{EpmHandler := #epmHer{epmM = EpmM, epmS = EpmS} = EpmHer} ->
  895. try EpmM:Func(Event, EpmS) of
  896. Result ->
  897. handleEpmCR(Result, EpmHers, EpmHer, Event, From)
  898. catch
  899. throw:Ret ->
  900. handleEpmCR(Ret, EpmHers, EpmHer, Event, From);
  901. C:R:S ->
  902. epmTerminate(EpmHer, {error, {C, R, S}}, Event, crash),
  903. NewEpmHers = maps:remove(EpmHandler, EpmHers),
  904. {NewEpmHers, false}
  905. end;
  906. _ ->
  907. try_reply(From, {error, bad_module}),
  908. {EpmHers, false}
  909. end.
  910. doDelEpm(EpmHers, EpmHandler, Args) ->
  911. case EpmHers of
  912. #{EpmHandler := EpmHer} ->
  913. epmTerminate(EpmHer, Args, delete, normal),
  914. {ok, maps:remove(EpmHandler, EpmHers)};
  915. undefined ->
  916. {{error, module_not_found}, EpmHers}
  917. end.
  918. epmTerminate(#epmHer{epmM = EpmM, epmS = State} = EpmHer, Args, LastIn, Reason) ->
  919. case erlang:function_exported(EpmM, terminate, 2) of
  920. true ->
  921. Res = (catch EpmM:terminate(Args, State)),
  922. reportTerminate(EpmHer, Reason, Args, LastIn, Res),
  923. Res;
  924. false ->
  925. reportTerminate(EpmHer, Reason, Args, LastIn, ok),
  926. ok
  927. end.
  928. reportTerminate(EpmHer, crash, {error, Why}, LastIn, _) ->
  929. reportTerminate2(EpmHer, Why, LastIn);
  930. %% How == normal | shutdown | {swapped, NewHandler, NewSupervisor}
  931. reportTerminate(EpmHer, How, _, LastIn, _) ->
  932. reportTerminate2(EpmHer, How, LastIn).
  933. reportTerminate2(#epmHer{epmSup = EpmSup, epmId = EpmId, epmS = State} = EpmHer, Reason, LastIn) ->
  934. report_error(EpmHer, Reason, State, LastIn),
  935. case EpmSup of
  936. undefined ->
  937. ok;
  938. _ ->
  939. EpmSup ! {gen_event_EXIT, EpmId, Reason},
  940. ok
  941. end.
  942. report_error(_EpmHer, normal, _, _) -> ok;
  943. report_error(_EpmHer, shutdown, _, _) -> ok;
  944. report_error(_EpmHer, {swapped, _, _}, _, _) -> ok;
  945. report_error(#epmHer{epmId = EpmId, epmM = EpmM}, Reason, State, LastIn) ->
  946. ?LOG_ERROR(
  947. #{
  948. label=>{es_gen_ipc, epm_terminate},
  949. handler => {EpmId, EpmM},
  950. name => undefined,
  951. last_message => LastIn,
  952. state => State,
  953. reason => Reason
  954. },
  955. #{
  956. domain => [otp],
  957. report_cb => fun es_gen_ipc:epm_log/1,
  958. error_logger => #{tag => error}
  959. }).
  960. epm_log(#{label := {es_gen_ipc, epm_terminate}, handler := Handler, name := SName, last_message := LastIn, state := State, reason := Reason}) ->
  961. Reason1 =
  962. case Reason of
  963. {'EXIT', {undef, [{M, F, A, L} | MFAs]}} ->
  964. case code:is_loaded(M) of
  965. false ->
  966. {'module could not be loaded', [{M, F, A, L} | MFAs]};
  967. _ ->
  968. case erlang:function_exported(M, F, length(A)) of
  969. true ->
  970. {undef, [{M, F, A, L} | MFAs]};
  971. false ->
  972. {'function not exported', [{M, F, A, L} | MFAs]}
  973. end
  974. end;
  975. {'EXIT', Why} ->
  976. Why;
  977. _ ->
  978. Reason
  979. end,
  980. {"** es_gen_ipc emp handler ~p crashed.~n"
  981. "** Was installed in ~tp~n"
  982. "** Last event was: ~tp~n"
  983. "** When handler state == ~tp~n"
  984. "** Reason == ~tp~n", [Handler, SName, LastIn, State, Reason1]};
  985. epm_log(#{label := {es_gen_ipc, no_handle_info}, module := Module, message := Msg}) ->
  986. {"** Undefined handle_info in ~tp~n"
  987. "** Unhandled message: ~tp~n", [Module, Msg]}.
  988. epmStopAll(EpmHers) ->
  989. allStop(maps:iterator(EpmHers)).
  990. allStop(Iterator) ->
  991. case maps:next(Iterator) of
  992. {_K, V, NextIterator} ->
  993. epmTerminate(V, stop, 'receive', shutdown),
  994. case element(#epmHer.epmSup, V) of
  995. undefined ->
  996. ignore;
  997. EpmSup ->
  998. unlink(EpmSup)
  999. end,
  1000. allStop(NextIterator);
  1001. none ->
  1002. ok
  1003. end.
  1004. epmStopOne(ExitEmpSup, EpmHers) ->
  1005. forStopOne(maps:iterator(EpmHers), ExitEmpSup, EpmHers).
  1006. forStopOne(Iterator, ExitEmpSup, TemEpmHers) ->
  1007. case maps:next(Iterator) of
  1008. {K, V, NextIterator} ->
  1009. case element(#epmHer.epmSup, V) =:= ExitEmpSup of
  1010. true ->
  1011. epmTerminate(V, stop, 'receive', shutdown),
  1012. forStopOne(NextIterator, ExitEmpSup, maps:remove(K, TemEpmHers));
  1013. _ ->
  1014. forStopOne(NextIterator, ExitEmpSup, TemEpmHers)
  1015. end;
  1016. none ->
  1017. TemEpmHers
  1018. end.
  1019. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_event end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1020. listify(Item) when is_list(Item) ->
  1021. Item;
  1022. listify(Item) ->
  1023. [Item].
  1024. %%%==========================================================================
  1025. %%% Internal callbacks
  1026. wakeupFromHib(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib) ->
  1027. %% 这是一条新消息,唤醒了我们,因此我们必须立即收到它
  1028. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib).
  1029. %%%==========================================================================
  1030. %% Entry point for system_continue/3
  1031. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib) ->
  1032. if
  1033. IsHib ->
  1034. proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib]);
  1035. true ->
  1036. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib)
  1037. end.
  1038. %% 接收新的消息
  1039. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib) ->
  1040. receive
  1041. Msg ->
  1042. case Msg of
  1043. {'$gen_call', From, Request} ->
  1044. matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request);
  1045. {'$gen_cast', Cast} ->
  1046. matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Cast);
  1047. {timeout, TimerRef, TimeoutType} ->
  1048. case Timers of
  1049. #{TimeoutType := {TimerRef, TimeoutMsg}} ->
  1050. NewTimers = maps:remove(TimeoutType, Timers),
  1051. matchTimeoutMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, Debug, TimeoutType, TimeoutMsg);
  1052. _ ->
  1053. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg)
  1054. end;
  1055. {system, PidFrom, Request} ->
  1056. %% 不返回但尾递归调用 system_continue/3
  1057. sys:handle_system_msg(Request, PidFrom, Parent, ?MODULE, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}, IsHib);
  1058. {'EXIT', PidFrom, Reason} ->
  1059. case Parent =:= PidFrom of
  1060. true ->
  1061. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, []);
  1062. _ ->
  1063. NewEpmHers = epmStopOne(PidFrom, EpmHers),
  1064. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg)
  1065. end;
  1066. {'$epm_call', From, Request} ->
  1067. matchEpmCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request);
  1068. {'$epm_info', CmdOrEmpHandler, Event} ->
  1069. matchEpmInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, CmdOrEmpHandler, Event);
  1070. _ ->
  1071. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg)
  1072. end
  1073. after
  1074. HibernateAfterTimeout ->
  1075. proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib])
  1076. end.
  1077. matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request) ->
  1078. CurEvent = {{call, From}, Request},
  1079. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1080. try Module:handleCall(Request, CurStatus, CurState, From) of
  1081. Result ->
  1082. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, From)
  1083. catch
  1084. throw:Result ->
  1085. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, From);
  1086. Class:Reason:Strace ->
  1087. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1088. end.
  1089. matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Cast) ->
  1090. CurEvent = {cast, Cast},
  1091. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1092. try Module:handleCast(Cast, CurStatus, CurState) of
  1093. Result ->
  1094. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false)
  1095. catch
  1096. throw:Result ->
  1097. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false);
  1098. Class:Reason:Strace ->
  1099. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1100. end.
  1101. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg) ->
  1102. CurEvent = {info, Msg},
  1103. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1104. try Module:handleInfo(Msg, CurStatus, CurState) of
  1105. Result ->
  1106. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false)
  1107. catch
  1108. throw:Result ->
  1109. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false);
  1110. Class:Reason:Strace ->
  1111. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1112. end.
  1113. matchTimeoutMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, TimeoutType, TimeoutMsg) ->
  1114. CurEvent = {TimeoutType, TimeoutMsg},
  1115. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1116. try Module:handleOnevent(TimeoutType, TimeoutMsg, CurStatus, CurState) of
  1117. Result ->
  1118. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false)
  1119. catch
  1120. throw:Result ->
  1121. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false);
  1122. Class:Reason:Strace ->
  1123. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1124. end.
  1125. matchEpmCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request) ->
  1126. NewDebug = ?SYS_DEBUG(Debug, Name, {in, Request, CurStatus}),
  1127. case Request of
  1128. '$which_handlers' ->
  1129. reply(From, EpmHers);
  1130. {'$addEpm', EpmHandler, Args} ->
  1131. {Reply, NewEpmHers, IsHib} = doAddEpm(EpmHers, EpmHandler, Args, undefined),
  1132. reply(From, Reply),
  1133. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1134. {'$addSupEpm', EpmHandler, Args, EpmSup} ->
  1135. {Reply, NewEpmHers, IsHib} = doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup),
  1136. reply(From, Reply),
  1137. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1138. {'$delEpm', EpmHandler, Args} ->
  1139. {Reply, NewEpmHers} = doDelEpm(EpmHers, EpmHandler, Args),
  1140. reply(From, Reply),
  1141. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, false);
  1142. {'$swapEpm', EpmId1, Args1, EpmId2, Args2} ->
  1143. {Reply, NewEpmHers, IsHib} = doSwapEpm(EpmHers, EpmId1, Args1, EpmId2, Args2),
  1144. reply(From, Reply),
  1145. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1146. {'$swapSupEpm', EpmId1, Args1, EpmId2, Args2, SupPid} ->
  1147. {Reply, NewEpmHers, IsHib} = doSwapSupEpm(EpmHers, EpmId1, Args1, EpmId2, Args2, SupPid),
  1148. reply(From, Reply),
  1149. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1150. {'$syncNotify', Event} ->
  1151. {NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
  1152. reply(From, ok),
  1153. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmEvent, Request, IsHib);
  1154. {'$epmCall', EpmHandler, Query} ->
  1155. {NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleCall, Query, From),
  1156. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmCall, Request, IsHib)
  1157. end.
  1158. matchEpmInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, CmdOrEmpHandler, Event) ->
  1159. NewDebug = ?SYS_DEBUG(Debug, Name, {in, {CmdOrEmpHandler, Event}, CurStatus}),
  1160. case CmdOrEmpHandler of
  1161. '$infoNotify' ->
  1162. {NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
  1163. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmEvent, Event, IsHib);
  1164. EpmHandler ->
  1165. {NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleInfo, Event, false),
  1166. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmInfo, Event, IsHib)
  1167. end.
  1168. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, CallbackFun, Event, IsHib) ->
  1169. case erlang:function_exported(Module, CallbackFun, 3) of
  1170. true ->
  1171. NewDebug = ?SYS_DEBUG(Debug, Name, {in, Event, CurStatus}),
  1172. try Module:CallbackFun(Event, CurStatus, CurState) of
  1173. Result ->
  1174. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [Event], Result, ?CB_FORM_EVENT, false)
  1175. catch
  1176. throw:Ret ->
  1177. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [Event], Ret, ?CB_FORM_EVENT, false);
  1178. Class:Reason:Strace ->
  1179. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [Event])
  1180. end;
  1181. _ ->
  1182. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib)
  1183. end.
  1184. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter) ->
  1185. try Module:handleEnter(PrevStatus, CurStatus, CurState) of
  1186. Result ->
  1187. handleEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, Result)
  1188. catch
  1189. throw:Result ->
  1190. handleEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, Result);
  1191. Class:Reason:Strace ->
  1192. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1193. end.
  1194. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Args) ->
  1195. try Module:handleAfter(Args, CurStatus, CurState) of
  1196. Result ->
  1197. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_AFTER, false)
  1198. catch
  1199. throw:Result ->
  1200. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_AFTER, false);
  1201. Class:Reason:Strace ->
  1202. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1203. end.
  1204. startEventCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, {Type, Content}) ->
  1205. case Type of
  1206. 'cast' ->
  1207. try Module:handleCast(Content, CurStatus, CurState) of
  1208. Result ->
  1209. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, false)
  1210. catch
  1211. throw:Ret ->
  1212. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, false);
  1213. Class:Reason:Strace ->
  1214. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1215. end;
  1216. 'info' ->
  1217. try Module:handleInfo(Content, CurStatus, CurState) of
  1218. Result ->
  1219. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, false)
  1220. catch
  1221. throw:Ret ->
  1222. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, false);
  1223. Class:Reason:Strace ->
  1224. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1225. end;
  1226. {'call', From} ->
  1227. try Module:handleCall(Content, CurStatus, CurState, From) of
  1228. Result ->
  1229. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, From)
  1230. catch
  1231. throw:Ret ->
  1232. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, From);
  1233. Class:Reason:Strace ->
  1234. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1235. end;
  1236. _ ->
  1237. try Module:handleOnevent(Type, Content, CurStatus, CurState) of
  1238. Result ->
  1239. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, false)
  1240. catch
  1241. throw:Ret ->
  1242. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, false);
  1243. Class:Reason:Strace ->
  1244. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1245. end
  1246. end.
  1247. %% handleEpmCallbackRet
  1248. handleEpmCR(Result, EpmHers, #epmHer{epmId = EpmId} = EpmHer, Event, From) ->
  1249. case Result of
  1250. kpS ->
  1251. {EpmHers, false};
  1252. {ok, NewEpmS} ->
  1253. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1254. {EpmHers#{EpmId := MewEpmHer}, false};
  1255. {ok, NewEpmS, hibernate} ->
  1256. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1257. {EpmHers#{EpmId := MewEpmHer}, true};
  1258. {swapEpm, NewEpmS, Args1, EpmMId, Args2} ->
  1259. #epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1260. State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
  1261. TemEpmHers = maps:remove(EpmId, EpmHers),
  1262. {_, NewEpmHers, IsHib} =
  1263. case EpmSup of
  1264. undefined ->
  1265. doAddEpm(TemEpmHers, EpmMId, {Args2, State}, undefined);
  1266. _ ->
  1267. doAddSupEpm(TemEpmHers, EpmMId, {Args2, State}, EpmSup)
  1268. end,
  1269. {NewEpmHers, IsHib};
  1270. {swapEpm, Reply, NewEpmS, Args1, EpmMId, Args2} ->
  1271. reply(From, Reply),
  1272. #epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1273. State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
  1274. TemEpmHers = maps:remove(EpmId, EpmHers),
  1275. {_, NewEpmHers, IsHib} =
  1276. case EpmSup of
  1277. undefined ->
  1278. doAddEpm(TemEpmHers, EpmMId, {Args2, State}, undefined);
  1279. _ ->
  1280. doAddSupEpm(TemEpmHers, EpmMId, {Args2, State}, EpmSup)
  1281. end,
  1282. {NewEpmHers, IsHib};
  1283. removeEpm ->
  1284. epmTerminate(EpmHer, removeEpm, remove, normal),
  1285. {maps:remove(EpmId, EpmHers), false};
  1286. {removeEpm, Reply} ->
  1287. reply(From, Reply),
  1288. epmTerminate(EpmHer, removeEpm, remove, normal),
  1289. {maps:remove(EpmId, EpmHers), false};
  1290. {reply, Reply} ->
  1291. reply(From, Reply),
  1292. {EpmHers, false};
  1293. {reply, Reply, NewEpmS} ->
  1294. reply(From, Reply),
  1295. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1296. {EpmHers#{EpmId := MewEpmHer}, false};
  1297. {reply, Reply, NewEpmS, hibernate} ->
  1298. reply(From, Reply),
  1299. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1300. {EpmHers#{EpmId := MewEpmHer}, true};
  1301. Other ->
  1302. epmTerminate(EpmHer, {error, Other}, Event, crash),
  1303. {maps:remove(EpmId, EpmHers), false}
  1304. end.
  1305. %% handleEnterCallbackRet
  1306. handleEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, Result) ->
  1307. case Result of
  1308. {kpS, NewState} ->
  1309. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false);
  1310. {kpS, NewState, Actions} ->
  1311. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false, listify(Actions));
  1312. kpS_S ->
  1313. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false);
  1314. {kpS_S, Actions} ->
  1315. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false, listify(Actions));
  1316. {reS, NewState} ->
  1317. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true);
  1318. {reS, NewState, Actions} ->
  1319. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true, listify(Actions));
  1320. reS_S ->
  1321. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true);
  1322. {reS_S, Actions} ->
  1323. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true, listify(Actions));
  1324. stop ->
  1325. terminate(exit, normal, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1326. {stop, Reason} ->
  1327. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1328. {stop, Reason, NewState} ->
  1329. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, LeftEvents);
  1330. {stopReply, Reason, Replies} ->
  1331. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1332. try
  1333. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, LeftEvents)
  1334. after
  1335. case Replies of
  1336. {reply, RFrom, Reply} ->
  1337. reply(RFrom, Reply);
  1338. _ ->
  1339. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1340. ok
  1341. end
  1342. end;
  1343. {stopReply, Reason, Replies, NewState} ->
  1344. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1345. try
  1346. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, LeftEvents)
  1347. after
  1348. case Replies of
  1349. {reply, RFrom, Reply} ->
  1350. reply(RFrom, Reply);
  1351. _ ->
  1352. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1353. ok
  1354. end
  1355. end;
  1356. _ ->
  1357. terminate(error, {bad_handleEnterCR, Result}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1358. end.
  1359. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, CallbackForm, From) ->
  1360. case Result of
  1361. {noreply, NewState} ->
  1362. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, false);
  1363. {noreply, NewState, Option} ->
  1364. case Option of
  1365. hibernate ->
  1366. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, true);
  1367. {doAfter, Args} ->
  1368. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, [], Args);
  1369. _Ret ->
  1370. terminate(error, {bad_noreply, _Ret}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, [])
  1371. end;
  1372. {reply, Reply, NewState} ->
  1373. reply(From, Reply),
  1374. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1375. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, false);
  1376. {reply, Reply, NewState, Option} ->
  1377. reply(From, Reply),
  1378. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1379. case Option of
  1380. hibernate ->
  1381. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, true);
  1382. {doAfter, Args} ->
  1383. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, [], Args);
  1384. _Ret ->
  1385. terminate(error, {bad_reply, _Ret}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, [])
  1386. end;
  1387. {sreply, Reply, NewStatus, NewState} ->
  1388. reply(From, Reply),
  1389. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1390. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, NewDebug, LeftEvents, NewStatus =/= CurStatus);
  1391. {sreply, Reply, NewStatus, NewState, Actions} ->
  1392. reply(From, Reply),
  1393. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1394. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, NewDebug, LeftEvents, NewStatus =/= CurStatus, listify(Actions), CallbackForm);
  1395. {nextS, NewStatus, NewState} ->
  1396. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, Debug, LeftEvents, NewStatus =/= CurStatus);
  1397. {nextS, NewStatus, NewState, Actions} ->
  1398. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, Debug, LeftEvents, NewStatus =/= CurStatus, listify(Actions), CallbackForm);
  1399. {kpS, NewState} ->
  1400. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, false);
  1401. {kpS, NewState, Actions} ->
  1402. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, false, listify(Actions), CallbackForm);
  1403. kpS_S ->
  1404. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, false);
  1405. {kpS_S, Actions} ->
  1406. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, false, listify(Actions), CallbackForm);
  1407. {reS, NewState} ->
  1408. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, true);
  1409. {reS, NewState, Actions} ->
  1410. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, true, listify(Actions), CallbackForm);
  1411. reS_S ->
  1412. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, true);
  1413. {reS_S, Actions} ->
  1414. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, true, listify(Actions), CallbackForm);
  1415. stop ->
  1416. terminate(exit, normal, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1417. {stop, Reason} ->
  1418. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1419. {stop, Reason, NewState} ->
  1420. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, LeftEvents);
  1421. {stopReply, Reason, Replies} ->
  1422. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1423. try
  1424. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, LeftEvents)
  1425. after
  1426. case Replies of
  1427. {reply, RFrom, Reply} ->
  1428. reply(RFrom, Reply);
  1429. _ when is_list(Replies) ->
  1430. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1431. ok;
  1432. _ ->
  1433. _ = reply(From, Replies)
  1434. end
  1435. end;
  1436. {stopReply, Reason, Replies, NewState} ->
  1437. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1438. try
  1439. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, LeftEvents)
  1440. after
  1441. case Replies of
  1442. {reply, RFrom, Reply} ->
  1443. _ = reply(RFrom, Reply);
  1444. _ when is_list(Replies) ->
  1445. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1446. ok;
  1447. _ ->
  1448. _ = reply(From, Replies)
  1449. end
  1450. end;
  1451. _ ->
  1452. terminate(error, {bad_handleEventCR, Result}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1453. end.
  1454. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, IsCallEnter) ->
  1455. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1456. case IsEnter andalso IsCallEnter of
  1457. true ->
  1458. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter);
  1459. false ->
  1460. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter)
  1461. end.
  1462. %% dealEventCallbackRet
  1463. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, IsCallEnter) ->
  1464. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1465. case IsEnter andalso IsCallEnter of
  1466. true ->
  1467. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false);
  1468. false ->
  1469. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false)
  1470. end.
  1471. %% 处理enter callback 动作列表
  1472. %% parseEnterActionsList
  1473. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsCallEnter, IsHib, DoAfter, Actions) ->
  1474. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1475. %% enter 调用不能改成状态 actions 不能返回 IsPos = true 但是可以取消之前的推迟 设置IsPos = false 不能设置 doafter 不能插入事件
  1476. case Actions of
  1477. [] ->
  1478. case IsEnter andalso IsCallEnter of
  1479. true ->
  1480. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter);
  1481. _ ->
  1482. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter)
  1483. end;
  1484. _ ->
  1485. case doParseAL(Actions, ?CB_FORM_ENTER, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs) of
  1486. {error, ErrorContent} ->
  1487. terminate(error, ErrorContent, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, Debug, LeftEvents);
  1488. {NewIsEnter, NNewTimers, NewDebug, NewIsPos, NewIsHib, DoAfter, NewNextEs} ->
  1489. case NewIsEnter andalso IsCallEnter of
  1490. true ->
  1491. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, NewIsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, DoAfter);
  1492. _ ->
  1493. performTransitions(Parent, Name, Module, HibernateAfterTimeout, NewIsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, DoAfter)
  1494. end
  1495. end
  1496. end.
  1497. %% 处理非 enter 或者after callback 返回的动作列表
  1498. %% parseEventActionsList
  1499. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, IsCallEnter, Actions, CallbackForm) ->
  1500. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1501. case Actions of
  1502. [] ->
  1503. case IsEnter andalso IsCallEnter of
  1504. true ->
  1505. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false);
  1506. _ ->
  1507. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false)
  1508. end;
  1509. _ ->
  1510. case doParseAL(Actions, CallbackForm, Name, IsEnter, NewTimers, Debug, false, false, false, []) of
  1511. {error, ErrorContent} ->
  1512. terminate(error, ErrorContent, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, []);
  1513. {NewIsEnter, NNewTimers, NewDebug, NewIsPos, NewIsHib, MewDoAfter, NewNextEs} ->
  1514. case NewIsEnter andalso IsCallEnter of
  1515. true ->
  1516. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, MewDoAfter);
  1517. _ ->
  1518. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, MewDoAfter)
  1519. end
  1520. end
  1521. end.
  1522. %% loopParseActionsList
  1523. doParseAL([], _CallbackForm, _Name, IsEnter, Times, Debug, IsPos, IsHib, DoAfter, NextEs) ->
  1524. {IsEnter, Times, Debug, IsPos, IsHib, DoAfter, NextEs};
  1525. doParseAL([OneAction | LeftActions], CallbackForm, Name, IsEnter, Timers, Debug, IsPos, IsHib, DoAfter, NextEs) ->
  1526. case OneAction of
  1527. {reply, From, Reply} ->
  1528. reply(From, Reply),
  1529. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1530. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, NewDebug, IsPos, IsHib, DoAfter, NextEs);
  1531. {eTimeout, Time, TimeoutMsg} ->
  1532. case Time of
  1533. infinity ->
  1534. NewTimers = doCancelTimer(eTimeout, Timers),
  1535. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1536. _ ->
  1537. TimerRef = erlang:start_timer(Time, self(), eTimeout),
  1538. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {eTimeout, Time, TimeoutMsg, []}}),
  1539. NewTimers = doRegisterTimer(eTimeout, TimerRef, TimeoutMsg, Timers),
  1540. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1541. end;
  1542. {sTimeout, Time, TimeoutMsg} ->
  1543. case Time of
  1544. infinity ->
  1545. NewTimers = doCancelTimer(sTimeout, Timers),
  1546. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1547. _ ->
  1548. TimerRef = erlang:start_timer(Time, self(), sTimeout),
  1549. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {sTimeout, Time, TimeoutMsg, []}}),
  1550. NewTimers = doRegisterTimer(sTimeout, TimerRef, TimeoutMsg, Timers),
  1551. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1552. end;
  1553. {gTimeout, TimeoutName, Time, TimeoutMsg} ->
  1554. case Time of
  1555. infinity ->
  1556. NewTimers = doCancelTimer(TimeoutName, Timers),
  1557. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1558. _ ->
  1559. TimerRef = erlang:start_timer(Time, self(), TimeoutName),
  1560. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, []}}),
  1561. NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers),
  1562. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1563. end;
  1564. {eTimeout, Time, TimeoutMsg, Options} ->
  1565. case Time of
  1566. infinity ->
  1567. NewTimers = doCancelTimer(eTimeout, Timers),
  1568. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1569. _ ->
  1570. TimerRef = erlang:start_timer(Time, self(), eTimeout, Options),
  1571. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {eTimeout, Time, TimeoutMsg, Options}}),
  1572. NewTimers = doRegisterTimer(eTimeout, TimerRef, TimeoutMsg, Timers),
  1573. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1574. end;
  1575. {sTimeout, Time, TimeoutMsg, Options} ->
  1576. case Time of
  1577. infinity ->
  1578. NewTimers = doCancelTimer(sTimeout, Timers),
  1579. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1580. _ ->
  1581. TimerRef = erlang:start_timer(Time, self(), sTimeout, Options),
  1582. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {sTimeout, Time, TimeoutMsg, Options}}),
  1583. NewTimers = doRegisterTimer(sTimeout, TimerRef, TimeoutMsg, Timers),
  1584. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1585. end;
  1586. {gTimeout, TimeoutName, Time, TimeoutMsg, Options} ->
  1587. case Time of
  1588. infinity ->
  1589. NewTimers = doCancelTimer(TimeoutName, Timers),
  1590. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1591. _ ->
  1592. TimerRef = erlang:start_timer(Time, self(), TimeoutName, Options),
  1593. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, Options}}),
  1594. NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers),
  1595. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1596. end;
  1597. {u_eTimeout, NewTimeoutMsg} ->
  1598. NewTimers = doUpdateTimer(eTimeout, NewTimeoutMsg, Timers),
  1599. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1600. {u_sTimeout, NewTimeoutMsg} ->
  1601. NewTimers = doUpdateTimer(sTimeout, NewTimeoutMsg, Timers),
  1602. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1603. {u_gTimeout, TimeoutName, NewTimeoutMsg} ->
  1604. NewTimers = doUpdateTimer(TimeoutName, NewTimeoutMsg, Timers),
  1605. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1606. c_eTimeout ->
  1607. NewTimers = doCancelTimer(eTimeout, Timers),
  1608. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1609. c_sTimeout ->
  1610. NewTimers = doCancelTimer(sTimeout, Timers),
  1611. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1612. {c_gTimeout, TimeoutName} ->
  1613. NewTimers = doCancelTimer(TimeoutName, Timers),
  1614. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1615. {isEnter, NewIsEnter} ->
  1616. NewDebug = ?SYS_DEBUG(Debug, Name, {change_isEnter, NewIsEnter}),
  1617. doParseAL(LeftActions, CallbackForm, Name, Timers, NewIsEnter, NewDebug, IsPos, IsHib, DoAfter, NextEs);
  1618. {isHib, NewIsHib} ->
  1619. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, IsPos, NewIsHib, DoAfter, NextEs);
  1620. {isPos, NewIsPos} when (not NewIsPos orelse CallbackForm == ?CB_FORM_EVENT) ->
  1621. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, NewIsPos, IsHib, DoAfter, NextEs);
  1622. {doAfter, Args} when CallbackForm == ?CB_FORM_EVENT ->
  1623. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, IsPos, IsHib, {true, Args}, NextEs);
  1624. {nextE, Type, Content} when CallbackForm == ?CB_FORM_EVENT orelse CallbackForm == ?CB_FORM_AFTER ->
  1625. %% 处理next_event动作
  1626. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, IsPos, IsHib, DoAfter, [{Type, Content} | NextEs]);
  1627. _ ->
  1628. {error, {bad_ActionType, OneAction}}
  1629. end.
  1630. % checkTimeOptions({TimeoutType, Time, TimeoutMsg, Options} = NewTV) ->
  1631. % case Options of
  1632. % [{abs, true}] when ?ABS_TIMEOUT(Time) ->
  1633. % NewTV;
  1634. % [{abs, false}] when ?REL_TIMEOUT(Time) ->
  1635. % {TimeoutType, Time, TimeoutMsg};
  1636. % [] when ?REL_TIMEOUT(Time) ->
  1637. % {TimeoutType, Time, TimeoutMsg};
  1638. % _ ->
  1639. % %% 如果将来 start_timer opt扩展了 这里的代码也要修改
  1640. % error_timeout_opt
  1641. % end.
  1642. %% 进行状态转换
  1643. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, AllLeftEvents, NextEs, IsPos, IsHib, DoAfter) ->
  1644. %% 已收集所有选项,并缓冲next_events。执行实际状态转换。如果推迟则将当前事件移至推迟
  1645. %% 此时 NextEs的顺序与最开始出现的顺序相反. 后面执行的顺序 当前新增事件 + 反序的Postpone事件 + LeftEvents
  1646. case AllLeftEvents of
  1647. [] ->
  1648. CurEvent = undefined,
  1649. LeftEvents = [];
  1650. _ ->
  1651. [CurEvent | LeftEvents] = AllLeftEvents
  1652. end,
  1653. NewDebug = ?SYS_DEBUG(Debug, Name, case IsPos of true -> {postpone, CurEvent, CurStatus, NewStatus}; _ -> {consume, CurEvent, CurStatus, NewStatus} end),
  1654. if
  1655. CurStatus =:= NewStatus ->
  1656. %% Cancel event timeout
  1657. if
  1658. IsPos ->
  1659. LastLeftEvents =
  1660. case NextEs of
  1661. [] ->
  1662. LeftEvents;
  1663. [Es1] ->
  1664. [Es1 | LeftEvents];
  1665. [Es2, Es1] ->
  1666. [Es1, Es2 | LeftEvents];
  1667. _ ->
  1668. lists:reverse(NextEs, LeftEvents)
  1669. end,
  1670. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, [CurEvent | Postponed], Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter);
  1671. true ->
  1672. LastLeftEvents =
  1673. case NextEs of
  1674. [] ->
  1675. LeftEvents;
  1676. [Es1] ->
  1677. [Es1 | LeftEvents];
  1678. [Es2, Es1] ->
  1679. [Es1, Es2 | LeftEvents];
  1680. _ ->
  1681. lists:reverse(NextEs, LeftEvents)
  1682. end,
  1683. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter)
  1684. end;
  1685. true ->
  1686. %% 状态发生改变 重试推迟的事件
  1687. if
  1688. IsPos ->
  1689. NewLeftEvents =
  1690. case Postponed of
  1691. [] ->
  1692. [CurEvent | LeftEvents];
  1693. [E1] ->
  1694. [E1, CurEvent | LeftEvents];
  1695. [E2, E1] ->
  1696. [E1, E2, CurEvent | LeftEvents];
  1697. _ ->
  1698. lists:reverse(Postponed, [CurEvent | LeftEvents])
  1699. end,
  1700. LastLeftEvents =
  1701. case NextEs of
  1702. [] ->
  1703. NewLeftEvents;
  1704. [Es1] ->
  1705. [Es1 | NewLeftEvents];
  1706. [Es2, Es1] ->
  1707. [Es1, Es2 | NewLeftEvents];
  1708. _ ->
  1709. lists:reverse(NextEs, NewLeftEvents)
  1710. end,
  1711. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, [], Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter);
  1712. true ->
  1713. NewLeftEvents =
  1714. case Postponed of
  1715. [] ->
  1716. LeftEvents;
  1717. [E1] ->
  1718. [E1 | LeftEvents];
  1719. [E2, E1] ->
  1720. [E1, E2 | LeftEvents];
  1721. _ ->
  1722. lists:reverse(Postponed, LeftEvents)
  1723. end,
  1724. LastLeftEvents =
  1725. case NextEs of
  1726. [] ->
  1727. NewLeftEvents;
  1728. [Es1] ->
  1729. [Es1 | NewLeftEvents];
  1730. [Es2, Es1] ->
  1731. [Es1, Es2 | NewLeftEvents];
  1732. _ ->
  1733. lists:reverse(NextEs, NewLeftEvents)
  1734. end,
  1735. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, [], Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter)
  1736. end
  1737. end.
  1738. %% 状态转换已完成,如果有排队事件,则继续循环,否则获取新事件
  1739. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, IsHib, DoAfter) ->
  1740. % io:format("loop_done: status_data = ~p ~n postponed = ~p LeftEvents = ~p ~n timers = ~p.~n", [S#status.status_data,,S#status.postponed,LeftEvents,S#status.timers]),
  1741. case DoAfter of
  1742. {true, Args} ->
  1743. %% 这里 IsHib设置会被丢弃 按照gen_server中的设计 continue 和 hiernate是互斥的
  1744. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Args);
  1745. _ ->
  1746. case LeftEvents of
  1747. [] ->
  1748. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib);
  1749. [Event | _Events] ->
  1750. %% 循环直到没有排队事件
  1751. if
  1752. IsHib ->
  1753. %% _ = garbage_collect(),
  1754. erts_internal:garbage_collect(major);
  1755. true ->
  1756. ignore
  1757. end,
  1758. startEventCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Event)
  1759. end
  1760. end.
  1761. %% 取消事件超时 和 状态超时
  1762. cancelESTimeout(true, Timers) ->
  1763. %% Cancel event timeout
  1764. case Timers of
  1765. #{eTimeout := {TimerRef, _TimeoutMsg}} ->
  1766. cancelTimer(eTimeout, TimerRef, Timers);
  1767. _ ->
  1768. Timers
  1769. end;
  1770. cancelESTimeout(false, Timers) ->
  1771. %% 取消 status and event timeout
  1772. case Timers of
  1773. #{sTimeout := {STimerRef, _STimeoutMsg}} ->
  1774. TemTimer = cancelTimer(sTimeout, STimerRef, Timers),
  1775. case TemTimer of
  1776. #{eTimeout := {ETimerRef, _ETimeoutMsg}} ->
  1777. cancelTimer(eTimeout, ETimerRef, TemTimer);
  1778. _ ->
  1779. TemTimer
  1780. end;
  1781. _ ->
  1782. case Timers of
  1783. #{eTimeout := {ETimerRef, _ETimeoutMsg}} ->
  1784. cancelTimer(eTimeout, ETimerRef, Timers);
  1785. _ ->
  1786. Timers
  1787. end
  1788. end.
  1789. doRegisterTimer(TimeoutType, NewTimerRef, TimeoutMsg, Timers) ->
  1790. case Timers of
  1791. #{TimeoutType := {OldTimerRef, _OldTimeMsg}} ->
  1792. justCancelTimer(TimeoutType, OldTimerRef),
  1793. Timers#{TimeoutType := {NewTimerRef, TimeoutMsg}};
  1794. _ ->
  1795. Timers#{TimeoutType => {NewTimerRef, TimeoutMsg}}
  1796. end.
  1797. doCancelTimer(TimeoutType, Timers) ->
  1798. case Timers of
  1799. #{TimeoutType := {TimerRef, _TimeoutMsg}} ->
  1800. cancelTimer(TimeoutType, TimerRef, Timers);
  1801. _ ->
  1802. Timers
  1803. end.
  1804. doUpdateTimer(TimeoutType, Timers, TimeoutMsg) ->
  1805. case Timers of
  1806. #{TimeoutType := {TimerRef, _OldTimeoutMsg}} ->
  1807. Timers#{TimeoutType := {TimerRef, TimeoutMsg}};
  1808. _ ->
  1809. Timers
  1810. end.
  1811. justCancelTimer(TimeoutType, TimerRef) ->
  1812. case erlang:cancel_timer(TimerRef) of
  1813. false ->
  1814. %% 找不到计时器,我们还没有看到超时消息
  1815. receive
  1816. {timeout, TimerRef, TimeoutType} ->
  1817. %% 丢弃该超时消息
  1818. ok
  1819. after 0 ->
  1820. ok
  1821. end;
  1822. _ ->
  1823. %% Timer 已经运行了
  1824. ok
  1825. end.
  1826. cancelTimer(TimeoutType, TimerRef, Timers) ->
  1827. case erlang:cancel_timer(TimerRef) of
  1828. false ->
  1829. %% 找不到计时器,我们还没有看到超时消息
  1830. receive
  1831. {timeout, TimerRef, TimeoutType} ->
  1832. %% 丢弃该超时消息
  1833. ok
  1834. after 0 ->
  1835. ok
  1836. end;
  1837. _ ->
  1838. %% Timer 已经运行了
  1839. ok
  1840. end,
  1841. maps:remove(TimeoutType, Timers).
  1842. %% 排队立即超时事件(超时0事件)
  1843. %% 自事件超时0起,事件得到特殊处理
  1844. %% 任何收到的事件都会取消事件超时,
  1845. %% 因此,如果在事件超时0事件之前存在入队事件-事件超时被取消,因此没有事件。
  1846. %% 其他(status_timeout和{timeout,Name})超时0个事件
  1847. %% 在事件计时器超时0事件之后发生的事件被认为是
  1848. %% 属于在事件计时器之后启动的计时器
  1849. %% 已触发超时0事件,因此它们不会取消事件计时器。
  1850. %% mergeTimeoutEvents([], _Status, _CycleData, Debug, Events) ->
  1851. %% {Events, Debug};
  1852. %% mergeTimeoutEvents([{eTimeout, _} = TimeoutEvent | TimeoutEvents], Status, CycleData, Debug, []) ->
  1853. %% %% 由于队列中没有其他事件,因此添加该事件零超时事件
  1854. %% NewDebug = ?SYS_DEBUG(Debug, CycleData, {insert_timeout, TimeoutEvent, Status}),
  1855. %% mergeTimeoutEvents(TimeoutEvents, Status, CycleData, NewDebug, [TimeoutEvent]);
  1856. %% mergeTimeoutEvents([{eTimeout, _} | TimeoutEvents], Status, CycleData, Debug, Events) ->
  1857. %% %% 忽略,因为队列中还有其他事件,因此它们取消了事件超时0。
  1858. %% mergeTimeoutEvents(TimeoutEvents, Status, CycleData, Debug, Events);
  1859. %% mergeTimeoutEvents([TimeoutEvent | TimeoutEvents], Status, CycleData, Debug, Events) ->
  1860. %% %% Just prepend all others
  1861. %% NewDebug = ?SYS_DEBUG(Debug, CycleData, {insert_timeout, TimeoutEvent, Status}),
  1862. %% mergeTimeoutEvents(TimeoutEvents, Status, CycleData, NewDebug, [TimeoutEvent | Events]).
  1863. %% Return a list of all pending timeouts
  1864. listTimeouts(Timers) ->
  1865. {maps:size(Timers), allTimer(maps:iterator(Timers), [])}.
  1866. allTimer(Iterator, Acc) ->
  1867. case maps:next(Iterator) of
  1868. {TimeoutType, {_TimerRef, TimeoutMsg}, NextIterator} ->
  1869. allTimer(NextIterator, [{TimeoutType, TimeoutMsg} | Acc]);
  1870. none ->
  1871. Acc
  1872. end.
  1873. %%---------------------------------------------------------------------------
  1874. terminate(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents) ->
  1875. epmStopAll(EpmHers),
  1876. %% 这里停止所有的epm 但是并没有更新 epmHers为#{} 目前感觉没必要清理掉
  1877. case erlang:function_exported(Module, terminate, 3) of
  1878. true ->
  1879. try Module:terminate(Reason, CurStatus, CurState) of
  1880. _ -> ok
  1881. catch
  1882. throw:_ -> ok;
  1883. C:R ->
  1884. error_info(C, R, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents),
  1885. erlang:raise(C, R, ?STACKTRACE())
  1886. end;
  1887. false ->
  1888. ok
  1889. end,
  1890. case Reason of
  1891. normal ->
  1892. ?SYS_DEBUG(Debug, Name, {terminate, Reason, CurStatus});
  1893. shutdown ->
  1894. ?SYS_DEBUG(Debug, Name, {terminate, Reason, CurStatus});
  1895. {shutdown, _} ->
  1896. ?SYS_DEBUG(Debug, Name, {terminate, Reason, CurStatus});
  1897. _ ->
  1898. error_info(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1899. end,
  1900. case Stacktrace of
  1901. [] ->
  1902. erlang:Class(Reason);
  1903. _ ->
  1904. erlang:raise(Class, Reason, Stacktrace)
  1905. end.
  1906. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% debug 日志 Start%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1907. error_info(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents) ->
  1908. Log = sys:get_log(Debug),
  1909. ?LOG_ERROR(
  1910. #{
  1911. label => {es_gen_ipc, terminate},
  1912. name => Name,
  1913. module => Module,
  1914. queue => LeftEvents,
  1915. postponed => Postponed,
  1916. isEnter => IsEnter,
  1917. status => format_status(terminate, get(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState),
  1918. timeouts => listTimeouts(Timers),
  1919. log => Log,
  1920. reason => {Class, Reason, Stacktrace},
  1921. client_info => cliStacktrace(LeftEvents)
  1922. },
  1923. #{
  1924. domain => [otp],
  1925. report_cb => fun es_gen_ipc:format_log/2,
  1926. error_logger => #{tag => error, report_cb => fun es_gen_ipc:format_log/1}}).
  1927. cliStacktrace([]) ->
  1928. undefined;
  1929. cliStacktrace([{{call, {Pid, _Tag}}, _Req} | _]) when is_pid(Pid) ->
  1930. if
  1931. node(Pid) =:= node() ->
  1932. case process_info(Pid, [current_stacktrace, registered_name]) of
  1933. undefined ->
  1934. {Pid, dead};
  1935. [{current_stacktrace, Stacktrace}, {registered_name, []}] ->
  1936. {Pid, {Pid, Stacktrace}};
  1937. [{current_stacktrace, Stacktrace}, {registered_name, Name}] ->
  1938. {Pid, {Name, Stacktrace}}
  1939. end;
  1940. true ->
  1941. {Pid, remote}
  1942. end;
  1943. cliStacktrace([_ | _]) ->
  1944. undefined;
  1945. cliStacktrace(_) ->
  1946. undefined.
  1947. %% format_log/1 is the report callback used by Logger handler
  1948. %% error_logger only. It is kept for backwards compatibility with
  1949. %% legacy error_logger event handlers. This function must always
  1950. %% return {Format,Args} compatible with the arguments in this module's
  1951. %% calls to error_logger prior to OTP-21.0.
  1952. format_log(Report) ->
  1953. Depth = error_logger:get_format_depth(),
  1954. FormatOpts = #{
  1955. chars_limit => unlimited,
  1956. depth => Depth,
  1957. single_line => false,
  1958. encoding => utf8
  1959. },
  1960. format_log_multi(limit_report(Report, Depth), FormatOpts).
  1961. limit_report(Report, unlimited) ->
  1962. Report;
  1963. limit_report(
  1964. #{
  1965. label := {es_gen_ipc, terminate},
  1966. queue := Q,
  1967. postponed := Postponed,
  1968. module := Module,
  1969. status := FmtData,
  1970. timeouts := Timeouts,
  1971. log := Log,
  1972. reason := {Class, Reason, Stacktrace},
  1973. client_info := ClientInfo
  1974. } = Report,
  1975. Depth) ->
  1976. Report#{
  1977. queue =>
  1978. case Q of
  1979. [Event | Events] ->
  1980. [io_lib:limit_term(Event, Depth) | io_lib:limit_term(Events, Depth)];
  1981. _ ->
  1982. []
  1983. end,
  1984. postponed =>
  1985. case Postponed of
  1986. [] -> [];
  1987. _ -> io_lib:limit_term(Postponed, Depth)
  1988. end,
  1989. modules => io_lib:limit_term(Module, Depth),
  1990. status => io_lib:limit_term(FmtData, Depth),
  1991. timeouts =>
  1992. case Timeouts of
  1993. {0, _} -> Timeouts;
  1994. _ -> io_lib:limit_term(Timeouts, Depth)
  1995. end,
  1996. log =>
  1997. case Log of
  1998. [] -> [];
  1999. _ -> [io_lib:limit_term(T, Depth) || T <- Log]
  2000. end,
  2001. reason =>
  2002. {Class, io_lib:limit_term(Reason, Depth), io_lib:limit_term(Stacktrace, Depth)},
  2003. client_info => limit_client_info(ClientInfo, Depth)
  2004. }.
  2005. limit_client_info({Pid, {Name, Stacktrace}}, Depth) ->
  2006. {Pid, {Name, io_lib:limit_term(Stacktrace, Depth)}};
  2007. limit_client_info(Client, _Depth) ->
  2008. Client.
  2009. %% format_log/2 is the report callback for any Logger handler, except
  2010. %% error_logger.
  2011. format_log(Report, FormatOpts0) ->
  2012. Default = #{
  2013. chars_limit => unlimited,
  2014. depth => unlimited,
  2015. single_line => false,
  2016. encoding => utf8
  2017. },
  2018. FormatOpts = maps:merge(Default, FormatOpts0),
  2019. IoOpts =
  2020. case FormatOpts of
  2021. #{chars_limit := unlimited} -> [];
  2022. #{chars_limit := Limit} -> [{chars_limit, Limit}]
  2023. end,
  2024. {Format, Args} = format_log_single(Report, FormatOpts),
  2025. io_lib:format(Format, Args, IoOpts).
  2026. format_log_single(
  2027. #{
  2028. label := {es_gen_ipc, terminate},
  2029. name := Name,
  2030. queue := Q,
  2031. %% postponed
  2032. %% isEnter
  2033. status := FmtData,
  2034. %% timeouts
  2035. log := Log,
  2036. reason := {Class, Reason, Stacktrace},
  2037. client_info := ClientInfo
  2038. },
  2039. #{single_line := true, depth := Depth} = FormatOpts) ->
  2040. P = p(FormatOpts),
  2041. {FixedReason, FixedStacktrace} = fix_reason(Class, Reason, Stacktrace),
  2042. {ClientFmt, ClientArgs} = format_client_log_single(ClientInfo, P, Depth),
  2043. Format =
  2044. lists:append(
  2045. ["State machine ", P, " terminating. Reason: ", P,
  2046. case FixedStacktrace of
  2047. [] -> "";
  2048. _ -> ". Stack: " ++ P
  2049. end,
  2050. case Q of
  2051. [] -> "";
  2052. _ -> ". Last event: " ++ P
  2053. end,
  2054. ". State: ", P,
  2055. case Log of
  2056. [] -> "";
  2057. _ -> ". Log: " ++ P
  2058. end,
  2059. "."]
  2060. ),
  2061. Args0 =
  2062. [Name, FixedReason] ++
  2063. case FixedStacktrace of
  2064. [] -> [];
  2065. _ -> [FixedStacktrace]
  2066. end ++
  2067. case Q of
  2068. [] -> [];
  2069. [Event | _] -> [Event]
  2070. end ++
  2071. [FmtData] ++
  2072. case Log of
  2073. [] -> [];
  2074. _ -> [Log]
  2075. end,
  2076. Args =
  2077. case Depth of
  2078. unlimited ->
  2079. Args0;
  2080. _ ->
  2081. lists:flatmap(fun(A) -> [A, Depth] end, Args0)
  2082. end,
  2083. {Format ++ ClientFmt, Args ++ ClientArgs};
  2084. format_log_single(Report, FormatOpts) ->
  2085. format_log_multi(Report, FormatOpts).
  2086. format_log_multi(
  2087. #{
  2088. label := {es_gen_ipc, terminate},
  2089. name := Name,
  2090. queue := Q,
  2091. postponed := Postponed,
  2092. module := Module,
  2093. isEnter := StateEnter,
  2094. status := FmtData,
  2095. timeouts := Timeouts,
  2096. log := Log,
  2097. reason := {Class, Reason, Stacktrace},
  2098. client_info := ClientInfo
  2099. },
  2100. #{depth := Depth} = FormatOpts) ->
  2101. P = p(FormatOpts),
  2102. {FixedReason, FixedStacktrace} = fix_reason(Class, Reason, Stacktrace),
  2103. {ClientFmt, ClientArgs} = format_client_log(ClientInfo, P, Depth),
  2104. CBMode =
  2105. case StateEnter of
  2106. true ->
  2107. [Module, 'isEnter=true'];
  2108. false ->
  2109. Module
  2110. end,
  2111. Format =
  2112. lists:append(
  2113. ["** es_gen_ipc State machine ", P, " terminating~n",
  2114. case Q of
  2115. [] -> "";
  2116. _ -> "** Last event = " ++ P ++ "~n"
  2117. end,
  2118. "** When server status = ", P, "~n",
  2119. "** Reason for termination = ", P, ":", P, "~n",
  2120. "** Callback modules = ", P, "~n",
  2121. "** Callback mode = ", P, "~n",
  2122. case Q of
  2123. [_, _ | _] -> "** Queued = " ++ P ++ "~n";
  2124. _ -> ""
  2125. end,
  2126. case Postponed of
  2127. [] -> "";
  2128. _ -> "** Postponed = " ++ P ++ "~n"
  2129. end,
  2130. case FixedStacktrace of
  2131. [] -> "";
  2132. _ -> "** Stacktrace =~n** " ++ P ++ "~n"
  2133. end,
  2134. case Timeouts of
  2135. {0, _} -> "";
  2136. _ -> "** Time-outs: " ++ P ++ "~n"
  2137. end,
  2138. case Log of
  2139. [] -> "";
  2140. _ -> "** Log =~n** " ++ P ++ "~n"
  2141. end]),
  2142. Args0 =
  2143. [Name |
  2144. case Q of
  2145. [] -> [];
  2146. [Event | _] -> [Event]
  2147. end] ++
  2148. [FmtData,
  2149. Class, FixedReason,
  2150. Module,
  2151. CBMode] ++
  2152. case Q of
  2153. [_ | [_ | _] = Events] -> [Events];
  2154. _ -> []
  2155. end ++
  2156. case Postponed of
  2157. [] -> [];
  2158. _ -> [Postponed]
  2159. end ++
  2160. case FixedStacktrace of
  2161. [] -> [];
  2162. _ -> [FixedStacktrace]
  2163. end ++
  2164. case Timeouts of
  2165. {0, _} -> [];
  2166. _ -> [Timeouts]
  2167. end ++
  2168. case Log of
  2169. [] -> [];
  2170. _ -> [Log]
  2171. end,
  2172. Args =
  2173. case Depth of
  2174. unlimited ->
  2175. Args0;
  2176. _ ->
  2177. lists:flatmap(fun(A) -> [A, Depth] end, Args0)
  2178. end,
  2179. {Format ++ ClientFmt, Args ++ ClientArgs}.
  2180. fix_reason(Class, Reason, Stacktrace) ->
  2181. case Stacktrace of
  2182. [{M, F, Args, _} | ST]
  2183. when Class =:= error, Reason =:= undef ->
  2184. case code:is_loaded(M) of
  2185. false ->
  2186. {{'module could not be loaded', M}, ST};
  2187. _ ->
  2188. Arity =
  2189. if
  2190. is_list(Args) ->
  2191. length(Args);
  2192. is_integer(Args) ->
  2193. Args
  2194. end,
  2195. case erlang:function_exported(M, F, Arity) of
  2196. true ->
  2197. {Reason, Stacktrace};
  2198. false ->
  2199. {{'function not exported', {M, F, Arity}}, ST}
  2200. end
  2201. end;
  2202. _ -> {Reason, Stacktrace}
  2203. end.
  2204. format_client_log_single(undefined, _, _) ->
  2205. {"", []};
  2206. format_client_log_single({Pid, dead}, _, _) ->
  2207. {" Client ~0p is dead.", [Pid]};
  2208. format_client_log_single({Pid, remote}, _, _) ->
  2209. {" Client ~0p is remote on node ~0p.", [Pid, node(Pid)]};
  2210. format_client_log_single({_Pid, {Name, Stacktrace0}}, P, Depth) ->
  2211. %% Minimize the stacktrace a bit for single line reports. This is
  2212. %% hopefully enough to point out the position.
  2213. Stacktrace = lists:sublist(Stacktrace0, 4),
  2214. Format = lists:append([" Client ", P, " stacktrace: ", P, "."]),
  2215. Args =
  2216. case Depth of
  2217. unlimited ->
  2218. [Name, Stacktrace];
  2219. _ ->
  2220. [Name, Depth, Stacktrace, Depth]
  2221. end,
  2222. {Format, Args}.
  2223. format_client_log(undefined, _, _) ->
  2224. {"", []};
  2225. format_client_log({Pid, dead}, _, _) ->
  2226. {"** Client ~p is dead~n", [Pid]};
  2227. format_client_log({Pid, remote}, _, _) ->
  2228. {"** Client ~p is remote on node ~p~n", [Pid, node(Pid)]};
  2229. format_client_log({_Pid, {Name, Stacktrace}}, P, Depth) ->
  2230. Format = lists:append(["** Client ", P, " stacktrace~n** ", P, "~n"]),
  2231. Args =
  2232. case Depth of
  2233. unlimited ->
  2234. [Name, Stacktrace];
  2235. _ ->
  2236. [Name, Depth, Stacktrace, Depth]
  2237. end,
  2238. {Format, Args}.
  2239. p(#{single_line := Single, depth := Depth, encoding := Enc}) ->
  2240. "~" ++ single(Single) ++ mod(Enc) ++ p(Depth);
  2241. p(unlimited) ->
  2242. "p";
  2243. p(_Depth) ->
  2244. "P".
  2245. single(true) -> "0";
  2246. single(false) -> "".
  2247. mod(latin1) -> "";
  2248. mod(_) -> "t".
  2249. %% Call Module:format_status/2 or return a default value
  2250. format_status(Opt, PDict, _Parent, _Name, Module, _HibernateAfterTimeout, _IsEnter, _EpmHers, _Postponed, _Timers, CurStatus, CurState) ->
  2251. case erlang:function_exported(Module, formatStatus, 2) of
  2252. true ->
  2253. try Module:formatStatus(Opt, [PDict, CurStatus, CurState])
  2254. catch
  2255. throw:Result -> Result;
  2256. _:_ ->
  2257. format_status_default(Opt, {{CurStatus, CurState}, atom_to_list(Module) ++ ":formatStatus/2 crashed"})
  2258. end;
  2259. false ->
  2260. format_status_default(Opt, {CurStatus, CurState})
  2261. end.
  2262. %% The default Module:format_status/3
  2263. format_status_default(Opt, State_Data) ->
  2264. case Opt of
  2265. terminate ->
  2266. State_Data;
  2267. _ ->
  2268. [{data, [{"State", State_Data}]}]
  2269. end.
  2270. print_event(Dev, SystemEvent, Name) ->
  2271. case SystemEvent of
  2272. {in, Event, Status} ->
  2273. io:format(
  2274. Dev, "*DBG* ~tp receive ~ts in Status ~tp~n",
  2275. [Name, event_string(Event), Status]);
  2276. {code_change, Event, Status} ->
  2277. io:format(
  2278. Dev, "*DBG* ~tp receive ~ts after code change in Status ~tp~n",
  2279. [Name, event_string(Event), Status]);
  2280. {out, Reply, {To, _Tag}} ->
  2281. io:format(
  2282. Dev, "*DBG* ~tp send ~tp to ~tw~n",
  2283. [Name, Reply, To]);
  2284. {out, Replys} ->
  2285. io:format(
  2286. Dev, "*DBG* ~tp sends to: ~tp~n",
  2287. [Name, Replys]);
  2288. {enter, Status} ->
  2289. io:format(
  2290. Dev, "*DBG* ~tp enter in Status ~tp~n",
  2291. [Name, Status]);
  2292. {start_timer, Action} ->
  2293. io:format(
  2294. Dev, "*DBG* ~tp start_timer ~tp ~n",
  2295. [Name, Action]);
  2296. {insert_timeout, Event, Status} ->
  2297. io:format(
  2298. Dev, "*DBG* ~tp insert_timeout ~tp in Status ~tp~n",
  2299. [Name, Event, Status]);
  2300. {terminate, Reason, Status} ->
  2301. io:format(
  2302. Dev, "*DBG* ~tp terminate ~tp in Status ~tp~n",
  2303. [Name, Reason, Status]);
  2304. {change_isEnter, IsEnter} ->
  2305. io:format(
  2306. Dev, "*DBG* ~tp change_isEnter to ~tp ~n",
  2307. [Name, IsEnter]);
  2308. {Tag, Event, Status, NextStatus}
  2309. when Tag =:= postpone; Tag =:= consume ->
  2310. StateString =
  2311. case NextStatus of
  2312. Status ->
  2313. io_lib:format("~tp", [Status]);
  2314. _ ->
  2315. io_lib:format("~tp => ~tp", [Status, NextStatus])
  2316. end,
  2317. io:format(
  2318. Dev, "*DBG* ~tp ~tw ~ts in state ~ts~n",
  2319. [Name, Tag, event_string(Event), StateString]);
  2320. _NotMatch ->
  2321. io:format(
  2322. Dev, "*DBG* ~tp NotMatch ~tp ~n",
  2323. [Name, _NotMatch])
  2324. end.
  2325. event_string(Event) ->
  2326. case Event of
  2327. {{call, {Pid, _Tag}}, Request} ->
  2328. io_lib:format("call ~tp from ~tw", [Request, Pid]);
  2329. {EventType, EventContent} ->
  2330. io_lib:format("~tw ~tp", [EventType, EventContent])
  2331. end.
  2332. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% debug 日志 End %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%