aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--src/ejabberd_config.erl8
-rw-r--r--src/ejabberd_router.erl199
-rw-r--r--src/mod_muc/mod_muc.erl74
-rw-r--r--src/mod_muc/mod_muc_room.erl2
5 files changed, 205 insertions, 90 deletions
diff --git a/ChangeLog b/ChangeLog
index 89bc96da6..2765358e2 100644
--- a/ChangeLog
+++ b/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
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index 257cb691a..199f374f3 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -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)
diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl
index 35c8d621c..af2e83f02 100644
--- a/src/ejabberd_router.erl
+++ b/src/ejabberd_router.erl
@@ -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),
- 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),
+ 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,
- 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
diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl
index d5ecb5b91..9a8eadbac 100644
--- a/src/mod_muc/mod_muc.erl
+++ b/src/mod_muc/mod_muc.erl
@@ -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}],
+ ['$_']}]).
diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl
index 2c9f268a6..e2f7d190d 100644
--- a/src/mod_muc/mod_muc_room.erl
+++ b/src/mod_muc/mod_muc_room.erl
@@ -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.