25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-10-31 15:21:38 +01:00

Make hash lookups more robust (EJABS-1965)

Conflicts:

	src/ejabberd_cluster.erl
This commit is contained in:
Evgeniy Khramtsov 2012-12-05 20:28:19 +10:00
parent a9b452fba9
commit d95778ea16

View File

@ -34,6 +34,8 @@
-define(LOCK, {migrate, node()}). -define(LOCK, {migrate, node()}).
-record(state, {}). -record(state, {}).
-record(?HASHTBL, {hash, node}).
-record(?HASHTBL_NEW, {hash, node}).
start() -> start() ->
ChildSpec = {?MODULE, {?MODULE, start_link, []}, ChildSpec = {?MODULE, {?MODULE, start_link, []},
@ -119,9 +121,20 @@ init([]) ->
{A, B, C} = now(), {A, B, C} = now(),
random:seed(A, B, C), random:seed(A, B, C),
net_kernel:monitor_nodes(true, [{node_type, visible}]), net_kernel:monitor_nodes(true, [{node_type, visible}]),
ets:new(?HASHTBL, [named_table, public, ordered_set]), mnesia:create_table(?HASHTBL,
ets:new(?HASHTBL_NEW, [{ram_copies, [node()]},
[named_table, public, ordered_set]), {type, ordered_set},
{local_content, true},
{attributes, record_info(fields, ?HASHTBL)}]),
mnesia:create_table(?HASHTBL_NEW,
[{ram_copies, [node()]},
{type, ordered_set},
{local_content, true},
{attributes, record_info(fields, ?HASHTBL_NEW)}]),
mnesia:add_table_copy(?HASHTBL, node(), ram_copies),
mnesia:add_table_copy(?HASHTBL_NEW, node(), ram_copies),
mnesia:clear_table(?HASHTBL),
mnesia:clear_table(?HASHTBL_NEW),
register_node(), register_node(),
AllNodes = get_nodes(), AllNodes = get_nodes(),
OtherNodes = case AllNodes of OtherNodes = case AllNodes of
@ -210,17 +223,18 @@ append_nodes(Tab, Nodes) ->
Nodes). Nodes).
append_node(Tab, Node) -> append_node(Tab, Node) ->
lists:foreach(fun (I) -> lists:foreach(
Hash = erlang:phash2({I, Node}), fun(I) ->
ets:insert(Tab, {Hash, Node}) Hash = erlang:phash2({I, Node}),
end, mnesia:dirty_write({Tab, Hash, Node})
lists:seq(1, ?POINTS)). end, lists:seq(1, ?POINTS)).
delete_node(Tab, Node) -> delete_node(Tab, Node) ->
lists:foreach(fun (I) -> lists:foreach(
Hash = erlang:phash2({I, Node}), ets:delete(Tab, Hash) fun(I) ->
end, Hash = erlang:phash2({I, Node}),
lists:seq(1, ?POINTS)). mnesia:dirty_delete(Tab, Hash)
end, lists:seq(1, ?POINTS)).
get_node_by_hash(Tab, Hash) -> get_node_by_hash(Tab, Hash) ->
NodeHash = case ets:next(Tab, Hash) of NodeHash = case ets:next(Tab, Hash) of
@ -228,12 +242,14 @@ get_node_by_hash(Tab, Hash) ->
NH -> NH NH -> NH
end, end,
if NodeHash == '$end_of_table' -> if NodeHash == '$end_of_table' ->
erlang:error(no_running_nodes); node();
true -> true ->
case ets:lookup(Tab, NodeHash) of case ets:lookup(Tab, NodeHash) of
[] -> get_node_by_hash(Tab, Hash); [] ->
[{_, Node}] -> Node get_node_by_hash(Tab, Hash);
end [{_, _, Node}] ->
Node
end
end. end.
register_node() -> register_node() ->