aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_router.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_router.erl')
-rw-r--r--src/ejabberd_router.erl199
1 files changed, 144 insertions, 55 deletions
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