mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +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>
|
||||
|
||||
* doc/guide.tex: Latex / Hevea related improvements for documentation
|
||||
|
@ -121,9 +121,11 @@ process_term(Term, State) ->
|
||||
add_option(cluster_nodes, Nodes, State);
|
||||
{domain_balancing, Domain, Balancing} ->
|
||||
add_option({domain_balancing, Domain}, Balancing, State);
|
||||
{loglevel, Loglevel} ->
|
||||
ejabberd_loglevel:set(Loglevel),
|
||||
State;
|
||||
{domain_balancing_component_number, Domain, N} ->
|
||||
add_option({domain_balancing_component_number, Domain}, N, State);
|
||||
{loglevel, Loglevel} ->
|
||||
ejabberd_loglevel:set(Loglevel),
|
||||
State;
|
||||
{Opt, Val} ->
|
||||
lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end,
|
||||
State, State#state.hosts)
|
||||
|
@ -56,30 +56,54 @@ route(From, To, Packet) ->
|
||||
end.
|
||||
|
||||
register_route(Domain) ->
|
||||
case jlib:nameprep(Domain) of
|
||||
error ->
|
||||
[] = {invalid_domain, Domain};
|
||||
LDomain ->
|
||||
Pid = self(),
|
||||
F = fun() ->
|
||||
mnesia:write(#route{domain = LDomain,
|
||||
pid = Pid})
|
||||
end,
|
||||
mnesia:transaction(F)
|
||||
end.
|
||||
register_route(Domain, undefined).
|
||||
|
||||
register_route(Domain, LocalHint) ->
|
||||
case jlib:nameprep(Domain) of
|
||||
error ->
|
||||
[] = {invalid_domain, Domain};
|
||||
erlang:error({invalid_domain, Domain});
|
||||
LDomain ->
|
||||
Pid = self(),
|
||||
F = fun() ->
|
||||
mnesia:write(#route{domain = LDomain,
|
||||
pid = Pid,
|
||||
local_hint = LocalHint})
|
||||
end,
|
||||
mnesia:transaction(F)
|
||||
case get_component_number(LDomain) of
|
||||
undefined ->
|
||||
F = fun() ->
|
||||
mnesia:write(#route{domain = LDomain,
|
||||
pid = Pid,
|
||||
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.
|
||||
|
||||
register_routes(Domains) ->
|
||||
@ -90,14 +114,40 @@ register_routes(Domains) ->
|
||||
unregister_route(Domain) ->
|
||||
case jlib:nameprep(Domain) of
|
||||
error ->
|
||||
[] = {invalid_domain, Domain};
|
||||
erlang:error({invalid_domain, Domain});
|
||||
LDomain ->
|
||||
Pid = self(),
|
||||
F = fun() ->
|
||||
mnesia:delete_object(#route{domain = LDomain,
|
||||
pid = Pid})
|
||||
end,
|
||||
mnesia:transaction(F)
|
||||
case get_component_number(LDomain) of
|
||||
undefined ->
|
||||
F = fun() ->
|
||||
case mnesia:match(#route{domain = LDomain,
|
||||
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.
|
||||
|
||||
unregister_routes(Domains) ->
|
||||
@ -188,9 +238,21 @@ handle_info({'DOWN', _Ref, _Type, Pid, _Info}, State) ->
|
||||
[{#route{pid = Pid, _ = '_'},
|
||||
[],
|
||||
['$_']}]),
|
||||
lists:foreach(fun(E) ->
|
||||
mnesia:delete_object(E)
|
||||
end, Es)
|
||||
lists:foreach(
|
||||
fun(E) ->
|
||||
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,
|
||||
mnesia:transaction(F),
|
||||
{noreply, State};
|
||||
@ -237,37 +299,56 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
|
||||
_ ->
|
||||
Pid ! {route, From, To, Packet}
|
||||
end;
|
||||
is_pid(Pid) ->
|
||||
Pid ! {route, From, To, Packet};
|
||||
true ->
|
||||
Pid ! {route, From, To, Packet}
|
||||
drop
|
||||
end;
|
||||
Rs ->
|
||||
case [R || R <- Rs, node(R#route.pid) == node()] of
|
||||
[] ->
|
||||
Value = case ejabberd_config:get_local_option(
|
||||
{domain_balancing, LDstDomain}) of
|
||||
source -> jlib:jid_tolower(From);
|
||||
destination -> jlib:jid_tolower(To);
|
||||
random -> now();
|
||||
undefined -> now()
|
||||
end,
|
||||
R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
|
||||
Value = case ejabberd_config:get_local_option(
|
||||
{domain_balancing, LDstDomain}) of
|
||||
undefined -> now();
|
||||
random -> now();
|
||||
source -> jlib:jid_tolower(From);
|
||||
destination -> jlib:jid_tolower(To);
|
||||
bare_source ->
|
||||
jlib:jid_remove_resource(
|
||||
jlib:jid_tolower(From));
|
||||
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 ! {route, From, To, Packet};
|
||||
LRs ->
|
||||
Value = case ejabberd_config:get_local_option(
|
||||
{domain_balancing, LDstDomain}) of
|
||||
source -> jlib:jid_tolower(From);
|
||||
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}
|
||||
if
|
||||
is_pid(Pid) ->
|
||||
Pid ! {route, From, To, Packet};
|
||||
true ->
|
||||
drop
|
||||
end
|
||||
end
|
||||
end;
|
||||
@ -275,7 +356,15 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
|
||||
ok
|
||||
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() ->
|
||||
case catch mnesia:table_info(route, attributes) of
|
||||
|
@ -17,7 +17,7 @@
|
||||
-export([start_link/2,
|
||||
start/2,
|
||||
stop/1,
|
||||
room_destroyed/3,
|
||||
room_destroyed/4,
|
||||
store_room/3,
|
||||
restore_room/2,
|
||||
forget_room/2,
|
||||
@ -69,9 +69,9 @@ stop(Host) ->
|
||||
gen_server:call(Proc, stop),
|
||||
supervisor:delete_child(ejabberd_sup, Proc).
|
||||
|
||||
room_destroyed(Host, Room, ServerHost) ->
|
||||
room_destroyed(Host, Room, Pid, ServerHost) ->
|
||||
gen_mod:get_module_proc(ServerHost, ?PROCNAME) !
|
||||
{room_destroyed, {Room, Host}},
|
||||
{room_destroyed, {Room, Host}, Pid},
|
||||
ok.
|
||||
|
||||
store_room(Host, Name, Opts) ->
|
||||
@ -142,6 +142,10 @@ init([Host, Opts]) ->
|
||||
mnesia:create_table(muc_registered,
|
||||
[{disc_copies, [node()]},
|
||||
{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),
|
||||
update_tables(MyHost),
|
||||
mnesia:add_table_index(muc_registered, nick),
|
||||
@ -149,9 +153,6 @@ init([Host, Opts]) ->
|
||||
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
|
||||
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
|
||||
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),
|
||||
load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin},
|
||||
HistorySize),
|
||||
@ -199,8 +200,12 @@ handle_info({route, From, To, Packet},
|
||||
ok
|
||||
end,
|
||||
{noreply, State};
|
||||
handle_info({room_destroyed, RoomHost}, State) ->
|
||||
ets:delete(muc_online_room, RoomHost),
|
||||
handle_info({room_destroyed, RoomHost, Pid}, State) ->
|
||||
F = fun() ->
|
||||
mnesia:delete_object(#muc_online_room{name_host = RoomHost,
|
||||
pid = Pid})
|
||||
end,
|
||||
mnesia:transaction(F),
|
||||
{noreply, State};
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
@ -373,7 +378,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
|
||||
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),
|
||||
case {Name, Type} of
|
||||
@ -385,10 +390,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
|
||||
Host, ServerHost, Access,
|
||||
Room, HistorySize, From,
|
||||
Nick),
|
||||
ets:insert(
|
||||
muc_online_room,
|
||||
#muc_online_room{name_host = {Room, Host},
|
||||
pid = Pid}),
|
||||
register_room(Host, Room, Pid),
|
||||
mod_muc_room:route(Pid, From, Nick, Packet),
|
||||
ok;
|
||||
_ ->
|
||||
@ -425,22 +427,32 @@ load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
|
||||
?ERROR_MSG("~p", [Reason]),
|
||||
ok;
|
||||
Rs ->
|
||||
lists:foreach(fun(R) ->
|
||||
{Room, Host} = R#muc_room.name_host,
|
||||
{ok, Pid} = mod_muc_room:start(
|
||||
Host,
|
||||
ServerHost,
|
||||
Access,
|
||||
Room,
|
||||
HistorySize,
|
||||
R#muc_room.opts),
|
||||
ets:insert(
|
||||
muc_online_room,
|
||||
#muc_online_room{name_host = {Room, Host},
|
||||
pid = Pid})
|
||||
end, Rs)
|
||||
lists:foreach(
|
||||
fun(R) ->
|
||||
{Room, Host} = R#muc_room.name_host,
|
||||
case mnesia:dirty_read(muc_online_room, {Room, Host}) of
|
||||
[] ->
|
||||
{ok, Pid} = mod_muc_room:start(
|
||||
Host,
|
||||
ServerHost,
|
||||
Access,
|
||||
Room,
|
||||
HistorySize,
|
||||
R#muc_room.opts),
|
||||
register_room(Host, Room, Pid);
|
||||
_ ->
|
||||
ok
|
||||
end
|
||||
end, Rs)
|
||||
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() ->
|
||||
[{xmlelement, "identity",
|
||||
@ -598,10 +610,10 @@ broadcast_service_message(Host, Msg) ->
|
||||
end, get_vh_rooms(Host)).
|
||||
|
||||
get_vh_rooms(Host) ->
|
||||
ets:select(muc_online_room,
|
||||
[{#muc_online_room{name_host = '$1', _ = '_'},
|
||||
[{'==', {element, 2, '$1'}, Host}],
|
||||
['$_']}]).
|
||||
mnesia:dirty_select(muc_online_room,
|
||||
[{#muc_online_room{name_host = '$1', _ = '_'},
|
||||
[{'==', {element, 2, '$1'}, Host}],
|
||||
['$_']}]).
|
||||
|
||||
|
||||
|
||||
|
@ -677,7 +677,7 @@ handle_info(_Info, StateName, StateData) ->
|
||||
%% Returns: any
|
||||
%%----------------------------------------------------------------------
|
||||
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),
|
||||
ok.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user