1 |
|
-module(mod_bosh_mnesia). |
2 |
|
|
3 |
|
-behaviour(mod_bosh_backend). |
4 |
|
|
5 |
|
%% mod_bosh_backend callbacks |
6 |
|
-export([start/0, |
7 |
|
create_session/1, |
8 |
|
delete_session/1, |
9 |
|
get_session/1, |
10 |
|
get_sessions/0, |
11 |
|
node_cleanup/1]). |
12 |
|
|
13 |
|
-include("mod_bosh.hrl"). |
14 |
|
|
15 |
|
-spec start() -> any(). |
16 |
|
start() -> |
17 |
104 |
mongoose_mnesia:create_table(bosh_session, |
18 |
|
[{ram_copies, [node()]}, |
19 |
|
{attributes, record_info(fields, bosh_session)}]). |
20 |
|
|
21 |
|
%% The choice of the operation context here (transaction vs dirty, |
22 |
|
%% see man on mnesia:activity/4 for description of contexts) and the deletion |
23 |
|
%% in delete_session/1 below depends on the availability of a load balancer |
24 |
|
%% capable of doing server/session affiliation. |
25 |
|
%% |
26 |
|
%% With affiliation, it suffices for this write to be synchronous, since the |
27 |
|
%% client can issue no subsequent request without a session ID and the ID is |
28 |
|
%% returned to the client only after the dirty synchronous write returns. |
29 |
|
%% Other nodes in the cluster eventually will have the current view of the |
30 |
|
%% database, possibly (significantly) later than the write returns. However, |
31 |
|
%% the only node serving the client in question always operates on valid data. |
32 |
|
%% |
33 |
|
%% Without affiliation, each BOSH/HTTP request may be handled by a different |
34 |
|
%% node in the cluster. Hence, we must guarantee that once the write |
35 |
|
%% operation returns, all nodes in the cluster will have access to currently |
36 |
|
%% valid data -- that's why a transaction is used instead of a dirty write. |
37 |
|
|
38 |
|
-spec create_session(mod_bosh:session()) -> any(). |
39 |
|
create_session(#bosh_session{} = Session) -> |
40 |
126 |
mnesia:sync_transaction(fun mnesia:write/1, [Session]). |
41 |
|
|
42 |
|
|
43 |
|
-spec delete_session(mod_bosh:sid()) -> any(). |
44 |
|
delete_session(Sid) -> |
45 |
126 |
mnesia:transaction(fun mnesia:delete/1, [{bosh_session, Sid}]). |
46 |
|
|
47 |
|
|
48 |
|
-spec get_session(mod_bosh:sid()) -> [mod_bosh:session()]. |
49 |
|
get_session(Sid) -> |
50 |
1942 |
mnesia:dirty_read(bosh_session, Sid). |
51 |
|
|
52 |
|
|
53 |
|
-spec get_sessions() -> [mod_bosh:session()]. |
54 |
|
get_sessions() -> |
55 |
71 |
mnesia:dirty_match_object(mnesia:table_info(bosh_session, wild_pattern)). |
56 |
|
|
57 |
|
-spec node_cleanup(atom()) -> any(). |
58 |
|
node_cleanup(Node) -> |
59 |
8 |
F = fun() -> |
60 |
8 |
SIDs = mnesia:select( |
61 |
|
bosh_session, |
62 |
|
[{#bosh_session{sid = '$1', socket = '$2'}, |
63 |
|
[{'==', {node, '$2'}, Node}], |
64 |
|
['$1']}]), |
65 |
8 |
lists:foreach(fun(SID) -> |
66 |
:-( |
mnesia:delete({bosh_session, SID}) |
67 |
|
end, SIDs) |
68 |
|
end, |
69 |
8 |
mnesia:async_dirty(F). |
70 |
|
|