Skip to content

Commit 55623f4

Browse files
committed
Pre-calculate application start order
This allows us to make some better assertions/logging when starting our application list on what should and should not already be started.
1 parent d96f47d commit 55623f4

File tree

1 file changed

+53
-7
lines changed

1 file changed

+53
-7
lines changed

src/couch/src/test_util.erl

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,19 @@ stop_couch(_) ->
8383
stop_couch().
8484

8585
start_applications(Apps) ->
86-
start_applications(Apps, []).
86+
StartOrder = calculate_start_order(Apps),
87+
start_applications(StartOrder, []).
8788

8889
start_applications([], Acc) ->
8990
lists:reverse(Acc);
91+
start_applications([App|Apps], Acc) when App == kernel; App == stdlib ->
92+
start_applications(Apps, Acc);
9093
start_applications([App|Apps], Acc) ->
9194
case application:start(App) of
92-
{error, {already_started, _}} ->
93-
start_applications(Apps, Acc);
94-
{error, {not_started, Dep}} ->
95-
start_applications([Dep, App | Apps], Acc);
96-
{error, {not_running, Dep}} ->
97-
start_applications([Dep, App | Apps], Acc);
95+
{error, {already_started, App}} ->
96+
io:format(standard_error, "Application ~s was left running!~n", [App]),
97+
application:stop(App),
98+
start_applications([App|Apps], Acc);
9899
ok ->
99100
start_applications(Apps, [App|Acc])
100101
end.
@@ -258,3 +259,48 @@ load_applications_with_stats() ->
258259
stats_file_to_app(File) ->
259260
[_Desc, _Priv, App|_] = lists:reverse(filename:split(File)),
260261
erlang:list_to_atom(App).
262+
263+
calculate_start_order(Apps) ->
264+
AllApps = calculate_start_order(sort_apps(Apps), []),
265+
% AllApps may not be the same list as Apps if we
266+
% loaded any dependencies. We recurse here when
267+
% that changes so that our sort_apps function has
268+
% a global view of all applications to start.
269+
case lists:usort(AllApps) == lists:usort(Apps) of
270+
true -> AllApps;
271+
false -> calculate_start_order(AllApps)
272+
end.
273+
274+
calculate_start_order([], StartOrder) ->
275+
lists:reverse(StartOrder);
276+
calculate_start_order([App | RestApps], StartOrder) ->
277+
NewStartOrder = load_app_deps(App, StartOrder),
278+
calculate_start_order(RestApps, NewStartOrder).
279+
280+
load_app_deps(App, StartOrder) ->
281+
case lists:member(App, StartOrder) of
282+
true ->
283+
StartOrder;
284+
false ->
285+
case application:load(App) of
286+
ok -> ok;
287+
{error, {already_loaded, App}} -> ok
288+
end,
289+
{ok, Apps} = application:get_key(App, applications),
290+
Deps = case App of
291+
kernel -> Apps;
292+
stdlib -> Apps;
293+
_ -> lists:usort([kernel, stdlib | Apps])
294+
end,
295+
NewStartOrder = lists:foldl(fun(Dep, Acc) ->
296+
load_app_deps(Dep, Acc)
297+
end, StartOrder, Deps),
298+
[App | NewStartOrder]
299+
end.
300+
301+
sort_apps(Apps) ->
302+
Weighted = [weight_app(App) || App <- Apps],
303+
element(2, lists:unzip(lists:sort(Weighted))).
304+
305+
weight_app(couch_log) -> {0.0, couch_log};
306+
weight_app(Else) -> {1.0, Else}.

0 commit comments

Comments
 (0)