aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/kernel_config.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src/kernel_config.erl')
-rw-r--r--lib/kernel/src/kernel_config.erl173
1 files changed, 173 insertions, 0 deletions
diff --git a/lib/kernel/src/kernel_config.erl b/lib/kernel/src/kernel_config.erl
new file mode 100644
index 0000000000..e5e9a0498d
--- /dev/null
+++ b/lib/kernel/src/kernel_config.erl
@@ -0,0 +1,173 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(kernel_config).
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0]).
+%% Internal exports
+-export([init/1, handle_info/2, terminate/2, send_timeout/2]).
+-export([handle_call/3, handle_cast/2, code_change/3]).
+
+%%%-----------------------------------------------------------------
+%%% This module implements a process that configures the kernel
+%%% application.
+%%% Its purpose is that in the init phase add an error_logger
+%%% and when it dies (when the kernel application dies) deleting the
+%%% previously installed error_logger.
+%%% Also, this process waits for other nodes at startup, if
+%%% specified.
+%%%-----------------------------------------------------------------
+start_link() -> gen_server:start_link(kernel_config, [], []).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ case sync_nodes() of
+ ok ->
+ case whereis(dist_ac) of
+ DAC when is_pid(DAC) ->
+ DAC ! {go, self()},
+ receive
+ dist_ac_took_control ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ {ok, []};
+ {error, Error} ->
+ {stop, Error}
+ end.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+handle_call('__not_used', _From, State) ->
+ {reply, ok, State}.
+
+handle_cast('__not_used', State) ->
+ {noreply, State}.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+sync_nodes() ->
+ case catch get_sync_data() of
+ {error, Reason} ->
+ error_logger:format("~p", [Reason]),
+ {error, Reason};
+ {infinity, MandatoryNodes, OptionalNodes} ->
+ case wait_nodes(MandatoryNodes, OptionalNodes) of
+ ok ->
+% sync(),
+ ok;
+ Error ->
+ Error
+ end;
+ {Timeout, MandatoryNodes, OptionalNodes} ->
+ spawn_link(kernel_config, send_timeout, [Timeout, self()]),
+ case wait_nodes(MandatoryNodes, OptionalNodes) of
+ ok ->
+% sync(),
+ ok;
+ Error ->
+ Error
+ end;
+ undefined -> ok
+ end.
+
+send_timeout(Timeout, Pid) ->
+ receive
+ after Timeout -> Pid ! timeout
+ end.
+
+wait_nodes(Mandatory, Optional) ->
+ net_kernel:monitor_nodes(true),
+ lists:foreach(fun(Node) ->
+ case net_adm:ping(Node) of
+ pong -> self() ! {nodeup, Node};
+ _ -> ok
+ end
+ end,
+ Mandatory ++ Optional),
+ rec_nodes(Mandatory, Optional).
+
+rec_nodes([], []) -> ok;
+rec_nodes(Mandatory, Optional) ->
+ receive
+ {nodeup, Node} -> check_up(Node, Mandatory, Optional);
+ timeout when Mandatory =:= [] -> ok;
+ timeout -> {error, {mandatory_nodes_down, Mandatory}}
+ end.
+
+check_up(Node, Mandatory, Optional) ->
+ case lists:member(Node, Mandatory) of
+ true ->
+ rec_nodes(lists:delete(Node, Mandatory), Optional);
+ false ->
+ case lists:member(Node, Optional) of
+ true ->
+ rec_nodes(Mandatory, lists:delete(Node, Optional));
+ false ->
+ rec_nodes(Mandatory, Optional)
+ end
+ end.
+
+%% Syncs standard servers
+%sync() ->
+% global:sync().
+
+get_sync_data() ->
+ Timeout = get_sync_timeout(),
+ MandatoryNodes = get_sync_mandatory_nodes(),
+ OptionalNodes = get_sync_optional_nodes(),
+ {Timeout, MandatoryNodes, OptionalNodes}.
+
+get_sync_timeout() ->
+ case application:get_env(sync_nodes_timeout) of
+ {ok, Timeout} when is_integer(Timeout), Timeout > 0 -> Timeout;
+ {ok, infinity} -> infinity;
+ undefined -> throw(undefined);
+ {ok, Else} -> throw({error, {badopt, {sync_nodes_timeout, Else}}})
+ end.
+
+get_sync_mandatory_nodes() ->
+ case application:get_env(sync_nodes_mandatory) of
+ {ok, Nodes} when is_list(Nodes) -> Nodes;
+ undefined -> [];
+ {ok, Else} -> throw({error, {badopt, {sync_nodes_mandatory, Else}}})
+ end.
+
+get_sync_optional_nodes() ->
+ case application:get_env(sync_nodes_optional) of
+ {ok, Nodes} when is_list(Nodes) -> Nodes;
+ undefined -> [];
+ {ok, Else} -> throw({error, {badopt, {sync_nodes_optional, Else}}})
+ end.
+