PageRenderTime 22ms CodeModel.GetById 2ms app.highlight 17ms RepoModel.GetById 1ms 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
 20-behaviour(gen_server).
 21
 22-include_lib("stdlib/include/qlc.hrl").
 23
 24-export([init/1,
 25         start_link/0,
 26         publish/2,
 27         subscribe/7,
 28         unsubscribe/1,
 29         handle_call/3,
 30         handle_cast/2,
 31         handle_info/2,
 32         code_change/3,
 33         terminate/2]).
 34
 35-include("uce.hrl").
 36
 37-record(uce_mnesia_pubsub, {pid, domain, uid, location, type, from, parent}).
 38
 39start_link() ->
 40    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 41
 42publish(Domain, #uce_event{location=Location, type=Type} = Event) ->
 43    ?COUNTER('pubsub:publish'),
 44    %% Publish on the domain
 45    gen_server:cast(?MODULE, {publish, Domain, "", Type, Event}),
 46    case Location of
 47        "" ->
 48            ok;
 49        Location ->
 50            gen_server:cast(?MODULE, {publish, Domain, Location, Type, Event})
 51    end.
 52
 53subscribe(Pid, Domain, Uid, Location, From, "", Parent) ->
 54    subscribe(Pid, Domain, Uid, Location, From, [""], Parent);
 55subscribe(Pid, Domain, Uid, Location, From, Types, Parent) ->
 56    ?COUNTER('pubsub:suscribe'),
 57    [gen_server:cast(?MODULE, {subscribe,
 58                               Domain,
 59                               Uid,
 60                               Location,
 61                               From,
 62                               Type,
 63                               Parent,
 64                               Pid}) || Type <- Types].
 65
 66unsubscribe(Pid) ->
 67    ?COUNTER('pubsub:unsubscribe'),
 68    gen_server:cast(?MODULE, {unsubscribe, Pid}).
 69
 70%
 71% Gen server callbacks
 72%
 73
 74init([]) ->
 75    mnesia:create_table(uce_mnesia_pubsub,
 76                        [{ram_copies, [node()]},
 77                         {type, bag},
 78                         {attributes, record_info(fields, uce_mnesia_pubsub)}]),
 79    {ok, {}}.
 80
 81handle_call(_Type, _From, State) ->
 82    {reply, error, State}.
 83
 84handle_cast({publish, Domain, Location, Type, #uce_event{from=From, parent=Parent, to=To} = Event}, State) ->
 85    Subscribers = get_subscribers(Domain, Location, Type, From, Parent, To),
 86    [Subscriber#uce_mnesia_pubsub.pid ! {event, Event} || Subscriber <- Subscribers],
 87    {noreply, State};
 88handle_cast({subscribe, Domain, Uid, Location, From, Type, Parent, Pid}, State) ->
 89    mnesia:transaction(fun() ->
 90                               mnesia:write(#uce_mnesia_pubsub{pid=Pid,
 91                                                               domain=Domain,
 92                                                               uid=Uid,
 93                                                               location=Location,
 94                                                               type=Type,
 95                                                               from=From,
 96                                                               parent=Parent})
 97                       end),
 98    {noreply, State};
 99handle_cast({unsubscribe, Pid}, State) ->
100    mnesia:transaction(fun() ->
101                               mnesia:delete({uce_mnesia_pubsub, Pid})
102                       end),
103    {noreply, State}.
104
105code_change(_,State,_) ->
106    {ok, State}.
107
108handle_info(_Info, State) ->
109    {reply, State}.
110
111terminate(_Reason, _State) ->
112    ok.
113
114%
115% Private functions
116%
117
118get_subscribers(Domain, Location, Type, From, Parent, To) ->
119    Transaction = fun() ->
120                          Query = qlc:q([Subscriber || #uce_mnesia_pubsub{domain=SubscribedDomain,
121                                                                          uid=SubscribedUid,
122                                                                          location=SubscribedLocation,
123                                                                          type=SubscribedType,
124                                                                          from=SubscribedFrom,
125                                                                          parent=SubscribedParent} = Subscriber
126                                                           <- mnesia:table(uce_mnesia_pubsub),
127                                                (SubscribedDomain == Domain) andalso
128                                                (SubscribedLocation == Location) andalso
129                                                ((SubscribedType == Type) or (SubscribedType == "")) andalso
130                                                ((SubscribedFrom == From) or (SubscribedFrom == "")) andalso
131                                                ((SubscribedParent == Parent) or (SubscribedParent == "")) andalso
132                                                ((To == "") or (To == SubscribedUid) or (From == SubscribedUid))
133                                        ]),
134                          qlc:eval(Query)
135                  end,
136    {atomic, Subscribers} = mnesia:transaction(Transaction),
137    Subscribers.