1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(kernel_config). 21 22-behaviour(gen_server). 23 24%% External exports 25-export([start_link/0]). 26%% Internal exports 27-export([init/1, handle_info/2, terminate/2, send_timeout/2]). 28-export([handle_call/3, handle_cast/2, code_change/3]). 29 30%%%----------------------------------------------------------------- 31%%% This module implements a process that configures the kernel 32%%% application. 33%%% Its purpose is that in the init phase waits for other nodes at startup, 34%%% if specified. 35%%%----------------------------------------------------------------- 36start_link() -> gen_server:start_link(kernel_config, [], []). 37 38%%----------------------------------------------------------------- 39%% Callback functions from gen_server 40%%----------------------------------------------------------------- 41 42-spec init([]) -> {'ok', []} | {'stop', term()}. 43 44init([]) -> 45 process_flag(trap_exit, true), 46 case sync_nodes() of 47 ok -> 48 case whereis(dist_ac) of 49 DAC when is_pid(DAC) -> 50 DAC ! {go, self()}, 51 receive 52 dist_ac_took_control -> 53 ok 54 end; 55 _ -> 56 ok 57 end, 58 {ok, []}; 59 {error, Error} -> 60 {stop, Error} 61 end. 62 63-spec handle_info(term(), State) -> {'noreply', State}. 64 65handle_info(_, State) -> 66 {noreply, State}. 67 68-spec terminate(term(), term()) -> 'ok'. 69 70terminate(_Reason, _State) -> 71 ok. 72 73-spec handle_call(term(), term(), State) -> {'reply', 'ok', State}. 74 75handle_call('__not_used', _From, State) -> 76 {reply, ok, State}. 77 78-spec handle_cast(term(), State) -> {'noreply', State}. 79 80handle_cast('__not_used', State) -> 81 {noreply, State}. 82 83-spec code_change(term(), State, term()) -> {'ok', State}. 84 85code_change(_OldVsn, State, _Extra) -> 86 {ok, State}. 87 88%%----------------------------------------------------------------- 89%% Internal functions 90%%----------------------------------------------------------------- 91sync_nodes() -> 92 case catch get_sync_data() of 93 {error, Reason} = Error -> 94 error_logger:format("~tp", [Reason]), 95 Error; 96 {infinity, MandatoryNodes, OptionalNodes} -> 97 case wait_nodes(MandatoryNodes, OptionalNodes) of 98 ok -> 99% sync(), 100 ok; 101 Error -> 102 Error 103 end; 104 {Timeout, MandatoryNodes, OptionalNodes} -> 105 spawn_link(kernel_config, send_timeout, [Timeout, self()]), 106 case wait_nodes(MandatoryNodes, OptionalNodes) of 107 ok -> 108% sync(), 109 ok; 110 Error -> 111 Error 112 end; 113 undefined -> ok 114 end. 115 116send_timeout(Timeout, Pid) -> 117 receive 118 after Timeout -> Pid ! timeout 119 end. 120 121wait_nodes(Mandatory, Optional) -> 122 ok = net_kernel:monitor_nodes(true), 123 lists:foreach(fun(Node) -> 124 case net_adm:ping(Node) of 125 pong -> self() ! {nodeup, Node}; 126 _ -> ok 127 end 128 end, 129 Mandatory ++ Optional), 130 R = rec_nodes(Mandatory, Optional), 131 ok = net_kernel:monitor_nodes(false), 132 R. 133 134rec_nodes([], []) -> ok; 135rec_nodes(Mandatory, Optional) -> 136 receive 137 {nodeup, Node} -> check_up(Node, Mandatory, Optional); 138 timeout when Mandatory =:= [] -> ok; 139 timeout -> {error, {mandatory_nodes_down, Mandatory}} 140 end. 141 142check_up(Node, Mandatory, Optional) -> 143 case lists:member(Node, Mandatory) of 144 true -> 145 rec_nodes(lists:delete(Node, Mandatory), Optional); 146 false -> 147 case lists:member(Node, Optional) of 148 true -> 149 rec_nodes(Mandatory, lists:delete(Node, Optional)); 150 false -> 151 rec_nodes(Mandatory, Optional) 152 end 153 end. 154 155%% Syncs standard servers 156%sync() -> 157% global:sync(). 158 159get_sync_data() -> 160 Timeout = get_sync_timeout(), 161 MandatoryNodes = get_sync_mandatory_nodes(), 162 OptionalNodes = get_sync_optional_nodes(), 163 {Timeout, MandatoryNodes, OptionalNodes}. 164 165get_sync_timeout() -> 166 case application:get_env(sync_nodes_timeout) of 167 {ok, Timeout} when is_integer(Timeout), Timeout > 0 -> Timeout; 168 {ok, infinity} -> infinity; 169 undefined -> throw(undefined); 170 {ok, Else} -> throw({error, {badopt, {sync_nodes_timeout, Else}}}) 171 end. 172 173get_sync_mandatory_nodes() -> 174 case application:get_env(sync_nodes_mandatory) of 175 {ok, Nodes} when is_list(Nodes) -> Nodes; 176 undefined -> []; 177 {ok, Else} -> throw({error, {badopt, {sync_nodes_mandatory, Else}}}) 178 end. 179 180get_sync_optional_nodes() -> 181 case application:get_env(sync_nodes_optional) of 182 {ok, Nodes} when is_list(Nodes) -> Nodes; 183 undefined -> []; 184 {ok, Else} -> throw({error, {badopt, {sync_nodes_optional, Else}}}) 185 end. 186 187