1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2020. 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). 21 22-behaviour(supervisor). 23 24%% External exports 25-export([start/2, init/1, stop/1]). 26-export([config_change/3]). 27 28%%%----------------------------------------------------------------- 29%%% The kernel is the first application started. 30%%% Callback functions for the kernel application. 31%%%----------------------------------------------------------------- 32start(_, []) -> 33 %% Setup the logger and configure the kernel logger environment 34 ok = logger:internal_init_logger(), 35 case supervisor:start_link({local, kernel_sup}, kernel, []) of 36 {ok, Pid} -> 37 ok = erl_signal_handler:start(), 38 ok = logger:add_handlers(kernel), 39 {ok, Pid, []}; 40 Error -> Error 41 end. 42 43stop(_State) -> 44 ok. 45 46%%------------------------------------------------------------------- 47%% Some configuration parameters for kernel are changed 48%%------------------------------------------------------------------- 49config_change(Changed, New, Removed) -> 50 do_distribution_change(Changed, New, Removed), 51 do_global_groups_change(Changed, New, Removed), 52 ok. 53 54%%%----------------------------------------------------------------- 55%%% The process structure in kernel is as shown in the figure. 56%%% 57%%% --------------- 58%%% | kernel_sup (A)| 59%%% --------------- 60%%% | 61%%% ------------------------------- 62%%% | | | 63%%% <std services> ------------- ------------- 64%%% (file,code, | erl_dist (A)| | safe_sup (1)| 65%%% rpc, ...) ------------- ------------- 66%%% | | 67%%% (net_kernel, (disk_log, pg, 68%%% auth, ...) ...) 69%%% 70%%% The rectangular boxes are supervisors. All supervisors except 71%%% for kernel_safe_sup terminates the entire erlang node if any of 72%%% their children dies. Any child that can't be restarted in case 73%%% of failure must be placed under one of these supervisors. Any 74%%% other child must be placed under safe_sup. These children may 75%%% be restarted. Be aware that if a child is restarted the old state 76%%% and all data will be lost. 77%%%----------------------------------------------------------------- 78%%% Callback functions for the kernel_sup supervisor. 79%%%----------------------------------------------------------------- 80 81init([]) -> 82 SupFlags = #{strategy => one_for_all, 83 intensity => 0, 84 period => 1}, 85 86 Config = #{id => kernel_config, 87 start => {kernel_config, start_link, []}, 88 restart => permanent, 89 shutdown => 2000, 90 type => worker, 91 modules => [kernel_config]}, 92 93 RefC = #{id => kernel_refc, 94 start => {kernel_refc, start_link, []}, 95 restart => permanent, 96 shutdown => 2000, 97 type => worker, 98 modules => [kernel_refc]}, 99 100 Code = #{id => code_server, 101 start => {code, start_link, []}, 102 restart => permanent, 103 shutdown => 2000, 104 type => worker, 105 modules => [code]}, 106 107 File = #{id => file_server_2, 108 start => {file_server, start_link, []}, 109 restart => permanent, 110 shutdown => 2000, 111 type => worker, 112 modules => [file, file_server, file_io_server, prim_file]}, 113 114 StdError = #{id => standard_error, 115 start => {standard_error, start_link, []}, 116 restart => temporary, 117 shutdown => 2000, 118 type => supervisor, 119 modules => [standard_error]}, 120 121 User = #{id => user, 122 start => {user_sup, start, []}, 123 restart => temporary, 124 shutdown => 2000, 125 type => supervisor, 126 modules => [user_sup]}, 127 128 SafeSup = #{id => kernel_safe_sup, 129 start =>{supervisor, start_link, [{local, kernel_safe_sup}, ?MODULE, safe]}, 130 restart => permanent, 131 shutdown => infinity, 132 type => supervisor, 133 modules => [?MODULE]}, 134 135 136 LoggerSup = #{id => logger_sup, 137 start => {logger_sup, start_link, []}, 138 restart => permanent, 139 shutdown => infinity, 140 type => supervisor, 141 modules => [logger_sup]}, 142 143 case init:get_argument(mode) of 144 {ok, [["minimal"]|_]} -> 145 {ok, {SupFlags, 146 [Code, File, StdError, User, LoggerSup, Config, RefC, SafeSup]}}; 147 _ -> 148 DistChildren = 149 case application:get_env(kernel, start_distribution) of 150 {ok, false} -> []; 151 _ -> start_distribution() 152 end, 153 154 InetDb = #{id => inet_db, 155 start => {inet_db, start_link, []}, 156 restart => permanent, 157 shutdown => 2000, 158 type => worker, 159 modules => [inet_db]}, 160 161 SigSrv = #{id => erl_signal_server, 162 start => {gen_event, start_link, [{local, erl_signal_server}]}, 163 restart => permanent, 164 shutdown => 2000, 165 type => worker, 166 modules => dynamic}, 167 168 Timer = start_timer(), 169 CompileServer = start_compile_server(), 170 171 {ok, {SupFlags, 172 [Code, InetDb | DistChildren] ++ 173 [File, SigSrv, StdError, User, Config, RefC, SafeSup, LoggerSup] ++ 174 Timer ++ CompileServer}} 175 end; 176init(safe) -> 177 SupFlags = #{strategy => one_for_one, 178 intensity => 4, 179 period => 3600}, 180 181 Boot = start_boot_server(), 182 DiskLog = start_disk_log(), 183 Pg = start_pg2() ++ start_pg(), 184 185 %% Run the on_load handlers for all modules that have been 186 %% loaded so far. Running them at this point means that 187 %% on_load handlers can safely call kernel processes 188 %% (and in particular call code:priv_dir/1 or code:lib_dir/1). 189 init:run_on_load_handlers(), 190 191 {ok, {SupFlags, Boot ++ DiskLog ++ Pg}}. 192 193start_distribution() -> 194 Rpc = #{id => rex, 195 start => {rpc, start_link, []}, 196 restart => permanent, 197 shutdown => 2000, 198 type => worker, 199 modules => [rpc]}, 200 201 Global = #{id => global_name_server, 202 start => {global, start_link, []}, 203 restart => permanent, 204 shutdown => 2000, 205 type => worker, 206 modules => [global]}, 207 208 DistAC = start_dist_ac(), 209 210 NetSup = #{id => net_sup, 211 start => {erl_distribution, start_link, []}, 212 restart => permanent, 213 shutdown => infinity, 214 type => supervisor, 215 modules => [erl_distribution]}, 216 217 GlGroup = #{id => global_group, 218 start => {global_group,start_link,[]}, 219 restart => permanent, 220 shutdown => 2000, 221 type => worker, 222 modules => [global_group]}, 223 224 [Rpc, Global | DistAC] ++ [NetSup, GlGroup]. 225 226start_dist_ac() -> 227 Spec = [#{id => dist_ac, 228 start => {dist_ac,start_link,[]}, 229 restart => permanent, 230 shutdown => 2000, 231 type => worker, 232 modules => [dist_ac]}], 233 case application:get_env(kernel, start_dist_ac) of 234 {ok, true} -> Spec; 235 {ok, false} -> []; 236 undefined -> 237 case application:get_env(kernel, distributed) of 238 {ok, _} -> Spec; 239 _ -> [] 240 end 241 end. 242 243start_boot_server() -> 244 case application:get_env(kernel, start_boot_server) of 245 {ok, true} -> 246 Args = get_boot_args(), 247 [#{id => boot_server, 248 start => {erl_boot_server, start_link, [Args]}, 249 restart => permanent, 250 shutdown => 1000, 251 type => worker, 252 modules => [erl_boot_server]}]; 253 _ -> 254 [] 255 end. 256 257get_boot_args() -> 258 case application:get_env(kernel, boot_server_slaves) of 259 {ok, Slaves} -> Slaves; 260 _ -> [] 261 end. 262 263start_disk_log() -> 264 case application:get_env(kernel, start_disk_log) of 265 {ok, true} -> 266 [#{id => disk_log_server, 267 start => {disk_log_server, start_link, []}, 268 restart => permanent, 269 shutdown => 2000, 270 type => worker, 271 modules => [disk_log_server]}, 272 #{id => disk_log_sup, 273 start => {disk_log_sup, start_link, []}, 274 restart => permanent, 275 shutdown => 1000, 276 type => supervisor, 277 modules => [disk_log_sup]}]; 278 _ -> 279 [] 280 end. 281 282start_pg() -> 283 case application:get_env(kernel, start_pg) of 284 {ok, true} -> 285 [#{id => pg, 286 start => {pg, start_link, []}, 287 restart => permanent, 288 shutdown => 1000, 289 type => worker, 290 modules => [pg]}]; 291 _ -> 292 [] 293 end. 294 295start_pg2() -> 296 case application:get_env(kernel, start_pg2) of 297 {ok, true} -> 298 [#{id => pg2, 299 start => {pg2, start_link, []}, 300 restart => permanent, 301 shutdown => 1000, 302 type => worker, 303 modules => [pg2]}]; 304 _ -> 305 [] 306 end. 307 308start_timer() -> 309 case application:get_env(kernel, start_timer) of 310 {ok, true} -> 311 [#{id => timer_server, 312 start => {timer, start_link, []}, 313 restart => permanent, 314 shutdown => 1000, 315 type => worker, 316 modules => [timer]}]; 317 _ -> 318 [] 319 end. 320 321start_compile_server() -> 322 case application:get_env(kernel, start_compile_server) of 323 {ok, true} -> 324 [#{id => erl_compile_server, 325 start => {erl_compile_server, start_link, []}, 326 restart => permanent, 327 shutdown => 2000, 328 type => worker, 329 modules => [erl_compile_server]}]; 330 _ -> 331 [] 332 end. 333 334%%----------------------------------------------------------------- 335%% The change of the distributed parameter is taken care of here 336%%----------------------------------------------------------------- 337do_distribution_change(Changed, New, Removed) -> 338 %% check if the distributed parameter is changed. It is not allowed 339 %% to make a local application to a distributed one, or vice versa. 340 case is_dist_changed(Changed, New, Removed) of 341 %%{changed, new, removed} 342 {false, false, false} -> 343 ok; 344 {C, false, false} -> 345 %% At last, update the parameter. 346 gen_server:call(dist_ac, {distribution_changed, C}, infinity); 347 {false, _, false} -> 348 error_logger:error_report("Distribution not changed: " 349 "Not allowed to add the 'distributed' " 350 "parameter."), 351 {error, {distribution_not_changed, "Not allowed to add the " 352 "'distributed' parameter"}}; 353 {false, false, _} -> 354 error_logger:error_report("Distribution not changed: " 355 "Not allowed to remove the " 356 "distribution parameter."), 357 {error, {distribution_not_changed, "Not allowed to remove the " 358 "'distributed' parameter"}} 359 end. 360 361%%----------------------------------------------------------------- 362%% Check if distribution is changed in someway. 363%%----------------------------------------------------------------- 364is_dist_changed(Changed, New, Removed) -> 365 C = case lists:keyfind(distributed, 1, Changed) of 366 false -> 367 false; 368 {distributed, NewDistC} -> 369 NewDistC 370 end, 371 N = case lists:keyfind(distributed, 1, New) of 372 false -> 373 false; 374 {distributed, NewDistN} -> 375 NewDistN 376 end, 377 R = lists:member(distributed, Removed), 378 {C, N, R}. 379 380%%----------------------------------------------------------------- 381%% The change of the global_groups parameter is taken care of here 382%%----------------------------------------------------------------- 383do_global_groups_change(Changed, New, Removed) -> 384 %% check if the global_groups parameter is changed. 385 case is_gg_changed(Changed, New, Removed) of 386 %%{changed, new, removed} 387 {false, false, false} -> 388 ok; 389 {C, false, false} -> 390 %% At last, update the parameter. 391 global_group:global_groups_changed(C); 392 {false, N, false} -> 393 global_group:global_groups_added(N); 394 {false, false, R} -> 395 global_group:global_groups_removed(R) 396 end. 397 398%%----------------------------------------------------------------- 399%% Check if global_groups is changed in someway. 400%%----------------------------------------------------------------- 401is_gg_changed(Changed, New, Removed) -> 402 C = case lists:keyfind(global_groups, 1, Changed) of 403 false -> 404 false; 405 {global_groups, NewDistC} -> 406 NewDistC 407 end, 408 N = case lists:keyfind(global_groups, 1, New) of 409 false -> 410 false; 411 {global_groups, NewDistN} -> 412 NewDistN 413 end, 414 R = lists:member(global_groups, Removed), 415 {C, N, R}. 416