kernel.erl 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. %% ``The contents of this file are subject to the Erlang Public License,
  2. %% Version 1.1, (the "License"); you may not use this file except in
  3. %% compliance with the License. You should have received a copy of the
  4. %% Erlang Public License along with this software. If not, it can be
  5. %% retrieved via the world wide web at http://www.erlang.org/.
  6. %%
  7. %% Software distributed under the License is distributed on an "AS IS"
  8. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. %% the License for the specific language governing rights and limitations
  10. %% under the License.
  11. %%
  12. %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. %% AB. All Rights Reserved.''
  15. %%
  16. %% $Id$
  17. %%
  18. -module(kernel).
  19. -behaviour(supervisor).
  20. %% External exports
  21. -export([start/2, init/1, stop/1]).
  22. -export([config_change/3]).
  23. %%%-----------------------------------------------------------------
  24. %%% The kernel is the first application started.
  25. %%% Callback functions for the kernel application.
  26. %%%-----------------------------------------------------------------
  27. start(_, []) ->
  28. {ok, _} = gproc:start_local(),
  29. case supervisor:start_link({local, kernel_sup}, kernel, []) of
  30. {ok, Pid} ->
  31. Type = get_error_logger_type(),
  32. error_logger:swap_handler(Type),
  33. {ok, Pid, []};
  34. Error -> Error
  35. end.
  36. stop(_State) ->
  37. ok.
  38. %%-------------------------------------------------------------------
  39. %% Some configuration parameters for kernel are changed
  40. %%-------------------------------------------------------------------
  41. config_change(Changed, New, Removed) ->
  42. do_distribution_change(Changed, New, Removed),
  43. do_global_groups_change(Changed, New, Removed),
  44. ok.
  45. get_error_logger_type() ->
  46. case application:get_env(kernel, error_logger) of
  47. {ok, tty} -> tty;
  48. {ok, {file, File}} when is_list(File) -> {logfile, File};
  49. {ok, false} -> false;
  50. {ok, silent} -> silent;
  51. undefined -> tty; % default value
  52. {ok, Bad} -> exit({bad_config, {kernel, {error_logger, Bad}}})
  53. end.
  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, pg2,
  68. %%% auth, ...) ...)
  69. %%%
  70. %%% The rectangular boxes are supervisors. All supervisors except
  71. %%% for kernel_safe_sup terminates the enitre 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. init([]) ->
  81. SupFlags = {one_for_all, 0, 1},
  82. Config = {kernel_config,
  83. {kernel_config, start_link, []},
  84. permanent, 2000, worker, [kernel_config]},
  85. Code = {code_server,
  86. {code, start_link, get_code_args()},
  87. permanent, 2000, worker, [code]},
  88. File = {file_server_2,
  89. {file_server, start_link, []},
  90. permanent, 2000, worker,
  91. [file, file_server, file_io_server, prim_file]},
  92. User = {user,
  93. {user_sup, start, []},
  94. temporary, 2000, supervisor, [user_sup]},
  95. case init:get_argument(mode) of
  96. {ok, [["minimal"]]} ->
  97. SafeSupervisor = {kernel_safe_sup,
  98. {supervisor, start_link,
  99. [{local, kernel_safe_sup}, ?MODULE, safe]},
  100. permanent, infinity, supervisor, [?MODULE]},
  101. {ok, {SupFlags,
  102. [File, Code, User,
  103. Config, SafeSupervisor]}};
  104. _ ->
  105. Rpc = {rex, {rpc, start_link, []},
  106. permanent, 2000, worker, [rpc]},
  107. Global = {global_name_server, {global, start_link, []},
  108. permanent, 2000, worker, [global]},
  109. Glo_grp = {global_group, {global_group,start_link,[]},
  110. permanent, 2000, worker, [global_group]},
  111. InetDb = {inet_db, {inet_db, start_link, []},
  112. permanent, 2000, worker, [inet_db]},
  113. NetSup = {net_sup, {erl_distribution, start_link, []},
  114. permanent, infinity, supervisor,[erl_distribution]},
  115. DistAC = start_dist_ac(),
  116. GProc = {gproc, {gproc, go_global, []},
  117. permanent, 3000, worker, [gproc]},
  118. Timer = start_timer(),
  119. SafeSupervisor = {kernel_safe_sup,
  120. {supervisor, start_link,
  121. [{local, kernel_safe_sup}, ?MODULE, safe]},
  122. permanent, infinity, supervisor, [?MODULE]},
  123. {ok, {SupFlags,
  124. [Rpc, Global, InetDb | DistAC] ++
  125. [NetSup, Glo_grp, File, Code,
  126. User, Config, GProc, SafeSupervisor] ++ Timer}}
  127. end;
  128. init(safe) ->
  129. SupFlags = {one_for_one, 4, 3600},
  130. Boot = start_boot_server(),
  131. DiskLog = start_disk_log(),
  132. Pg2 = start_pg2(),
  133. {ok, {SupFlags, Boot ++ DiskLog ++ Pg2}}.
  134. get_code_args() ->
  135. case init:get_argument(nostick) of
  136. {ok, [[]]} -> [[nostick]];
  137. _ -> []
  138. end.
  139. start_dist_ac() ->
  140. Spec = [{dist_ac,{dist_ac,start_link,[]},permanent,2000,worker,[dist_ac]}],
  141. case application:get_env(kernel, start_dist_ac) of
  142. {ok, true} -> Spec;
  143. {ok, false} -> [];
  144. undefined ->
  145. case application:get_env(kernel, distributed) of
  146. {ok, _} -> Spec;
  147. _ -> []
  148. end
  149. end.
  150. start_boot_server() ->
  151. case application:get_env(kernel, start_boot_server) of
  152. {ok, true} ->
  153. Args = get_boot_args(),
  154. [{boot_server, {erl_boot_server, start_link, [Args]}, permanent,
  155. 1000, worker, [erl_boot_server]}];
  156. _ ->
  157. []
  158. end.
  159. get_boot_args() ->
  160. case application:get_env(kernel, boot_server_slaves) of
  161. {ok, Slaves} -> Slaves;
  162. _ -> []
  163. end.
  164. start_disk_log() ->
  165. case application:get_env(kernel, start_disk_log) of
  166. {ok, true} ->
  167. [{disk_log_server,
  168. {disk_log_server, start_link, []},
  169. permanent, 2000, worker, [disk_log_server]},
  170. {disk_log_sup, {disk_log_sup, start_link, []}, permanent,
  171. 1000, supervisor, [disk_log_sup]}];
  172. _ ->
  173. []
  174. end.
  175. start_pg2() ->
  176. case application:get_env(kernel, start_pg2) of
  177. {ok, true} ->
  178. [{pg2, {pg2, start_link, []}, permanent, 1000, worker, [pg2]}];
  179. _ ->
  180. []
  181. end.
  182. start_timer() ->
  183. case application:get_env(kernel, start_timer) of
  184. {ok, true} ->
  185. [{timer_server, {timer, start_link, []}, permanent, 1000, worker,
  186. [timer]}];
  187. _ ->
  188. []
  189. end.
  190. %%-----------------------------------------------------------------
  191. %% The change of the distributed parameter is taken care of here
  192. %%-----------------------------------------------------------------
  193. do_distribution_change(Changed, New, Removed) ->
  194. %% check if the distributed parameter is changed. It is not allowed
  195. %% to make a local application to a distributed one, or vice versa.
  196. case is_dist_changed(Changed, New, Removed) of
  197. %%{changed, new, removed}
  198. {false, false, false} ->
  199. ok;
  200. {C, false, false} ->
  201. %% At last, update the parameter.
  202. gen_server:call(dist_ac, {distribution_changed, C}, infinity);
  203. {false, _, false} ->
  204. error_logger:error_report("Distribution not changed: "
  205. "Not allowed to add the 'distributed' "
  206. "parameter."),
  207. {error, {distribution_not_changed, "Not allowed to add the "
  208. "'distributed' parameter"}};
  209. {false, false, _} ->
  210. error_logger:error_report("Distribution not changed: "
  211. "Not allowed to remove the "
  212. "distribution parameter."),
  213. {error, {distribution_not_changed, "Not allowed to remove the "
  214. "'distributed' parameter"}}
  215. end.
  216. %%-----------------------------------------------------------------
  217. %% Check if distribution is changed in someway.
  218. %%-----------------------------------------------------------------
  219. is_dist_changed(Changed, New, Removed) ->
  220. C = case lists:keysearch(distributed, 1, Changed) of
  221. false ->
  222. false;
  223. {value, {distributed, NewDistC}} ->
  224. NewDistC
  225. end,
  226. N = case lists:keysearch(distributed, 1, New) of
  227. false ->
  228. false;
  229. {value, {distributed, NewDistN}} ->
  230. NewDistN
  231. end,
  232. R = lists:member(distributed, Removed),
  233. {C, N, R}.
  234. %%-----------------------------------------------------------------
  235. %% The change of the global_groups parameter is taken care of here
  236. %%-----------------------------------------------------------------
  237. do_global_groups_change(Changed, New, Removed) ->
  238. %% check if the global_groups parameter is changed.
  239. case is_gg_changed(Changed, New, Removed) of
  240. %%{changed, new, removed}
  241. {false, false, false} ->
  242. ok;
  243. {C, false, false} ->
  244. %% At last, update the parameter.
  245. global_group:global_groups_changed(C);
  246. {false, N, false} ->
  247. global_group:global_groups_added(N);
  248. {false, false, R} ->
  249. global_group:global_groups_removed(R)
  250. end.
  251. %%-----------------------------------------------------------------
  252. %% Check if global_groups is changed in someway.
  253. %%-----------------------------------------------------------------
  254. is_gg_changed(Changed, New, Removed) ->
  255. C = case lists:keysearch(global_groups, 1, Changed) of
  256. false ->
  257. false;
  258. {value, {global_groups, NewDistC}} ->
  259. NewDistC
  260. end,
  261. N = case lists:keysearch(global_groups, 1, New) of
  262. false ->
  263. false;
  264. {value, {global_groups, NewDistN}} ->
  265. NewDistN
  266. end,
  267. R = lists:member(global_groups, Removed),
  268. {C, N, R}.