* src/web/ejabberd_web_admin.erl: Updated CSS, added modules

management (thanks to Sergei Golovan)

* src/gen_mod.erl: Added function loaded_modules_with_opts/0, new
API for module stopping (thanks to Sergei Golovan)
* src/mod_muc/mod_muc.erl: Moved a process name to a macros,
updated module stopping (thanks to Sergei Golovan)
* src/mod_irc/mod_irc.erl: Likewise
* src/mod_pubsub/mod_pubsub.erl: Likewise
* src/mod_announce.erl: Updated module stopping (thanks to Sergei
Golovan)
* src/mod_echo.erl: Likewise
* src/mod_offline.erl: Likewise

SVN Revision: 354
This commit is contained in:
Alexey Shchepin 2005-05-23 00:30:29 +00:00
parent 94ed3740d9
commit 820c78484a
9 changed files with 176 additions and 29 deletions

View File

@ -1,5 +1,19 @@
2005-05-23 Alexey Shchepin <alexey@sevcom.net>
* src/web/ejabberd_web_admin.erl: Updated CSS, added modules
management (thanks to Sergei Golovan)
* src/gen_mod.erl: Added function loaded_modules_with_opts/0, new
API for module stopping (thanks to Sergei Golovan)
* src/mod_muc/mod_muc.erl: Moved a process name to a macros,
updated module stopping (thanks to Sergei Golovan)
* src/mod_irc/mod_irc.erl: Likewise
* src/mod_pubsub/mod_pubsub.erl: Likewise
* src/mod_announce.erl: Updated module stopping (thanks to Sergei
Golovan)
* src/mod_echo.erl: Likewise
* src/mod_offline.erl: Likewise
* src/web/ejabberd_http.erl: "Connection:" header value now
matched case-insensitive, and returned to client, replaced
duplicate is_space($\r) with is_space($\t) (thanks to Maxim

View File

@ -17,6 +17,7 @@
get_opt/3,
get_module_opt/3,
loaded_modules/0,
loaded_modules_with_opts/0,
get_hosts/2]).
-export([behaviour_info/1]).
@ -52,11 +53,39 @@ stop_module(Module) ->
case catch Module:stop() of
{'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]);
{wait, ProcList} when is_list(ProcList) ->
lists:foreach(fun wait_for_process/1, ProcList),
ets:delete(ejabberd_modules, Module),
ok;
{wait, Process} ->
wait_for_process(Process),
ets:delete(ejabberd_modules, Module),
ok;
_ ->
ets:delete(ejabberd_modules, Module),
ok
end.
wait_for_process(Process) ->
MonitorReference = erlang:monitor(process, Process),
wait_for_stop(Process, MonitorReference).
wait_for_stop(Process, MonitorReference) ->
receive
{'DOWN', MonitorReference, _Type, _Object, _Info} ->
ok
after 5000 ->
catch exit(whereis(Process), kill),
wait_for_stop1(MonitorReference)
end.
wait_for_stop1(MonitorReference) ->
receive
{'DOWN', MonitorReference, _Type, _Object, _Info} ->
ok
after 5000 ->
ok
end.
get_opt(Opt, Opts) ->
case lists:keysearch(Opt, 1, Opts) of
@ -86,7 +115,15 @@ get_module_opt(Module, Opt, Default) ->
loaded_modules() ->
ets:select(ejabberd_modules,
[{#ejabberd_module{_ = '_', module = '$1'}, [],['$1']}]).
[{#ejabberd_module{_ = '_', module = '$1'},
[],
['$1']}]).
loaded_modules_with_opts() ->
ets:select(ejabberd_modules,
[{#ejabberd_module{_ = '_', module = '$1', opts = '$2'},
[],
[{{'$1', '$2'}}]}]).
get_hosts(Opts, Prefix) ->
case catch gen_mod:get_opt(hosts, Opts) of

View File

@ -70,7 +70,7 @@ stop() ->
ejabberd_hooks:delete(sm_register_connection_hook,
?MODULE, send_motd, 50),
exit(whereis(?PROCNAME), stop),
ok.
{wait, ?PROCNAME}.
announce(From, To, Packet) ->
case To of

View File

@ -17,12 +17,12 @@
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(PROCNAME, ejabberd_mod_echo).
start(Opts) ->
%Host = gen_mod:get_opt(host, Opts),
Host = gen_mod:get_opt(host, Opts, "echo." ++ ?MYNAME),
register(ejabberd_mod_echo, spawn(?MODULE, init, [Host])).
register(?PROCNAME, spawn(?MODULE, init, [Host])).
init(Host) ->
ejabberd_router:register_route(Host),
@ -41,5 +41,6 @@ loop(Host) ->
end.
stop() ->
ejabberd_mod_echo ! stop,
ok.
?PROCNAME ! stop,
{wait, ?PROCNAME}.

View File

@ -24,6 +24,8 @@
-record(irc_connection, {jid_server_host, pid}).
-record(irc_custom, {us_host, data}).
-define(PROCNAME, ejabberd_mod_irc).
start(Opts) ->
iconv:start(),
mnesia:create_table(irc_custom,
@ -33,7 +35,7 @@ start(Opts) ->
Host = hd(Hosts),
update_table(Host),
Access = gen_mod:get_opt(access, Opts, all),
register(ejabberd_mod_irc, spawn(?MODULE, init, [Hosts, Access])).
register(?PROCNAME, spawn(?MODULE, init, [Hosts, Access])).
init(Hosts, Access) ->
catch ets:new(irc_connection, [named_table,
@ -172,11 +174,10 @@ do_route1(Host, From, To, Packet) ->
end.
stop() ->
ejabberd_mod_irc ! stop,
ok.
?PROCNAME ! stop,
{wait, ?PROCNAME}.
closed_connection(Host, From, Server) ->
ets:delete(irc_connection, {From, Server, Host}).

View File

@ -30,6 +30,7 @@
-record(muc_online_room, {name_host, pid}).
-record(muc_registered, {us_host, nick}).
-define(PROCNAME, ejabberd_mod_muc).
start(Opts) ->
mnesia:create_table(muc_room,
@ -45,7 +46,7 @@ start(Opts) ->
Access = gen_mod:get_opt(access, Opts, all),
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
register(ejabberd_mod_muc,
register(?PROCNAME,
spawn(?MODULE, init,
[Hosts, {Access, AccessCreate, AccessAdmin}])).
@ -252,12 +253,12 @@ do_route1(Host, Access, From, To, Packet) ->
room_destroyed(Host, Room) ->
ejabberd_mod_muc ! {room_destroyed, {Room, Host}},
?PROCNAME ! {room_destroyed, {Room, Host}},
ok.
stop() ->
ejabberd_mod_muc ! stop,
ok.
?PROCNAME ! stop,
{wait, ?PROCNAME}.
store_room(Host, Name, Opts) ->

View File

@ -89,7 +89,7 @@ stop() ->
ejabberd_hooks:delete(remove_user,
?MODULE, remove_user, 50),
exit(whereis(?PROCNAME), stop),
ok.
{wait, ?PROCNAME}.
store_packet(From, To, Packet) ->
Type = xml:get_tag_attr_s("type", Packet),

View File

@ -35,6 +35,7 @@
subscription = none}).
-record(item, {id, publisher, payload}).
-define(PROCNAME, ejabberd_mod_pubsub).
start(Opts) ->
mnesia:create_table(pubsub_node,
@ -45,7 +46,7 @@ start(Opts) ->
update_table(Host),
mnesia:add_table_index(pubsub_node, host_parent),
ServedHosts = gen_mod:get_opt(served_hosts, Opts, []),
register(ejabberd_mod_pubsub,
register(?PROCNAME,
proc_lib:spawn_link(?MODULE, init, [Hosts, ServedHosts, self()])).
@ -202,8 +203,8 @@ do_route(Host, From, To, Packet) ->
stop() ->
ejabberd_mod_pubsub ! stop,
ok.
?PROCNAME ! stop,
{wait, ?PROCNAME}.

View File

@ -185,12 +185,12 @@ html>body #container {
#navigation ul {
position: absolute;
top: 55px;
top: 54px;
left: 0;
padding: 0 1px 1px;
padding: 0 1px 1px 1px;
margin: 0;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 7.5pt;
font-size: 8pt;
font-weight: bold;
background: #d47911;
width: 13em;
@ -206,9 +206,9 @@ html>body #container {
#navigation ul li a {
margin: 0;
display: block;
padding: 0.25em 0.5em 0.25em 0.75em;
padding: 3px 6px 3px 9px;
border-left: 1em solid #ffc78c;
border-top: 1px solid gray;
border-top: 1px solid #d47911;
background: #ffe3c9;
text-decoration: none;
}
@ -257,7 +257,7 @@ input {
input[type=submit] {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 7pt;
font-size: 8pt;
font-weight: bold;
color: #ffffff;
background-color: #fe8a00;
@ -1683,6 +1683,7 @@ get_node(Node, [], Query, Lang) ->
[?LI([?ACT("db/", "DB Management")]),
?LI([?ACT("backup/", "Backup Management")]),
?LI([?ACT("ports/", "Listened Ports Management")]),
?LI([?ACT("modules/", "Modules Management")]),
?LI([?ACT("stats/", "Statistics")])
]),
?XAE("form", [{"method", "post"}],
@ -1825,6 +1826,28 @@ get_node(Node, ["ports"], Query, Lang) ->
[node_ports_to_xhtml(NewPorts, Lang)])
];
get_node(Node, ["modules"], Query, Lang) ->
Modules = rpc:call(Node, gen_mod, loaded_modules_with_opts, []),
Res = case catch node_modules_parse_query(Node, Modules, Query) of
submitted ->
ok;
{'EXIT', Reason} ->
?INFO_MSG("~p~n", [Reason]),
error;
_ ->
nothing
end,
NewModules = lists:sort(rpc:call(Node, gen_mod, loaded_modules_with_opts, [])),
[?XC("h1", ?T("Modules at ") ++ atom_to_list(Node))] ++
case Res of
ok -> [?CT("submitted"), ?P];
error -> [?CT("bad format"), ?P];
nothing -> []
end ++
[?XAE("form", [{"method", "post"}],
[node_modules_to_xhtml(NewModules, Lang)])
];
get_node(Node, ["stats"], Query, Lang) ->
UpTime = rpc:call(Node, erlang, statistics, [wall_clock]),
UpTimeS = io_lib:format("~.3f", [element(1, UpTime)/1000]),
@ -2041,13 +2064,13 @@ node_ports_parse_query(Node, Ports, Query) ->
Module = list_to_atom(SModule),
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
{ok, Opts} = erl_parse:parse_term(Tokens),
ejabberd_listener:delete_listener(Port),
ejabberd_listener:add_listener(Port, Module, Opts),
rpc:call(Node, ejabberd_listener, delete_listener, [Port]),
rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
throw(submitted);
_ ->
case lists:keysearch("delete" ++ SPort, 1, Query) of
{value, _} ->
ejabberd_listener:delete_listener(Port),
rpc:call(Node, ejabberd_listener, delete_listener, [Port]),
throw(submitted);
_ ->
ok
@ -2066,12 +2089,81 @@ node_ports_parse_query(Node, Ports, Query) ->
Module = list_to_atom(SModule),
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
{ok, Opts} = erl_parse:parse_term(Tokens),
ejabberd_listener:add_listener(Port, Module, Opts),
rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
throw(submitted);
_ ->
ok
end.
node_modules_to_xhtml(Modules, Lang) ->
?XAE("table", [],
[?XE("thead",
[?XE("tr",
[?XCT("td", "Module"),
?XCT("td", "Options")
])]),
?XE("tbody",
lists:map(
fun({Module, Opts} = E) ->
SModule = atom_to_list(Module),
ID = term_to_id(E),
?XE("tr",
[?XC("td", SModule),
?XE("td", [?INPUTS("text", "opts" ++ SModule,
term_to_string(Opts), "40")]),
?XE("td", [?INPUTT("submit", "restart" ++ SModule,
"Restart")]),
?XE("td", [?INPUTT("submit", "stop" ++ SModule,
"Stop")])
]
)
end, Modules) ++
[?XE("tr",
[?XE("td", [?INPUT("text", "modulenew", "")]),
?XE("td", [?INPUTS("text", "optsnew", "", "40")]),
?XAE("td", [{"colspan", "2"}],
[?INPUTT("submit", "start", "Start")])
]
)]
)]).
node_modules_parse_query(Node, Modules, Query) ->
lists:foreach(
fun({Module, _Opts1}) ->
SModule = atom_to_list(Module),
case lists:keysearch("restart" ++ SModule, 1, Query) of
{value, _} ->
{value, {_, SOpts}} =
lists:keysearch("opts" ++ SModule, 1, Query),
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
{ok, Opts} = erl_parse:parse_term(Tokens),
rpc:call(Node, gen_mod, stop_module, [Module]),
rpc:call(Node, gen_mod, start_module, [Module, Opts]),
throw(submitted);
_ ->
case lists:keysearch("stop" ++ SModule, 1, Query) of
{value, _} ->
rpc:call(Node, gen_mod, stop_module, [Module]),
throw(submitted);
_ ->
ok
end
end
end, Modules),
case lists:keysearch("start", 1, Query) of
{value, _} ->
{{value, {_, SModule}},
{value, {_, SOpts}}} =
{lists:keysearch("modulenew", 1, Query),
lists:keysearch("optsnew", 1, Query)},
Module = list_to_atom(SModule),
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
{ok, Opts} = erl_parse:parse_term(Tokens),
rpc:call(Node, gen_mod, start_module, [Module, Opts]),
throw(submitted);
_ ->
ok
end.
pretty_print(El) ->