Complex gproc queries

Steve Davis steven.charles.davis@REDACTED
Sun Apr 4 13:32:26 CEST 2010


Interesting and useful discussion -- thanks to you both --

Now I'm "on board" with the ideas, the functionality that gproc
provides appears stunningly practical and useful... and, because of
this, I'm left somewhat bemused as to why it hasn't already been
absorbed into the otp platform.

Does anyone know/have a comment on this? Is it something to do with a
back-compat issue with the gen_* patches it requires?

/s



On Apr 3, 9:34 am, Ulf Wiger <ulf.wi...@REDACTED> wrote:
> Pablo Platt wrote:
> > Thank you very much for the detailed answer.
> > gproc is super powerful with QLC.
>
> Thanks. Yes, I think so too.
>
> Now that you seem satisfied with the answer, I copy the list
> again. I didn't want to litter it with my attempts at
> understanding what you were really after.
>
> BR,
> Ulf W
>
>
>
>
>
>
>
> > ------------------------------------------------------------------------
> > *From:* Ulf Wiger <ulf.wi...@REDACTED>
> > *To:* Pablo Platt <pablo.pl...@REDACTED>
> > *Sent:* Sat, April 3, 2010 3:24:01 PM
> > *Subject:* Re: [erlang-questions] Complex gproc queries
>
> > Pablo Platt wrote:
> >  > I think that this assumes that users in the roster are online.
> >  >  > Wouldn't this just be [gproc:send({p,l,Id}, Msg) || Id <- Roster] then
> >  > If some users are not online and the roster is big I'll need to make
> > a lot of queries every time.
>
> > Ok, so let's look at QLC. In this first example, I still assume that
> > you have a list of Ids to check in, so it's pretty much doing the
> > same thing as the snippet above:
>
> > 2> spawn(fun() -> gproc:reg({p,l,foo}), receive die -> die end end).
> > <0.41.0>
> > 3> spawn(fun() -> gproc:reg({p,l,foo}), receive die -> die end end).
> > <0.43.0>
> > 4> spawn(fun() -> gproc:reg({p,l,foo}), receive die -> die end end).
> > <0.45.0>
> > 5> spawn(fun() -> gproc:reg({p,l,foo}), receive die -> die end end).
> > <0.47.0>
> > 6> spawn(fun() -> gproc:reg({p,l,bar}), receive die -> die end end).
> > <0.49.0>
> > 7> spawn(fun() -> gproc:reg({p,l,bar}), receive die -> die end end).
> > <0.51.0>
> > 8> spawn(fun() -> gproc:reg({p,l,bar}), receive die -> die end end).
> > <0.53.0>
> > 9> Q1 = qlc:q([P || {{p,l,X},P,_} <- gproc:table(props),
> >               lists:member(X, [foo])])).
> > {qlc_handle,{qlc_lc,#Fun<erl_eval.20.67289768>,
> >                     {qlc_opt,false,false,-1,any,[],any,524288,allowed}}}
> > 10> qlc:e(Q1).
> > [<0.41.0>,<0.43.0>,<0.45.0>,<0.47.0>]
>
> > Now, let's assume you have a mnesia table that makes up the roster.
> > I don't know the structure of this table, but one possible way to
> > represent it would be to have it as an ordered_set disc_copy,
> > and then use the key {Roster, UserId}.
>
> > 11> mnesia:create_schema([node()]).
> > ok
> > 12> mnesia:start().
> > ok
> > 13> mnesia:create_table(roster,[{ram_copies,[node()]},{type,ordered_set}]).
> > {atomic,ok}
> > 14> mnesia:dirty_write({roster,{r1,foo},[]}).
> > ok
> > 15> catch qlc:e(qlc:q([P || {{p,l,X},P,_} <- gproc:table(props),
> > ets:member(roster,{r1,X})])).
> > [<0.41.0>,<0.43.0>,<0.45.0>,<0.47.0>]
>
> > I used ets:member/2 here, which would only work if executed on a
> > node that actually has a copy in RAM of the roster table, and
> > it doesn't respect any mnesia-level locks. You could write your
> > own function, e.g. is_member(R, UId) that does a mnesia lookup,
> > and then run the query inside a transaction...
>
> > You can make this into a more complex QLC query, but I'm not
> > certain what the performance would be:
>
> > 16> rd(roster,{key,value}).  % define the record in the shell            
> >                       roster
> > 17> Q2 = qlc:q([P ||
> >             {{p,l,X},P,_} <- gproc:table(props),
> >             #roster{key={r1,X1}} <- mnesia:table(roster),
> >             X==X1]).
> > {qlc_handle,{qlc_lc,#Fun<erl_eval.20.67289768>,
> >                     {qlc_opt,false,false,-1,any,[],any,524288,allowed}}}
> > 18> mnesia:activity(transaction, fun() -> qlc:e(Q2) end).
> > [<0.41.0>,<0.43.0>,<0.45.0>,<0.47.0>]
>
> > The above is rather trivially generalized to work with rosters other
> > than 'r1', of course.
>
> > Hope this was more helpful.
>
> > BR,
> > Ulf W
>
> >  > What I thought doing is to first query for a list of users that are
> > both in the roster and online
> >  > and only then send them a message.
>
> >  > ------------------------------------------------------------------------
> >  > *From:* Ulf Wiger <ulf.wi...@REDACTED
> > <mailto:ulf.wi...@REDACTED>>
> >  > *To:* Pablo Platt <pablo.pl...@REDACTED <mailto:pablo.pl...@REDACTED>>
> >  > *Sent:* Sat, April 3, 2010 1:52:36 AM
> >  > *Subject:* Re: [erlang-questions] Complex gproc queries
>
> >  > Ah, I thought you used gproc to keep up with the roster
> >  > as well. :)
>
> >  > Wouldn't this just be [gproc:send({p,l,Id}, Msg) || Id <- Roster] then?
>
> >  > Or am I missing something again? If so, you may respond to me directly.
>
> >  > BTW, I have merged minor changes from Hans Svensson and fixed
> >  > the EQC suite. New commit, in other words.
>
> >  > BR,
> >  > Ulf W
>
> >  > Pablo Platt wrote:
> >  >  >  I should have said that Roster is a list with the contact list IDs
> >  >  > Roster = [id1, id2, id3...]
> >  >  > each user have a different list.
> >  >  > I need to send a message to all the the users in the list that are
> > online.
>
> >  >  > Thanks
>
> > ------------------------------------------------------------------------
> >  >  > *From:* Ulf Wiger <ulf.wi...@REDACTED
> > <mailto:ulf.wi...@REDACTED>
> > <mailto:ulf.wi...@REDACTED
> > <mailto:ulf.wi...@REDACTED>>>
> >  >  > *To:* Pablo Platt <pablo.pl...@REDACTED
> > <mailto:pablo.pl...@REDACTED> <mailto:pablo.pl...@REDACTED
> > <mailto:pablo.pl...@REDACTED>>>
> >  >  > *Cc:* erlang-questi...@REDACTED
> > <mailto:erlang-questi...@REDACTED> <mailto:erlang-questi...@REDACTED
> > <mailto:erlang-questi...@REDACTED>>
> >  >  > *Sent:* Fri, April 2, 2010 7:37:25 PM
> >  >  > *Subject:* Re: [erlang-questions] Complex gproc queries
>
> >  >  > Pablo Platt wrote:
> >  >  >  > Hi,
>
> >  >  >  > I'm building a simple chat server and using gproc to keep track
> > of online users and the process for each user session.
>
> >  >  >  > Basically, each online user has a process that register a
> > unique session id and non unique user id (same user can have several
> > clients):
> >  >  >  > gproc:add_local_name(SessionId)
> >  >  >  > gproc:add_local_property(UserId, undefined)
>
> >  >  >  > When a user change his presence(online/busy/offline) I need to
> > inform all the users on his roster.
> >  >  >  > After I retrieved the roster from the db, how can I select all
> > the processes with UserId that is a part of the roster?
> >  >  >  > Rusty Klupaus's blog about gproc note that gproc:select support
> > QLC but I don't understand how to do it.
>
> >http://rklophaus.com/blog/2009/9/16/gproc-erlang-global-process-regis...
>
> >  >  >  > Thanks
>
> >  >  > Not sure if you need any complex queries for that.
> >  >  > If all members of a roster have a property {p,l,Roster},
> >  >  > then all it should take is:
>
> >  >  > gproc:send({p,l,Roster}, Msg)
>
> >  >  > If you want to e.g. exclude the sender, you could use:
>
> >  >  > [P ! Msg || P <- gproc:lookup_pids({p,l,Roster}) -- [self()]]
>
> >  >  > Disclaimer: When verifying this, I found that gproc:send/2 was
> >  >  > broken for properties. I fixed it in the last commit, 1 minute ago.
>
> >  >  > The commit also changes anther bug: aggregated counters had to
> >  >  > have an integer value when created. This doesn't make sense, since
> >  >  > the value is derived; therefore the only sensible value is
> > 'undefined',
> >  >  > which is what you get if you call gproc:reg({a,l,AggrCounter}).
>
> >  >  > Unfortunately, the commit broke the QuickCheck suite... I had forgot
> >  >  > that I started writing a test for gproc:await/1 at the SF Erlang
> >  >  > factory, didn't finish it. Oh well, if anyone is really hurt by
> >  >  > this condition, let me know. (Hans, I haven't merged your changes
> >  >  > yet).
>
> >  >  > BR,
> >  >  > Ulf W
> >  >  > -- Ulf Wiger
> >  >  > CTO, Erlang Solutions Ltd, formerly Erlang Training & Consulting Ltd
> >> >  http://www.erlang-solutions.com
> >  >  > ---------------------------------------------------
>
> >  >  > ---------------------------------------------------
>
> >  >  > WE'VE CHANGED NAMES!
>
> >  >  > Since January 1st 2010 Erlang Training and Consulting Ltd. has
> > become ERLANG SOLUTIONS LTD.
>
> >  >  >www.erlang-solutions.com<http://www.erlang-solutions.com>
> > <http://www.erlang-solutions.com> <http://www.erlang-solutions.com>
>
> >  > -- Ulf Wiger
> >  > CTO, Erlang Solutions Ltd, formerly Erlang Training & Consulting Ltd
> >  >http://www.erlang-solutions.com
>
> > -- Ulf Wiger
> > CTO, Erlang Solutions Ltd, formerly Erlang Training & Consulting Ltd
> >http://www.erlang-solutions.com
>
> --
> Ulf Wiger
> CTO, Erlang Solutions Ltd, formerly Erlang Training & Consulting Ltdhttp://www.erlang-solutions.com
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> Seehttp://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscr...@REDACTED


More information about the erlang-questions mailing list