PageRenderTime 9ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/ucengine/src/backends/pubsub/mnesia/mnesia_pubsub.erl

http://github.com/AF83/ucengine
Erlang | 137 lines | 95 code | 18 blank | 24 comment | 14 complexity | de9106947f8d303cda97f100e59166e9 MD5 | raw file
  1. %%
  2. %% U.C.Engine - Unified Collaboration Engine
  3. %% Copyright (C) 2011 af83
  4. %%
  5. %% This program is free software: you can redistribute it and/or modify
  6. %% it under the terms of the GNU Affero General Public License as published by
  7. %% the Free Software Foundation, either version 3 of the License, or
  8. %% (at your option) any later version.
  9. %%
  10. %% This program is distributed in the hope that it will be useful,
  11. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. %% GNU Affero General Public License for more details.
  14. %%
  15. %% You should have received a copy of the GNU Affero General Public License
  16. %% along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. %%
  18. -module(mnesia_pubsub).
  19. -behaviour(gen_server).
  20. -include_lib("stdlib/include/qlc.hrl").
  21. -export([init/1,
  22. start_link/0,
  23. publish/2,
  24. subscribe/7,
  25. unsubscribe/1,
  26. handle_call/3,
  27. handle_cast/2,
  28. handle_info/2,
  29. code_change/3,
  30. terminate/2]).
  31. -include("uce.hrl").
  32. -record(uce_mnesia_pubsub, {pid, domain, uid, location, type, from, parent}).
  33. start_link() ->
  34. gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  35. publish(Domain, #uce_event{location=Location, type=Type} = Event) ->
  36. ?COUNTER('pubsub:publish'),
  37. %% Publish on the domain
  38. gen_server:cast(?MODULE, {publish, Domain, "", Type, Event}),
  39. case Location of
  40. "" ->
  41. ok;
  42. Location ->
  43. gen_server:cast(?MODULE, {publish, Domain, Location, Type, Event})
  44. end.
  45. subscribe(Pid, Domain, Uid, Location, From, "", Parent) ->
  46. subscribe(Pid, Domain, Uid, Location, From, [""], Parent);
  47. subscribe(Pid, Domain, Uid, Location, From, Types, Parent) ->
  48. ?COUNTER('pubsub:suscribe'),
  49. [gen_server:cast(?MODULE, {subscribe,
  50. Domain,
  51. Uid,
  52. Location,
  53. From,
  54. Type,
  55. Parent,
  56. Pid}) || Type <- Types].
  57. unsubscribe(Pid) ->
  58. ?COUNTER('pubsub:unsubscribe'),
  59. gen_server:cast(?MODULE, {unsubscribe, Pid}).
  60. %
  61. % Gen server callbacks
  62. %
  63. init([]) ->
  64. mnesia:create_table(uce_mnesia_pubsub,
  65. [{ram_copies, [node()]},
  66. {type, bag},
  67. {attributes, record_info(fields, uce_mnesia_pubsub)}]),
  68. {ok, {}}.
  69. handle_call(_Type, _From, State) ->
  70. {reply, error, State}.
  71. handle_cast({publish, Domain, Location, Type, #uce_event{from=From, parent=Parent, to=To} = Event}, State) ->
  72. Subscribers = get_subscribers(Domain, Location, Type, From, Parent, To),
  73. [Subscriber#uce_mnesia_pubsub.pid ! {event, Event} || Subscriber <- Subscribers],
  74. {noreply, State};
  75. handle_cast({subscribe, Domain, Uid, Location, From, Type, Parent, Pid}, State) ->
  76. mnesia:transaction(fun() ->
  77. mnesia:write(#uce_mnesia_pubsub{pid=Pid,
  78. domain=Domain,
  79. uid=Uid,
  80. location=Location,
  81. type=Type,
  82. from=From,
  83. parent=Parent})
  84. end),
  85. {noreply, State};
  86. handle_cast({unsubscribe, Pid}, State) ->
  87. mnesia:transaction(fun() ->
  88. mnesia:delete({uce_mnesia_pubsub, Pid})
  89. end),
  90. {noreply, State}.
  91. code_change(_,State,_) ->
  92. {ok, State}.
  93. handle_info(_Info, State) ->
  94. {reply, State}.
  95. terminate(_Reason, _State) ->
  96. ok.
  97. %
  98. % Private functions
  99. %
  100. get_subscribers(Domain, Location, Type, From, Parent, To) ->
  101. Transaction = fun() ->
  102. Query = qlc:q([Subscriber || #uce_mnesia_pubsub{domain=SubscribedDomain,
  103. uid=SubscribedUid,
  104. location=SubscribedLocation,
  105. type=SubscribedType,
  106. from=SubscribedFrom,
  107. parent=SubscribedParent} = Subscriber
  108. <- mnesia:table(uce_mnesia_pubsub),
  109. (SubscribedDomain == Domain) andalso
  110. (SubscribedLocation == Location) andalso
  111. ((SubscribedType == Type) or (SubscribedType == "")) andalso
  112. ((SubscribedFrom == From) or (SubscribedFrom == "")) andalso
  113. ((SubscribedParent == Parent) or (SubscribedParent == "")) andalso
  114. ((To == "") or (To == SubscribedUid) or (From == SubscribedUid))
  115. ]),
  116. qlc:eval(Query)
  117. end,
  118. {atomic, Subscribers} = mnesia:transaction(Transaction),
  119. Subscribers.