From dffe80889500a5e0f749cc57289091edacbc208f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 19 May 2009 21:59:15 +0000 Subject: [PATCH] PubSub: improve get_entity_* API SVN Revision: 2090 --- src/mod_pubsub/mod_pubsub.erl | 73 ++++++++++++++--------------- src/mod_pubsub/node_default.erl | 47 +++++++++++-------- src/mod_pubsub/node_pep.erl | 33 ++++++++++--- src/mod_pubsub/nodetree_virtual.erl | 12 ++--- src/mod_pubsub/pubsub.hrl | 12 ++--- 5 files changed, 99 insertions(+), 78 deletions(-) diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index df009d8da..4129fd628 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -225,9 +225,9 @@ init_plugins(Host, ServerHost, Opts) -> gen_mod:get_opt(nodetree, Opts, ?STDTREE)), ?DEBUG("** tree plugin is ~p",[TreePlugin]), TreePlugin:init(Host, ServerHost, Opts), - Plugins = lists:usort(gen_mod:get_opt(plugins, Opts, []) ++ [?STDNODE]), - PepMapping = lists:usort(gen_mod:get_opt(pep_mapping, Opts, [])), - ?DEBUG("** PEP Mapping : ~p~n",[PepMapping]), + Plugins = gen_mod:get_opt(plugins, Opts, [?STDNODE]), + PepMapping = gen_mod:get_opt(pep_mapping, Opts, []), + ?DEBUG("** PEP Mapping : ~p~n",[PepMapping]), lists:foreach(fun(Name) -> ?DEBUG("** init ~s plugin",[Name]), Plugin = list_to_atom(?PLUGIN_PREFIX ++ Name), @@ -387,14 +387,10 @@ send_loop(State) -> lists:foreach( fun({Node, subscribed, SubJID}) -> if (SubJID == LJID) or (SubJID == BJID) -> - case tree_action(Host, get_node, [Host, Node, JID]) of - #pubsub_node{options = Options, type = Type, id = NodeId} -> - case get_option(Options, send_last_published_item) of - on_sub_and_presence -> - send_items(Host, Node, NodeId, Type, SubJID, last); - _ -> - ok - end; + #pubsub_node{options = Options, type = Type, id = NodeId} = Node, + case get_option(Options, send_last_published_item) of + on_sub_and_presence -> + send_items(Host, Node, NodeId, Type, SubJID, last); _ -> ok end; @@ -700,19 +696,20 @@ handle_cast({remove_user, LUser, LServer}, State) -> lists:foreach(fun(PType) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]), lists:foreach(fun - ({Node, subscribed, JID}) -> - unsubscribe_node(Host, Node, Owner, JID, all); - (_) -> + ({#pubsub_node{nodeid = {H, N}}, subscribed, JID}) -> + unsubscribe_node(H, N, Owner, JID, all); + (_) -> ok - end, Subscriptions) + end, Subscriptions), + {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Owner]), + lists:foreach(fun + ({#pubsub_node{nodeid = {H, N}}, owner}) -> + delete_node(H, N, Owner); + (_) -> + ok + end, Affiliations) end, State#state.plugins), - %% remove user's PEP nodes - lists:foreach(fun(#pubsub_node{nodeid={NodeKey, NodeName}}) -> - delete_node(NodeKey, NodeName, Owner) - end, tree_action(Host, get_nodes, [jlib:jid_tolower(Owner), Owner])), - %% remove user's nodes - delete_node(Host, ["home", LServer, LUser], Owner), - {noreply, State}; + {noreply, State}; handle_cast({unsubscribe, Subscriber, Owner}, State) -> Host = State#state.host, @@ -721,20 +718,18 @@ handle_cast({unsubscribe, Subscriber, Owner}, State) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), lists:foreach(fun ({Node, subscribed, JID}) -> - Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId}) -> - case get_option(Options, access_model) of - presence -> - case lists:member(BJID, Owners) of - true -> - node_call(Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); - false -> - {result, ok} - end; - _ -> - {result, ok} - end - end, - transaction(Host, Node, Action, sync_dirty); + #pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId} = Node, + case get_option(Options, access_model) of + presence -> + case lists:member(BJID, Owners) of + true -> + node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); + false -> + {result, ok} + end; + _ -> + {result, ok} + end; (_) -> ok end, Subscriptions) @@ -2036,7 +2031,7 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> {ok, Affiliations} -> Entities = lists:flatmap( fun({_, none}) -> []; - ({Node, Affiliation}) -> + ({#pubsub_node{nodeid = {_, Node}}, Affiliation}) -> [{xmlelement, "affiliation", [{"affiliation", affiliation_to_string(Affiliation)}|nodeAttr(Node)], []}] @@ -2175,7 +2170,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> Entities = lists:flatmap( fun({_, none}) -> []; - ({SubsNode, Subscription}) -> + ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) -> case Node of [] -> [{xmlelement, "subscription", @@ -2190,7 +2185,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> end; ({_, none, _}) -> []; - ({SubsNode, Subscription, SubJID}) -> + ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) -> case Node of [] -> [{xmlelement, "subscription", diff --git a/src/mod_pubsub/node_default.erl b/src/mod_pubsub/node_default.erl index e7dd56900..ad7ad73bf 100644 --- a/src/mod_pubsub/node_default.erl +++ b/src/mod_pubsub/node_default.erl @@ -549,16 +549,22 @@ purge_node(NodeId, Owner) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% pubsub_state table.

-get_entity_affiliations(_Host, Owner) -> +get_entity_affiliations(Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - States = mnesia:match_object( - %% TODO check if Host needed - #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), - Tr = fun(#pubsub_state{stateid = {_, N}, affiliation = A}) -> - {get_nodename(N), A} - end, - {result, lists:map(Tr, States)}. + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), + Reply = lists:foldl(fun(#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> + case mnesia:index_read(pubsub_node, N, #pubsub_node.id) of + [#pubsub_node{nodeid = {H, _}} = Node] -> + case H of + Host -> [{Node, A}|Acc]; + _ -> Acc + end; + _ -> + Acc + end + end, [], States), + {result, Reply}. get_node_affiliations(NodeId) -> {result, States} = get_states(NodeId), @@ -594,7 +600,7 @@ set_affiliation(NodeId, Owner, Affiliation) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% pubsub_state table.

-get_entity_subscriptions(_Host, Owner) -> +get_entity_subscriptions(Host, Owner) -> {U, D, _} = SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), States = case SubKey of @@ -605,10 +611,18 @@ get_entity_subscriptions(_Host, Owner) -> ++ mnesia:match_object( #pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) end, - Tr = fun(#pubsub_state{stateid = {J, N}, subscription = S}) -> - {get_nodename(N), S, J} - end, - {result, lists:map(Tr, States)}. + Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscription = S}, Acc) -> + case mnesia:index_read(pubsub_node, N, #pubsub_node.id) of + [#pubsub_node{nodeid = {H, _}} = Node] -> + case H of + Host -> [{Node, S, J}|Acc]; + _ -> Acc + end; + _ -> + Acc + end + end, [], States), + {result, Reply}. get_node_subscriptions(NodeId) -> {result, States} = get_states(NodeId), @@ -813,10 +827,3 @@ can_fetch_item(none, subscribed) -> true; can_fetch_item(none, none) -> false; can_fetch_item(_Affiliation, _Subscription) -> false. -%% @spec (NodeId) -> Node -%% @doc retreive pubsubNode() representation giving a NodeId -get_nodename(NodeId) -> - case mnesia:index_read(pubsub_node, NodeId, #pubsub_node.id) of - [#pubsub_node{nodeid = {_, Node}}] -> Node; - _ -> [] - end. diff --git a/src/mod_pubsub/node_pep.erl b/src/mod_pubsub/node_pep.erl index d1d1731ef..833612ae3 100644 --- a/src/mod_pubsub/node_pep.erl +++ b/src/mod_pubsub/node_pep.erl @@ -180,8 +180,29 @@ get_affiliation(NodeId, Owner) -> set_affiliation(NodeId, Owner, Affiliation) -> node_default:set_affiliation(NodeId, Owner, Affiliation). -get_entity_subscriptions(_Host, _Owner) -> - {result, []}. +get_entity_subscriptions(_Host, Owner) -> + {U, D, _} = SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + States = case SubKey of + GenKey -> mnesia:match_object( + #pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); + _ -> mnesia:match_object( + #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) + ++ mnesia:match_object( + #pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) + end, + Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscription = S}, Acc) -> + case mnesia:index_read(pubsub_node, N, #pubsub_node.id) of + [#pubsub_node{nodeid = {H, _}} = Node] -> + case H of + {_, D, _} -> [{Node, S, J}|Acc]; + _ -> Acc + end; + _ -> + Acc + end + end, [], States), + {result, Reply}. get_node_subscriptions(NodeId) -> %% note: get_node_subscriptions is used for broadcasting @@ -191,11 +212,11 @@ get_node_subscriptions(NodeId) -> %% DO NOT REMOVE node_default:get_node_subscriptions(NodeId). -get_subscription(_NodeId, _Owner) -> - {result, none}. +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(_NodeId, _Owner, _Subscription) -> - ok. +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). get_states(NodeId) -> node_default:get_states(NodeId). diff --git a/src/mod_pubsub/nodetree_virtual.erl b/src/mod_pubsub/nodetree_virtual.erl index 6913b6e43..05107cb7e 100644 --- a/src/mod_pubsub/nodetree_virtual.erl +++ b/src/mod_pubsub/nodetree_virtual.erl @@ -26,10 +26,9 @@ %%% @doc The module {@module} is the PubSub node tree plugin that %%% allow virtual nodes handling. %%%

PubSub node tree plugins are using the {@link gen_nodetree} behaviour.

-%%%

The API isn't stabilized yet. The pubsub plugin -%%% development is still a work in progress. However, the system is already -%%% useable and useful as is. Please, send us comments, feedback and -%%% improvements.

+%%% This plugin development is still a work in progress. Due to optimizations in +%%% mod_pubsub, this plugin can not work anymore without altering functioning. +%%% Please, send us comments, feedback and improvements.

-module(nodetree_virtual). -author('christophe.romain@process-one.net'). @@ -83,14 +82,13 @@ options() -> set_node(_NodeRecord) -> ok. -get_node(Host, Node, _From) -> - get_node(Host, Node). - %% @spec (Host, Node) -> pubsubNode() %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() %% @doc

Virtual node tree does not handle a node database. Any node is considered %% as existing. Node record contains default values.

+get_node(Host, Node, _From) -> + get_node(Host, Node). get_node(Host, Node) -> #pubsub_node{nodeid = {Host, Node}}. diff --git a/src/mod_pubsub/pubsub.hrl b/src/mod_pubsub/pubsub.hrl index 87088eb6a..dc95e3378 100644 --- a/src/mod_pubsub/pubsub.hrl +++ b/src/mod_pubsub/pubsub.hrl @@ -82,8 +82,8 @@ %%% @type pubsubNode() = #pubsub_node{ %%% nodeid = {Host::host(), Node::pubsubNode()}, -%%% parentid = {Host::host(), Node::pubsubNode()}, -%%% nodeidx = int(). +%%% parentid = Node::pubsubNode(), +%%% nodeidx = int(). % can be anything you want %%% type = nodeType(), %%% options = [nodeOption()]} %%%

This is the format of the nodes table. The type of the table @@ -98,7 +98,7 @@ }). %%% @type pubsubState() = #pubsub_state{ -%%% stateid = {ljid(), pubsubNodeId()}}, +%%% stateid = {ljid(), nodeidx()}}, %%% items = [ItemId::string()], %%% affiliation = affiliation(), %%% subscription = subscription()}. @@ -111,9 +111,9 @@ }). %%% @type pubsubItem() = #pubsub_item{ -%%% itemid = {ItemId::string(), pubsubNodeId()}}, -%%% creation = {ljid(), now()}, -%%% modification = {ljid(), now()}, +%%% itemid = {ItemId::string(), nodeidx()}}, +%%% creation = {now(), ljid()}, +%%% modification = {now(), ljid()}, %%% payload = XMLContent::string()}. %%%

This is the format of the published items table. The type of the %%% table is: set,disc,fragmented.