Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

228 lines (188 sloc) 8.014 kb
%% @author Marc Worrell <marc@worrell.nl>
%% @copyright 2009-2012 Marc Worrell
%% @doc Supervisor for the zotonic application.
%% Copyright 2009-2012 Marc Worrell
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-module(zotonic_sup).
-author('Marc Worrell <marc@worrell.nl>').
-behaviour(supervisor).
-compile([{parse_transform, lager_transform}]).
%% External exports
-export([start_link/0, upgrade/0, upgrade/2]).
%% supervisor callbacks
-export([init/1]).
-include_lib("zotonic.hrl").
%% @spec start_link() -> ServerRet
%% @doc API for starting the supervisor.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%% @spec upgrade(Name, NewSpecs) -> ok
%% @doc Add processes if necessary.
upgrade(SupName, Specs) ->
Old = sets:from_list([Name || {Name, _, _, _} <- supervisor:which_children(SupName)]),
New = sets:from_list([Name || {Name, _, _, _, _, _} <- Specs]),
Kill = sets:subtract(Old, New),
sets:fold(fun (Id, ok) ->
supervisor:terminate_child(SupName, Id),
supervisor:delete_child(SupName, Id),
ok
end, ok, Kill),
[supervisor:start_child(SupName, Spec) || Spec <- Specs],
ok.
%% @spec upgrade() -> ok
%% @doc Add processes if necessary.
upgrade() ->
{ok, {_, Specs}} = init([]),
upgrade(?MODULE, Specs).
%% @spec init([]) -> SupervisorTree
%% @doc supervisor callback.
init([]) ->
{A1,A2,A3} = erlang:now(),
random:seed(A1, A2, A3),
% Random id generation
Ids = {z_ids,
{z_ids, start_link, []},
permanent, 5000, worker, dynamic},
% File based configuration, manages the file priv/config
Config = {z_config,
{z_config, start_link, []},
permanent, 5000, worker, dynamic},
% Image resizer, prevents to many images to be resized at once, bogging the processor.
PreviewServer = {z_media_preview_server,
{z_media_preview_server, start_link, []},
permanent, 5000, worker, dynamic},
% SMTP gen_servers: one for encoding and sending mails, the other for bounces
SmtpServer = {z_email_server,
{z_email_server, start_link, []},
permanent, 5000, worker, dynamic},
% Smtp listen to IP address, Domain and Port
SmtpListenDomain = case os:getenv("ZOTONIC_SMTP_LISTEN_DOMAIN") of
false -> z_config:get_dirty(smtp_listen_domain);
SmtpListenDomain_ -> SmtpListenDomain_
end,
SmtpListenIp = case os:getenv("ZOTONIC_SMTP_LISTEN_IP") of
false -> z_config:get_dirty(smtp_listen_ip);
SmtpListenAny when SmtpListenAny == []; SmtpListenAny == "*"; SmtpListenAny == "any" -> any;
SmtpListenIp_-> SmtpListenIp_
end,
SmtpListenPort = case os:getenv("ZOTONIC_SMTP_LISTEN_PORT") of
false -> z_config:get_dirty(smtp_listen_port);
SmtpListenPort_ -> list_to_integer(SmtpListenPort_)
end,
z_config:set_dirty(smtp_listen_domain, SmtpListenDomain),
z_config:set_dirty(smtp_listen_ip, SmtpListenIp),
z_config:set_dirty(smtp_listen_port, SmtpListenPort),
SmtpBounceServer = {z_email_receive_server,
{z_email_receive_server, start_link, []},
permanent, 5000, worker, dynamic},
% Sites supervisor, starts all enabled sites
SitesSup = {z_sites_sup,
{z_sites_sup, start_link, []},
permanent, 10100, supervisor, dynamic},
Processes = [
Ids, Config, PreviewServer,
SmtpServer, SmtpBounceServer,
SitesSup | get_extensions()
],
% Listen to IP address and Port
WebIp = case os:getenv("ZOTONIC_IP") of
false -> z_config:get_dirty(listen_ip);
Any when Any == []; Any == "*"; Any == "any" -> any;
ConfIP -> ConfIP
end,
WebPort = case os:getenv("ZOTONIC_PORT") of
false -> z_config:get_dirty(listen_port);
Anyport -> list_to_integer(Anyport)
end,
z_config:set_dirty(listen_ip, WebIp),
z_config:set_dirty(listen_port, WebPort),
WebConfig = [
{dispatcher, z_sites_dispatcher},
{dispatch_list, []},
{backlog, z_config:get_dirty(inet_backlog)}
],
% Listen to the ip address and port for all sites.
IPv4Opts = [{port, WebPort}, {ip, WebIp}],
IPv6Opts = [{port, WebPort}, {ip, any6}],
% Webmachine/Mochiweb processes
[IPv4Proc, IPv6Proc] =
[[{Name,
{webmachine_mochiweb, start,
[Name, Opts]},
permanent, 5000, worker, dynamic}]
|| {Name, Opts}
<- [{webmachine_mochiweb, IPv4Opts ++ WebConfig},
{webmachine_mochiweb_v6, IPv6Opts ++ WebConfig}]],
%% When binding to all IP addresses ('any'), bind separately for ipv6 addresses
EnableIPv6 = case WebIp of
any -> ipv6_supported();
_ -> false
end,
Processes1 =
case EnableIPv6 of
true -> Processes ++ IPv4Proc ++ IPv6Proc;
false -> Processes ++ IPv4Proc
end,
init_ua_classifier(),
init_webmachine(),
{ok, {{one_for_one, 1000, 10}, Processes1}}.
%% @doc Initializes the ua classifier. When it is enabled it is loaded and
%% tested if it works.
init_ua_classifier() ->
case z_config:get_dirty(use_ua_classifier) of
true ->
{ok, _Something} = ua_classifier:classify("");
false ->
ok
end.
%% @doc Sets the application parameters for webmachine and starts the logger processes.
%% NOTE: This part has been removed from webmachine_mochiweb:start/2 to avoid
%% messing with application parameters when starting up a new wm-mochiweb process.
init_webmachine() ->
ErrorHandler0 = z_config:get_dirty(webmachine_error_handler),
ErrorHandler =
case ErrorHandler0 of
undefined ->
webmachine_error_handler;
EH -> EH
end,
application:set_env(webzmachine, server_header, webmachine_request:server_header() ++ " Zotonic/" ++ ?ZOTONIC_VERSION),
application:set_env(webzmachine, error_handler, ErrorHandler),
LogDir = z_config:get_dirty(log_dir),
application:set_env(webzmachine, webmachine_logger_module, webmachine_logger),
webmachine_sup:start_logger(LogDir),
case z_config:get_dirty(enable_perf_logger) of
true ->
application:set_env(webzmachine, enable_perf_logger, true),
webmachine_sup:start_perf_logger(LogDir);
_ ->
ignore
end.
%% @todo Exclude platforms that do not support raw ipv6 socket options
ipv6_supported() ->
case (catch inet:getaddr("localhost", inet6)) of
{ok, _Addr} -> true;
{error, _} -> false
end.
%% @doc Scan priv/extensions for ext_ folders and add those as childs to the supervisor.
get_extensions() ->
Files = filelib:wildcard(filename:join([z_utils:lib_dir(priv), "extensions", "ext_*"])),
[
begin
Module = list_to_atom(filename:basename(F)),
{Module,
{Module, start_link, []},
permanent, 5000, worker, dynamic}
end
|| F <- Files].
Jump to Line
Something went wrong with that request. Please try again.