PubSub: improve get_entity_* API

SVN Revision: 2090
This commit is contained in:
Christophe Romain 2009-05-19 21:59:15 +00:00
parent b5964c2a5f
commit dffe808895
5 changed files with 99 additions and 78 deletions

View File

@ -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",

View File

@ -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
%% <tt>pubsub_state</tt> table.</p>
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
%% <tt>pubsub_state</tt> table.</p>
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.

View File

@ -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).

View File

@ -26,10 +26,9 @@
%%% @doc The module <strong>{@module}</strong> is the PubSub node tree plugin that
%%% allow virtual nodes handling.
%%% <p>PubSub node tree plugins are using the {@link gen_nodetree} behaviour.</p>
%%% <p><strong>The API isn't stabilized yet</strong>. 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.</p>
%%% 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.</p>
-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 <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Node record contains default values.</p>
get_node(Host, Node, _From) ->
get_node(Host, Node).
get_node(Host, Node) ->
#pubsub_node{nodeid = {Host, Node}}.

View File

@ -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()]}
%%% <p>This is the format of the <tt>nodes</tt> 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()}.
%%% <p>This is the format of the <tt>published items</tt> table. The type of the
%%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p>