projects/aports·blob master · refs

401 lines · 15.5 KiB

1From 8fde93608109537b26e9d81c01906f1385016e9f Mon Sep 17 00:00:00 2001
2From: Michael Truog <[email protected]>
3Date: Thu, 21 Mar 2024 17:02:15 -0700
4Subject: [PATCH] Add use of format_status/1 callback for Erlang/OTP 27.0
5 support.
6
7Backported from https://github.com/CloudI/CloudI/commit/8fde93608109537b26e9d81c01906f1385016e9f
8
9---
10 .../src/cloudi_core_i_constants.hrl | 9 +-
11 .../src/cloudi_core_i_services_external.erl | 66 ++++---
12 .../src/cloudi_core_i_services_internal.erl | 163 ++++++++++--------
13 3 files changed, 135 insertions(+), 105 deletions(-)
14
15diff --git a/src/lib/cloudi_core/src/cloudi_core_i_constants.hrl b/src/lib/cloudi_core/src/cloudi_core_i_constants.hrl
16index e3f4cbb22..1fb9daa67 100644
17--- a/src/lib/cloudi_core/src/cloudi_core_i_constants.hrl
18+++ b/src/lib/cloudi_core/src/cloudi_core_i_constants.hrl
19@@ -3,7 +3,7 @@
20 %%%
21 %%% MIT License
22 %%%
23-%%% Copyright (c) 2014-2023 Michael Truog <mjtruog at protonmail dot com>
24+%%% Copyright (c) 2014-2024 Michael Truog <mjtruog at protonmail dot com>
25 %%%
26 %%% Permission is hereby granted, free of charge, to any person obtaining a
27 %%% copy of this software and associated documentation files (the "Software"),
28@@ -32,11 +32,14 @@
29
30 -ifdef(OTP_RELEASE). % Erlang/OTP >= 21.0
31 % able to use -if/-elif here
32+-if(?OTP_RELEASE >= 24).
33+-define(ERLANG_OTP_VERSION_24_FEATURES, true).
34 -if(?OTP_RELEASE >= 25).
35 -define(ERLANG_OTP_VERSION_25_FEATURES, true).
36+-if(?OTP_RELEASE >= 27).
37+-define(ERLANG_OTP_VERSION_27_FEATURES, true).
38+-endif.
39 -endif.
40--if(?OTP_RELEASE >= 24).
41--define(ERLANG_OTP_VERSION_24_FEATURES, true).
42 -endif.
43 -if(?OTP_RELEASE < 22).
44 -error("Erlang/OTP version >= 22.0 is required!").
45diff --git a/src/lib/cloudi_core/src/cloudi_core_i_services_external.erl b/src/lib/cloudi_core/src/cloudi_core_i_services_external.erl
46index b224b7e0e..504b3a95e 100644
47--- a/src/lib/cloudi_core/src/cloudi_core_i_services_external.erl
48+++ b/src/lib/cloudi_core/src/cloudi_core_i_services_external.erl
49@@ -10,7 +10,7 @@
50 %%%
51 %%% MIT License
52 %%%
53-%%% Copyright (c) 2011-2023 Michael Truog <mjtruog at protonmail dot com>
54+%%% Copyright (c) 2011-2024 Michael Truog <mjtruog at protonmail dot com>
55 %%%
56 %%% Permission is hereby granted, free of charge, to any person obtaining a
57 %%% copy of this software and associated documentation files (the "Software"),
58@@ -31,8 +31,8 @@
59 %%% DEALINGS IN THE SOFTWARE.
60 %%%
61 %%% @author Michael Truog <mjtruog at protonmail dot com>
62-%%% @copyright 2011-2023 Michael Truog
63-%%% @version 2.0.7 {@date} {@time}
64+%%% @copyright 2011-2024 Michael Truog
65+%%% @version 2.0.8 {@date} {@time}
66 %%%------------------------------------------------------------------------
67
68 -module(cloudi_core_i_services_external).
69@@ -51,7 +51,7 @@
70 %% gen_statem callbacks
71 -export([callback_mode/0,
72 init/1, handle_event/4,
73- terminate/3, code_change/4, format_status/2]).
74+ terminate/3, code_change/4]).
75
76 %% FSM States
77 -export(['CONNECT'/3,
78@@ -63,6 +63,12 @@
79 -include("cloudi_core_i_constants.hrl").
80 -include("cloudi_core_i_services_common_types.hrl").
81
82+-ifdef(ERLANG_OTP_VERSION_27_FEATURES).
83+-export([format_status/1]).
84+-else.
85+-export([format_status/2]).
86+-endif.
87+
88 % message type enumeration
89 -define(MESSAGE_INIT, 1).
90 -define(MESSAGE_SEND_ASYNC, 2).
91@@ -1462,21 +1468,27 @@ terminate_pids(_, _) ->
92 code_change(_, StateName, State, _) ->
93 {ok, StateName, State}.
94
95--ifdef(VERBOSE_STATE).
96+-ifdef(ERLANG_OTP_VERSION_27_FEATURES).
97+format_status(Status) ->
98+ maps:update_with(data, fun format_status_state/1, Status).
99+-else.
100 format_status(_Opt, [_PDict, _StateName, State]) ->
101- [{data, [{"State", State}]}].
102+ [{data, [{"State", format_status_state(State)}]}].
103+-endif.
104+
105+-ifdef(VERBOSE_STATE).
106+format_status_state(#state{} = State) ->
107+ State.
108 -else.
109-format_status(_Opt,
110- [_PDict, _StateName,
111- #state{send_timeouts = SendTimeouts,
112- send_timeout_monitors = SendTimeoutMonitors,
113- recv_timeouts = RecvTimeouts,
114- async_responses = AsyncResponses,
115- queued = Queue,
116- cpg_data = Groups,
117- dest_deny = DestDeny,
118- dest_allow = DestAllow,
119- options = ConfigOptions} = State]) ->
120+format_status_state(#state{send_timeouts = SendTimeouts,
121+ send_timeout_monitors = SendTimeoutMonitors,
122+ recv_timeouts = RecvTimeouts,
123+ async_responses = AsyncResponses,
124+ queued = Queue,
125+ cpg_data = Groups,
126+ dest_deny = DestDeny,
127+ dest_allow = DestAllow,
128+ options = ConfigOptions} = State) ->
129 GroupsNew = case Groups of
130 undefined ->
131 undefined;
132@@ -1497,17 +1509,15 @@ format_status(_Opt,
133 end,
134 ConfigOptionsNew = cloudi_core_i_configuration:
135 services_format_options_external(ConfigOptions),
136- [{data,
137- [{"State",
138- State#state{send_timeouts = maps:to_list(SendTimeouts),
139- send_timeout_monitors = maps:to_list(SendTimeoutMonitors),
140- recv_timeouts = maps:to_list(RecvTimeouts),
141- async_responses = maps:to_list(AsyncResponses),
142- queued = cloudi_x_pqueue4:to_plist(Queue),
143- cpg_data = GroupsNew,
144- dest_deny = DestDenyNew,
145- dest_allow = DestAllowNew,
146- options = ConfigOptionsNew}}]}].
147+ State#state{send_timeouts = maps:to_list(SendTimeouts),
148+ send_timeout_monitors = maps:to_list(SendTimeoutMonitors),
149+ recv_timeouts = maps:to_list(RecvTimeouts),
150+ async_responses = maps:to_list(AsyncResponses),
151+ queued = cloudi_x_pqueue4:to_plist(Queue),
152+ cpg_data = GroupsNew,
153+ dest_deny = DestDenyNew,
154+ dest_allow = DestAllowNew,
155+ options = ConfigOptionsNew}.
156 -endif.
157
158 %%%------------------------------------------------------------------------
159diff --git a/src/lib/cloudi_core/src/cloudi_core_i_services_internal.erl b/src/lib/cloudi_core/src/cloudi_core_i_services_internal.erl
160index 46a641d81..3ee84ff9c 100644
161--- a/src/lib/cloudi_core/src/cloudi_core_i_services_internal.erl
162+++ b/src/lib/cloudi_core/src/cloudi_core_i_services_internal.erl
163@@ -10,7 +10,7 @@
164 %%%
165 %%% MIT License
166 %%%
167-%%% Copyright (c) 2011-2023 Michael Truog <mjtruog at protonmail dot com>
168+%%% Copyright (c) 2011-2024 Michael Truog <mjtruog at protonmail dot com>
169 %%%
170 %%% Permission is hereby granted, free of charge, to any person obtaining a
171 %%% copy of this software and associated documentation files (the "Software"),
172@@ -31,8 +31,8 @@
173 %%% DEALINGS IN THE SOFTWARE.
174 %%%
175 %%% @author Michael Truog <mjtruog at protonmail dot com>
176-%%% @copyright 2011-2023 Michael Truog
177-%%% @version 2.0.7 {@date} {@time}
178+%%% @copyright 2011-2024 Michael Truog
179+%%% @version 2.0.8 {@date} {@time}
180 %%%------------------------------------------------------------------------
181
182 -module(cloudi_core_i_services_internal).
183@@ -48,7 +48,7 @@
184 %% gen_server callbacks
185 -export([init/1,
186 handle_call/3, handle_cast/2, handle_info/2,
187- terminate/2, code_change/3, format_status/2]).
188+ terminate/2, code_change/3]).
189
190 %% duo_mode callbacks
191 -export([duo_mode_loop_init/1,
192@@ -68,6 +68,12 @@
193 -include("cloudi_core_i_constants.hrl").
194 -include("cloudi_core_i_services_common_types.hrl").
195
196+-ifdef(ERLANG_OTP_VERSION_27_FEATURES).
197+-export([format_status/1]).
198+-else.
199+-export([format_status/2]).
200+-endif.
201+
202 -record(state,
203 {
204 % state record fields common for cloudi_core_i_services_common.hrl:
205@@ -817,22 +823,8 @@ handle_call(trans_id, _,
206 {TransId, UUIDNew} = cloudi_x_uuid:get_v1(UUID),
207 hibernate_check({reply, TransId, State#state{uuid_generator = UUIDNew}});
208
209-handle_call({get_status, Timeout}, _,
210- #state{dispatcher = Dispatcher,
211- duo_mode_pid = DuoModePid} = State) ->
212- % provide something close to the dispatcher's status to have more
213- % consistency between the DuoModePid, if it exists
214- PDict = erlang:get(),
215- Result = {{status,
216- Dispatcher,
217- {module, gen_server},
218- [PDict,
219- running,
220- undefined, % Parent
221- undefined, % Debug
222- format_status(normal, [PDict, State])]},
223- format_status_duo_mode(DuoModePid, Timeout)},
224- hibernate_check({reply, Result, State});
225+handle_call({get_status, Timeout}, _, State) ->
226+ hibernate_check({reply, sys_get_status(Timeout, State), State});
227
228 handle_call(Request, _, State) ->
229 {stop, cloudi_string:format("Unknown call \"~w\"", [Request]),
230@@ -1870,23 +1862,28 @@ terminate_pids(_, _) ->
231 code_change(_, State, _) ->
232 {ok, State}.
233
234--ifdef(VERBOSE_STATE).
235+-ifdef(ERLANG_OTP_VERSION_27_FEATURES).
236+format_status(Status) ->
237+ maps:update_with(state, fun format_status_state/1, Status).
238+-else.
239 format_status(_Opt, [_PDict, State]) ->
240- [{data,
241- [{"State", State}]}].
242+ [{data, [{"State", format_status_state(State)}]}].
243+-endif.
244+
245+-ifdef(VERBOSE_STATE).
246+format_status_state(#state{} = State) ->
247+ State.
248 -else.
249-format_status(_Opt,
250- [_PDict,
251- #state{send_timeouts = SendTimeouts,
252- send_timeout_monitors = SendTimeoutMonitors,
253- recv_timeouts = RecvTimeouts,
254- async_responses = AsyncResponses,
255- queued = Queue,
256- queued_info = QueueInfo,
257- cpg_data = Groups,
258- dest_deny = DestDeny,
259- dest_allow = DestAllow,
260- options = ConfigOptions} = State]) ->
261+format_status_state(#state{send_timeouts = SendTimeouts,
262+ send_timeout_monitors = SendTimeoutMonitors,
263+ recv_timeouts = RecvTimeouts,
264+ async_responses = AsyncResponses,
265+ queued = Queue,
266+ queued_info = QueueInfo,
267+ cpg_data = Groups,
268+ dest_deny = DestDeny,
269+ dest_allow = DestAllow,
270+ options = ConfigOptions} = State) ->
271 RecvTimeoutsNew = if
272 RecvTimeouts =:= undefined ->
273 undefined;
274@@ -1925,24 +1922,16 @@ format_status(_Opt,
275 end,
276 ConfigOptionsNew = cloudi_core_i_configuration:
277 services_format_options_internal(ConfigOptions),
278- [{data,
279- [{"State",
280- State#state{send_timeouts = maps:to_list(SendTimeouts),
281- send_timeout_monitors = maps:to_list(SendTimeoutMonitors),
282- recv_timeouts = RecvTimeoutsNew,
283- async_responses = maps:to_list(AsyncResponses),
284- queued = QueueNew,
285- queued_info = QueueInfoNew,
286- cpg_data = GroupsNew,
287- dest_deny = DestDenyNew,
288- dest_allow = DestAllowNew,
289- options = ConfigOptionsNew}}]}];
290-format_status(_Opt,
291- [_PDict, _SysState, _Parent, _Debug,
292- #state_duo{} = State]) ->
293- [{data,
294- [{"State",
295- duo_mode_format_state(State)}]}].
296+ State#state{send_timeouts = maps:to_list(SendTimeouts),
297+ send_timeout_monitors = maps:to_list(SendTimeoutMonitors),
298+ recv_timeouts = RecvTimeoutsNew,
299+ async_responses = maps:to_list(AsyncResponses),
300+ queued = QueueNew,
301+ queued_info = QueueInfoNew,
302+ cpg_data = GroupsNew,
303+ dest_deny = DestDenyNew,
304+ dest_allow = DestAllowNew,
305+ options = ConfigOptionsNew}.
306 -endif.
307
308 %%%------------------------------------------------------------------------
309@@ -3426,17 +3415,6 @@ handle_module_info_loop_hibernate(Uses,
310
311 % duo_mode specific logic
312
313-format_status_duo_mode(undefined, _) ->
314- undefined;
315-format_status_duo_mode(DuoModePid, Timeout)
316- when is_pid(DuoModePid) ->
317- case catch sys:get_status(DuoModePid, Timeout) of
318- {status, _, _, _} = Status ->
319- Status;
320- _ ->
321- timeout
322- end.
323-
324 duo_mode_loop_init(#state_duo{duo_mode_pid = DuoModePid,
325 module = Module,
326 dispatcher = Dispatcher} = State) ->
327@@ -3556,20 +3534,51 @@ system_terminate(Reason, _Dispatcher, _Debug, State) ->
328 system_code_change(State, _Module, _VsnOld, _Extra) ->
329 {ok, State}.
330
331-duo_mode_dispatcher_options(ConfigOptions) ->
332- ConfigOptions#config_service_options{
333- rate_request_max = undefined,
334- count_process_dynamic = false,
335- hibernate = false}.
336+sys_get_status(Timeout,
337+ #state{duo_mode_pid = DuoModePid} = State) ->
338+ % provide sys:get_status/2 data for all linked long-lived processes
339+ {sys_get_status_dispatcher(State),
340+ sys_get_status_duo_mode(DuoModePid, Timeout)}.
341+
342+sys_get_status_dispatcher(#state{dispatcher = Dispatcher} = State) ->
343+ % only dispatcher process state is used to provide data similar to
344+ % the sys:get_status/2 output to allow calling
345+ % sys:get_status/2 on other linked processes
346+ PDict = erlang:get(),
347+ {status,
348+ Dispatcher,
349+ {module, gen_server},
350+ [PDict,
351+ running,
352+ undefined, % Parent
353+ undefined, % Debug
354+ format_status_state(State)]}.
355+
356+sys_get_status_duo_mode(undefined, _) ->
357+ undefined;
358+sys_get_status_duo_mode(DuoModePid, Timeout)
359+ when is_pid(DuoModePid) ->
360+ case catch sys:get_status(DuoModePid, Timeout) of
361+ {status, DuoModePid,
362+ {module, cloudi_core_i_services_internal} = ModuleTuple,
363+ StatusItems} ->
364+ [#state_duo{} = State |
365+ StatusItemsReversed] = lists:reverse(StatusItems),
366+ StatusItemsNew = lists:reverse(StatusItemsReversed,
367+ [duo_mode_format_status(State)]),
368+ {status, DuoModePid, ModuleTuple, StatusItemsNew};
369+ _ ->
370+ timeout
371+ end.
372
373 -ifdef(VERBOSE_STATE).
374-duo_mode_format_state(State) ->
375+duo_mode_format_status(State) ->
376 State.
377 -else.
378-duo_mode_format_state(#state_duo{recv_timeouts = RecvTimeouts,
379- queued = Queue,
380- queued_info = QueueInfo,
381- options = ConfigOptions} = State) ->
382+duo_mode_format_status(#state_duo{recv_timeouts = RecvTimeouts,
383+ queued = Queue,
384+ queued_info = QueueInfo,
385+ options = ConfigOptions} = State) ->
386 State#state_duo{recv_timeouts = maps:to_list(RecvTimeouts),
387 queued = cloudi_x_pqueue4:to_plist(Queue),
388 queued_info = queue:to_list(QueueInfo),
389@@ -3577,6 +3586,12 @@ duo_mode_format_state(#state_duo{recv_timeouts = RecvTimeouts,
390 services_format_options_internal(ConfigOptions)}.
391 -endif.
392
393+duo_mode_dispatcher_options(ConfigOptions) ->
394+ ConfigOptions#config_service_options{
395+ rate_request_max = undefined,
396+ count_process_dynamic = false,
397+ hibernate = false}.
398+
399 duo_mode_loop_terminate(Reason,
400 #state_duo{duo_mode_pid = DuoModePid,
401 module = Module,