mirror of
https://github.com/processone/ejabberd.git
synced 2025-01-01 17:53:00 +01:00
* src/mod_muc/mod_muc.erl: Now mod_muc can be distributed on
several nodes * src/mod_muc/mod_muc_room.erl: Likewise * src/ejabberd_router.erl: Added bare_source and bare_destination service balancing options and domain_balancing_component_number option for specifying the number of connected components for the domain * src/ejabberd_config.erl: Likewise SVN Revision: 706
This commit is contained in:
parent
7fb38dd38a
commit
efab31848e
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
2007-01-19 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/mod_muc/mod_muc.erl: Now mod_muc can be distributed on
|
||||||
|
several nodes
|
||||||
|
* src/mod_muc/mod_muc_room.erl: Likewise
|
||||||
|
|
||||||
|
* src/ejabberd_router.erl: Added bare_source and bare_destination
|
||||||
|
service balancing options and domain_balancing_component_number
|
||||||
|
option for specifying the number of connected components for the
|
||||||
|
domain
|
||||||
|
* src/ejabberd_config.erl: Likewise
|
||||||
|
|
||||||
2007-01-11 Mickael Remond <mickael.remond@process-one.net>
|
2007-01-11 Mickael Remond <mickael.remond@process-one.net>
|
||||||
|
|
||||||
* doc/guide.tex: Latex / Hevea related improvements for documentation
|
* doc/guide.tex: Latex / Hevea related improvements for documentation
|
||||||
|
@ -121,9 +121,11 @@ process_term(Term, State) ->
|
|||||||
add_option(cluster_nodes, Nodes, State);
|
add_option(cluster_nodes, Nodes, State);
|
||||||
{domain_balancing, Domain, Balancing} ->
|
{domain_balancing, Domain, Balancing} ->
|
||||||
add_option({domain_balancing, Domain}, Balancing, State);
|
add_option({domain_balancing, Domain}, Balancing, State);
|
||||||
{loglevel, Loglevel} ->
|
{domain_balancing_component_number, Domain, N} ->
|
||||||
ejabberd_loglevel:set(Loglevel),
|
add_option({domain_balancing_component_number, Domain}, N, State);
|
||||||
State;
|
{loglevel, Loglevel} ->
|
||||||
|
ejabberd_loglevel:set(Loglevel),
|
||||||
|
State;
|
||||||
{Opt, Val} ->
|
{Opt, Val} ->
|
||||||
lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end,
|
lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end,
|
||||||
State, State#state.hosts)
|
State, State#state.hosts)
|
||||||
|
@ -56,30 +56,54 @@ route(From, To, Packet) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
register_route(Domain) ->
|
register_route(Domain) ->
|
||||||
case jlib:nameprep(Domain) of
|
register_route(Domain, undefined).
|
||||||
error ->
|
|
||||||
[] = {invalid_domain, Domain};
|
|
||||||
LDomain ->
|
|
||||||
Pid = self(),
|
|
||||||
F = fun() ->
|
|
||||||
mnesia:write(#route{domain = LDomain,
|
|
||||||
pid = Pid})
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F)
|
|
||||||
end.
|
|
||||||
|
|
||||||
register_route(Domain, LocalHint) ->
|
register_route(Domain, LocalHint) ->
|
||||||
case jlib:nameprep(Domain) of
|
case jlib:nameprep(Domain) of
|
||||||
error ->
|
error ->
|
||||||
[] = {invalid_domain, Domain};
|
erlang:error({invalid_domain, Domain});
|
||||||
LDomain ->
|
LDomain ->
|
||||||
Pid = self(),
|
Pid = self(),
|
||||||
F = fun() ->
|
case get_component_number(LDomain) of
|
||||||
mnesia:write(#route{domain = LDomain,
|
undefined ->
|
||||||
pid = Pid,
|
F = fun() ->
|
||||||
local_hint = LocalHint})
|
mnesia:write(#route{domain = LDomain,
|
||||||
end,
|
pid = Pid,
|
||||||
mnesia:transaction(F)
|
local_hint = LocalHint})
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F);
|
||||||
|
N ->
|
||||||
|
F = fun() ->
|
||||||
|
case mnesia:read({route, LDomain}) of
|
||||||
|
[] ->
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
local_hint = 1}),
|
||||||
|
lists:foreach(
|
||||||
|
fun(I) ->
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = undefined,
|
||||||
|
local_hint = I})
|
||||||
|
end, lists:seq(2, N));
|
||||||
|
Rs ->
|
||||||
|
lists:any(
|
||||||
|
fun(#route{pid = undefined,
|
||||||
|
local_hint = I} = R) ->
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
local_hint = I}),
|
||||||
|
mnesia:delete_object(R),
|
||||||
|
true;
|
||||||
|
(_) ->
|
||||||
|
false
|
||||||
|
end, Rs)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F)
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
register_routes(Domains) ->
|
register_routes(Domains) ->
|
||||||
@ -90,14 +114,40 @@ register_routes(Domains) ->
|
|||||||
unregister_route(Domain) ->
|
unregister_route(Domain) ->
|
||||||
case jlib:nameprep(Domain) of
|
case jlib:nameprep(Domain) of
|
||||||
error ->
|
error ->
|
||||||
[] = {invalid_domain, Domain};
|
erlang:error({invalid_domain, Domain});
|
||||||
LDomain ->
|
LDomain ->
|
||||||
Pid = self(),
|
Pid = self(),
|
||||||
F = fun() ->
|
case get_component_number(LDomain) of
|
||||||
mnesia:delete_object(#route{domain = LDomain,
|
undefined ->
|
||||||
pid = Pid})
|
F = fun() ->
|
||||||
end,
|
case mnesia:match(#route{domain = LDomain,
|
||||||
mnesia:transaction(F)
|
pid = Pid,
|
||||||
|
_ = '_'}) of
|
||||||
|
[R] ->
|
||||||
|
mnesia:delete_object(R);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F);
|
||||||
|
_ ->
|
||||||
|
F = fun() ->
|
||||||
|
case mnesia:match(#route{domain = LDomain,
|
||||||
|
pid = Pid,
|
||||||
|
_ = '_'}) of
|
||||||
|
[R] ->
|
||||||
|
I = R#route.local_hint,
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = undefined,
|
||||||
|
local_hint = I}),
|
||||||
|
mnesia:delete_object(R);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F)
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
unregister_routes(Domains) ->
|
unregister_routes(Domains) ->
|
||||||
@ -188,9 +238,21 @@ handle_info({'DOWN', _Ref, _Type, Pid, _Info}, State) ->
|
|||||||
[{#route{pid = Pid, _ = '_'},
|
[{#route{pid = Pid, _ = '_'},
|
||||||
[],
|
[],
|
||||||
['$_']}]),
|
['$_']}]),
|
||||||
lists:foreach(fun(E) ->
|
lists:foreach(
|
||||||
mnesia:delete_object(E)
|
fun(E) ->
|
||||||
end, Es)
|
if
|
||||||
|
is_integer(E#route.local_hint) ->
|
||||||
|
LDomain = E#route.domain,
|
||||||
|
I = E#route.local_hint,
|
||||||
|
mnesia:write(
|
||||||
|
#route{domain = LDomain,
|
||||||
|
pid = undefined,
|
||||||
|
local_hint = I}),
|
||||||
|
mnesia:delete_object(E);
|
||||||
|
true ->
|
||||||
|
mnesia:delete_object(E)
|
||||||
|
end
|
||||||
|
end, Es)
|
||||||
end,
|
end,
|
||||||
mnesia:transaction(F),
|
mnesia:transaction(F),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
@ -237,37 +299,56 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
|
|||||||
_ ->
|
_ ->
|
||||||
Pid ! {route, From, To, Packet}
|
Pid ! {route, From, To, Packet}
|
||||||
end;
|
end;
|
||||||
|
is_pid(Pid) ->
|
||||||
|
Pid ! {route, From, To, Packet};
|
||||||
true ->
|
true ->
|
||||||
Pid ! {route, From, To, Packet}
|
drop
|
||||||
end;
|
end;
|
||||||
Rs ->
|
Rs ->
|
||||||
case [R || R <- Rs, node(R#route.pid) == node()] of
|
Value = case ejabberd_config:get_local_option(
|
||||||
[] ->
|
{domain_balancing, LDstDomain}) of
|
||||||
Value = case ejabberd_config:get_local_option(
|
undefined -> now();
|
||||||
{domain_balancing, LDstDomain}) of
|
random -> now();
|
||||||
source -> jlib:jid_tolower(From);
|
source -> jlib:jid_tolower(From);
|
||||||
destination -> jlib:jid_tolower(To);
|
destination -> jlib:jid_tolower(To);
|
||||||
random -> now();
|
bare_source ->
|
||||||
undefined -> now()
|
jlib:jid_remove_resource(
|
||||||
end,
|
jlib:jid_tolower(From));
|
||||||
R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
|
bare_destination ->
|
||||||
|
jlib:jid_remove_resource(
|
||||||
|
jlib:jid_tolower(To))
|
||||||
|
end,
|
||||||
|
case get_component_number(LDstDomain) of
|
||||||
|
undefined ->
|
||||||
|
case [R || R <- Rs, node(R#route.pid) == node()] of
|
||||||
|
[] ->
|
||||||
|
R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
|
||||||
|
Pid = R#route.pid,
|
||||||
|
if
|
||||||
|
is_pid(Pid) ->
|
||||||
|
Pid ! {route, From, To, Packet};
|
||||||
|
true ->
|
||||||
|
drop
|
||||||
|
end;
|
||||||
|
LRs ->
|
||||||
|
R = lists:nth(erlang:phash(Value, length(LRs)), LRs),
|
||||||
|
Pid = R#route.pid,
|
||||||
|
case R#route.local_hint of
|
||||||
|
{apply, Module, Function} ->
|
||||||
|
Module:Function(From, To, Packet);
|
||||||
|
_ ->
|
||||||
|
Pid ! {route, From, To, Packet}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
SRs = lists:ukeysort(#route.local_hint, Rs),
|
||||||
|
R = lists:nth(erlang:phash(Value, length(SRs)), SRs),
|
||||||
Pid = R#route.pid,
|
Pid = R#route.pid,
|
||||||
Pid ! {route, From, To, Packet};
|
if
|
||||||
LRs ->
|
is_pid(Pid) ->
|
||||||
Value = case ejabberd_config:get_local_option(
|
Pid ! {route, From, To, Packet};
|
||||||
{domain_balancing, LDstDomain}) of
|
true ->
|
||||||
source -> jlib:jid_tolower(From);
|
drop
|
||||||
destination -> jlib:jid_tolower(To);
|
|
||||||
random -> now();
|
|
||||||
undefined -> now()
|
|
||||||
end,
|
|
||||||
R = lists:nth(erlang:phash(Value, length(LRs)), LRs),
|
|
||||||
Pid = R#route.pid,
|
|
||||||
case R#route.local_hint of
|
|
||||||
{apply, Module, Function} ->
|
|
||||||
Module:Function(From, To, Packet);
|
|
||||||
_ ->
|
|
||||||
Pid ! {route, From, To, Packet}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
@ -275,7 +356,15 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
get_component_number(LDomain) ->
|
||||||
|
case ejabberd_config:get_local_option(
|
||||||
|
{domain_balancing_component_number, LDomain}) of
|
||||||
|
N when is_integer(N),
|
||||||
|
N > 1 ->
|
||||||
|
N;
|
||||||
|
_ ->
|
||||||
|
undefined
|
||||||
|
end.
|
||||||
|
|
||||||
update_tables() ->
|
update_tables() ->
|
||||||
case catch mnesia:table_info(route, attributes) of
|
case catch mnesia:table_info(route, attributes) of
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
-export([start_link/2,
|
-export([start_link/2,
|
||||||
start/2,
|
start/2,
|
||||||
stop/1,
|
stop/1,
|
||||||
room_destroyed/3,
|
room_destroyed/4,
|
||||||
store_room/3,
|
store_room/3,
|
||||||
restore_room/2,
|
restore_room/2,
|
||||||
forget_room/2,
|
forget_room/2,
|
||||||
@ -69,9 +69,9 @@ stop(Host) ->
|
|||||||
gen_server:call(Proc, stop),
|
gen_server:call(Proc, stop),
|
||||||
supervisor:delete_child(ejabberd_sup, Proc).
|
supervisor:delete_child(ejabberd_sup, Proc).
|
||||||
|
|
||||||
room_destroyed(Host, Room, ServerHost) ->
|
room_destroyed(Host, Room, Pid, ServerHost) ->
|
||||||
gen_mod:get_module_proc(ServerHost, ?PROCNAME) !
|
gen_mod:get_module_proc(ServerHost, ?PROCNAME) !
|
||||||
{room_destroyed, {Room, Host}},
|
{room_destroyed, {Room, Host}, Pid},
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
store_room(Host, Name, Opts) ->
|
store_room(Host, Name, Opts) ->
|
||||||
@ -142,6 +142,10 @@ init([Host, Opts]) ->
|
|||||||
mnesia:create_table(muc_registered,
|
mnesia:create_table(muc_registered,
|
||||||
[{disc_copies, [node()]},
|
[{disc_copies, [node()]},
|
||||||
{attributes, record_info(fields, muc_registered)}]),
|
{attributes, record_info(fields, muc_registered)}]),
|
||||||
|
mnesia:create_table(muc_online_room,
|
||||||
|
[{ram_copies, [node()]},
|
||||||
|
{attributes, record_info(fields, muc_online_room)}]),
|
||||||
|
mnesia:add_table_copy(muc_online_room, node(), ram_copies),
|
||||||
MyHost = gen_mod:get_opt(host, Opts, "conference." ++ Host),
|
MyHost = gen_mod:get_opt(host, Opts, "conference." ++ Host),
|
||||||
update_tables(MyHost),
|
update_tables(MyHost),
|
||||||
mnesia:add_table_index(muc_registered, nick),
|
mnesia:add_table_index(muc_registered, nick),
|
||||||
@ -149,9 +153,6 @@ init([Host, Opts]) ->
|
|||||||
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
|
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
|
||||||
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
|
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
|
||||||
HistorySize = gen_mod:get_opt(history_size, Opts, 20),
|
HistorySize = gen_mod:get_opt(history_size, Opts, 20),
|
||||||
catch ets:new(muc_online_room, [named_table,
|
|
||||||
public,
|
|
||||||
{keypos, #muc_online_room.name_host}]),
|
|
||||||
ejabberd_router:register_route(MyHost),
|
ejabberd_router:register_route(MyHost),
|
||||||
load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin},
|
load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin},
|
||||||
HistorySize),
|
HistorySize),
|
||||||
@ -199,8 +200,12 @@ handle_info({route, From, To, Packet},
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({room_destroyed, RoomHost}, State) ->
|
handle_info({room_destroyed, RoomHost, Pid}, State) ->
|
||||||
ets:delete(muc_online_room, RoomHost),
|
F = fun() ->
|
||||||
|
mnesia:delete_object(#muc_online_room{name_host = RoomHost,
|
||||||
|
pid = Pid})
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Info, State) ->
|
handle_info(_Info, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
@ -373,7 +378,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
|
|||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
case ets:lookup(muc_online_room, {Room, Host}) of
|
case mnesia:dirty_read(muc_online_room, {Room, Host}) of
|
||||||
[] ->
|
[] ->
|
||||||
Type = xml:get_attr_s("type", Attrs),
|
Type = xml:get_attr_s("type", Attrs),
|
||||||
case {Name, Type} of
|
case {Name, Type} of
|
||||||
@ -385,10 +390,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
|
|||||||
Host, ServerHost, Access,
|
Host, ServerHost, Access,
|
||||||
Room, HistorySize, From,
|
Room, HistorySize, From,
|
||||||
Nick),
|
Nick),
|
||||||
ets:insert(
|
register_room(Host, Room, Pid),
|
||||||
muc_online_room,
|
|
||||||
#muc_online_room{name_host = {Room, Host},
|
|
||||||
pid = Pid}),
|
|
||||||
mod_muc_room:route(Pid, From, Nick, Packet),
|
mod_muc_room:route(Pid, From, Nick, Packet),
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
@ -425,22 +427,32 @@ load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
|
|||||||
?ERROR_MSG("~p", [Reason]),
|
?ERROR_MSG("~p", [Reason]),
|
||||||
ok;
|
ok;
|
||||||
Rs ->
|
Rs ->
|
||||||
lists:foreach(fun(R) ->
|
lists:foreach(
|
||||||
{Room, Host} = R#muc_room.name_host,
|
fun(R) ->
|
||||||
{ok, Pid} = mod_muc_room:start(
|
{Room, Host} = R#muc_room.name_host,
|
||||||
Host,
|
case mnesia:dirty_read(muc_online_room, {Room, Host}) of
|
||||||
ServerHost,
|
[] ->
|
||||||
Access,
|
{ok, Pid} = mod_muc_room:start(
|
||||||
Room,
|
Host,
|
||||||
HistorySize,
|
ServerHost,
|
||||||
R#muc_room.opts),
|
Access,
|
||||||
ets:insert(
|
Room,
|
||||||
muc_online_room,
|
HistorySize,
|
||||||
#muc_online_room{name_host = {Room, Host},
|
R#muc_room.opts),
|
||||||
pid = Pid})
|
register_room(Host, Room, Pid);
|
||||||
end, Rs)
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, Rs)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
register_room(Host, Room, Pid) ->
|
||||||
|
F = fun() ->
|
||||||
|
mnesia:write(#muc_online_room{name_host = {Room, Host},
|
||||||
|
pid = Pid})
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F).
|
||||||
|
|
||||||
|
|
||||||
iq_disco_info() ->
|
iq_disco_info() ->
|
||||||
[{xmlelement, "identity",
|
[{xmlelement, "identity",
|
||||||
@ -598,10 +610,10 @@ broadcast_service_message(Host, Msg) ->
|
|||||||
end, get_vh_rooms(Host)).
|
end, get_vh_rooms(Host)).
|
||||||
|
|
||||||
get_vh_rooms(Host) ->
|
get_vh_rooms(Host) ->
|
||||||
ets:select(muc_online_room,
|
mnesia:dirty_select(muc_online_room,
|
||||||
[{#muc_online_room{name_host = '$1', _ = '_'},
|
[{#muc_online_room{name_host = '$1', _ = '_'},
|
||||||
[{'==', {element, 2, '$1'}, Host}],
|
[{'==', {element, 2, '$1'}, Host}],
|
||||||
['$_']}]).
|
['$_']}]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -677,7 +677,7 @@ handle_info(_Info, StateName, StateData) ->
|
|||||||
%% Returns: any
|
%% Returns: any
|
||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
terminate(_Reason, _StateName, StateData) ->
|
terminate(_Reason, _StateName, StateData) ->
|
||||||
mod_muc:room_destroyed(StateData#state.host, StateData#state.room,
|
mod_muc:room_destroyed(StateData#state.host, StateData#state.room, self(),
|
||||||
StateData#state.server_host),
|
StateData#state.server_host),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user