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