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.