1 |
|
%%% @doc Allocates unique ids for each node. |
2 |
|
-module(ejabberd_node_id). |
3 |
|
-export([start/0, node_id/0, node_id_to_name/1]). |
4 |
|
|
5 |
|
|
6 |
|
-include("mongoose.hrl"). |
7 |
|
-include("jlib.hrl"). |
8 |
|
|
9 |
|
-type nodeid() :: non_neg_integer(). |
10 |
|
-record(node, {name :: atom(), |
11 |
|
id :: nodeid() |
12 |
|
}). |
13 |
|
|
14 |
|
start() -> |
15 |
83 |
mnesia:create_table(node, |
16 |
|
[{ram_copies, [node()]}, |
17 |
|
{type, set}, |
18 |
|
{attributes, record_info(fields, node)}]), |
19 |
83 |
mnesia:add_table_copy(node, node(), ram_copies), |
20 |
83 |
mnesia:add_table_index(node, id), |
21 |
83 |
register_node(node()), |
22 |
83 |
ok. |
23 |
|
|
24 |
|
-spec register_node(atom()) -> 'ok'. |
25 |
|
register_node(NodeName) -> |
26 |
83 |
{atomic, _} = mnesia:transaction(fun() -> |
27 |
83 |
case mnesia:read(node, NodeName) of |
28 |
|
[] -> |
29 |
65 |
mnesia:write(#node{name = NodeName, id = next_node_id()}); |
30 |
18 |
[_] -> ok |
31 |
|
end |
32 |
|
end), |
33 |
83 |
ok. |
34 |
|
|
35 |
|
%% @doc Return an integer node ID. |
36 |
|
-spec node_id() -> {ok, nodeid()}. |
37 |
|
node_id() -> |
38 |
|
%% Save result into the process's memory space. |
39 |
815 |
case get(node_id) of |
40 |
|
undefined -> |
41 |
184 |
{ok, NodeId} = select_node_id(node()), |
42 |
184 |
put(node_id, NodeId), |
43 |
184 |
{ok, NodeId}; |
44 |
|
NodeId -> |
45 |
631 |
{ok, NodeId} |
46 |
|
end. |
47 |
|
|
48 |
|
node_id_to_name(ID) -> |
49 |
1 |
case mnesia:dirty_index_read(node, ID, #node.id) of |
50 |
|
[] -> |
51 |
:-( |
{error, unknown_id}; |
52 |
|
[#node{name = Name}] -> |
53 |
1 |
{ok, Name} |
54 |
|
end. |
55 |
|
|
56 |
|
-spec next_node_id() -> nodeid(). |
57 |
|
next_node_id() -> |
58 |
65 |
max_node_id() + 1. |
59 |
|
|
60 |
|
-spec max_node_id() -> nodeid(). |
61 |
|
max_node_id() -> |
62 |
65 |
mnesia:foldl(fun(#node{id=Id}, Max) -> max(Id, Max) end, 0, node). |
63 |
|
|
64 |
|
-spec select_node_id(NodeName :: atom() |
65 |
|
) -> {'error', 'not_found'} | {'ok', nodeid()}. |
66 |
|
select_node_id(NodeName) -> |
67 |
184 |
case mnesia:dirty_read(node, NodeName) of |
68 |
184 |
[#node{id=Id}] -> {ok, Id}; |
69 |
:-( |
[] -> {error, not_found} |
70 |
|
end. |