25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-22 17:28:25 +01:00

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,8 +225,8 @@ init_plugins(Host, ServerHost, Opts) ->
gen_mod:get_opt(nodetree, Opts, ?STDTREE)), gen_mod:get_opt(nodetree, Opts, ?STDTREE)),
?DEBUG("** tree plugin is ~p",[TreePlugin]), ?DEBUG("** tree plugin is ~p",[TreePlugin]),
TreePlugin:init(Host, ServerHost, Opts), TreePlugin:init(Host, ServerHost, Opts),
Plugins = lists:usort(gen_mod:get_opt(plugins, Opts, []) ++ [?STDNODE]), Plugins = gen_mod:get_opt(plugins, Opts, [?STDNODE]),
PepMapping = lists:usort(gen_mod:get_opt(pep_mapping, Opts, [])), PepMapping = gen_mod:get_opt(pep_mapping, Opts, []),
?DEBUG("** PEP Mapping : ~p~n",[PepMapping]), ?DEBUG("** PEP Mapping : ~p~n",[PepMapping]),
lists:foreach(fun(Name) -> lists:foreach(fun(Name) ->
?DEBUG("** init ~s plugin",[Name]), ?DEBUG("** init ~s plugin",[Name]),
@ -387,17 +387,13 @@ send_loop(State) ->
lists:foreach( lists:foreach(
fun({Node, subscribed, SubJID}) -> fun({Node, subscribed, SubJID}) ->
if (SubJID == LJID) or (SubJID == BJID) -> if (SubJID == LJID) or (SubJID == BJID) ->
case tree_action(Host, get_node, [Host, Node, JID]) of #pubsub_node{options = Options, type = Type, id = NodeId} = Node,
#pubsub_node{options = Options, type = Type, id = NodeId} ->
case get_option(Options, send_last_published_item) of case get_option(Options, send_last_published_item) of
on_sub_and_presence -> on_sub_and_presence ->
send_items(Host, Node, NodeId, Type, SubJID, last); send_items(Host, Node, NodeId, Type, SubJID, last);
_ -> _ ->
ok ok
end; end;
_ ->
ok
end;
true -> true ->
% resource not concerned about that subscription % resource not concerned about that subscription
ok ok
@ -700,18 +696,19 @@ handle_cast({remove_user, LUser, LServer}, State) ->
lists:foreach(fun(PType) -> lists:foreach(fun(PType) ->
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]), {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]),
lists:foreach(fun lists:foreach(fun
({Node, subscribed, JID}) -> ({#pubsub_node{nodeid = {H, N}}, subscribed, JID}) ->
unsubscribe_node(Host, Node, Owner, JID, all); unsubscribe_node(H, N, Owner, JID, all);
(_) -> (_) ->
ok 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), 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) -> handle_cast({unsubscribe, Subscriber, Owner}, State) ->
@ -721,20 +718,18 @@ handle_cast({unsubscribe, Subscriber, Owner}, State) ->
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]),
lists:foreach(fun lists:foreach(fun
({Node, subscribed, JID}) -> ({Node, subscribed, JID}) ->
Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId}) -> #pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId} = Node,
case get_option(Options, access_model) of case get_option(Options, access_model) of
presence -> presence ->
case lists:member(BJID, Owners) of case lists:member(BJID, Owners) of
true -> true ->
node_call(Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]);
false -> false ->
{result, ok} {result, ok}
end; end;
_ -> _ ->
{result, ok} {result, ok}
end end;
end,
transaction(Host, Node, Action, sync_dirty);
(_) -> (_) ->
ok ok
end, Subscriptions) end, Subscriptions)
@ -2036,7 +2031,7 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) ->
{ok, Affiliations} -> {ok, Affiliations} ->
Entities = lists:flatmap( Entities = lists:flatmap(
fun({_, none}) -> []; fun({_, none}) -> [];
({Node, Affiliation}) -> ({#pubsub_node{nodeid = {_, Node}}, Affiliation}) ->
[{xmlelement, "affiliation", [{xmlelement, "affiliation",
[{"affiliation", affiliation_to_string(Affiliation)}|nodeAttr(Node)], [{"affiliation", affiliation_to_string(Affiliation)}|nodeAttr(Node)],
[]}] []}]
@ -2175,7 +2170,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
Entities = lists:flatmap( Entities = lists:flatmap(
fun({_, none}) -> fun({_, none}) ->
[]; [];
({SubsNode, Subscription}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) ->
case Node of case Node of
[] -> [] ->
[{xmlelement, "subscription", [{xmlelement, "subscription",
@ -2190,7 +2185,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
end; end;
({_, none, _}) -> ({_, none, _}) ->
[]; [];
({SubsNode, Subscription, SubJID}) -> ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) ->
case Node of case Node of
[] -> [] ->
[{xmlelement, "subscription", [{xmlelement, "subscription",

View File

@ -549,16 +549,22 @@ purge_node(NodeId, Owner) ->
%% the default PubSub module. Otherwise, it should return its own affiliation, %% the default PubSub module. Otherwise, it should return its own affiliation,
%% that will be added to the affiliation stored in the main %% that will be added to the affiliation stored in the main
%% <tt>pubsub_state</tt> table.</p> %% <tt>pubsub_state</tt> table.</p>
get_entity_affiliations(_Host, Owner) -> get_entity_affiliations(Host, Owner) ->
SubKey = jlib:jid_tolower(Owner), SubKey = jlib:jid_tolower(Owner),
GenKey = jlib:jid_remove_resource(SubKey), GenKey = jlib:jid_remove_resource(SubKey),
States = mnesia:match_object( States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}),
%% TODO check if Host needed Reply = lists:foldl(fun(#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) ->
#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), case mnesia:index_read(pubsub_node, N, #pubsub_node.id) of
Tr = fun(#pubsub_state{stateid = {_, N}, affiliation = A}) -> [#pubsub_node{nodeid = {H, _}} = Node] ->
{get_nodename(N), A} case H of
end, Host -> [{Node, A}|Acc];
{result, lists:map(Tr, States)}. _ -> Acc
end;
_ ->
Acc
end
end, [], States),
{result, Reply}.
get_node_affiliations(NodeId) -> get_node_affiliations(NodeId) ->
{result, States} = get_states(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, %% the default PubSub module. Otherwise, it should return its own affiliation,
%% that will be added to the affiliation stored in the main %% that will be added to the affiliation stored in the main
%% <tt>pubsub_state</tt> table.</p> %% <tt>pubsub_state</tt> table.</p>
get_entity_subscriptions(_Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
{U, D, _} = SubKey = jlib:jid_tolower(Owner), {U, D, _} = SubKey = jlib:jid_tolower(Owner),
GenKey = jlib:jid_remove_resource(SubKey), GenKey = jlib:jid_remove_resource(SubKey),
States = case SubKey of States = case SubKey of
@ -605,10 +611,18 @@ get_entity_subscriptions(_Host, Owner) ->
++ mnesia:match_object( ++ mnesia:match_object(
#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) #pubsub_state{stateid = {SubKey, '_'}, _ = '_'})
end, end,
Tr = fun(#pubsub_state{stateid = {J, N}, subscription = S}) -> Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscription = S}, Acc) ->
{get_nodename(N), S, J} case mnesia:index_read(pubsub_node, N, #pubsub_node.id) of
end, [#pubsub_node{nodeid = {H, _}} = Node] ->
{result, lists:map(Tr, States)}. case H of
Host -> [{Node, S, J}|Acc];
_ -> Acc
end;
_ ->
Acc
end
end, [], States),
{result, Reply}.
get_node_subscriptions(NodeId) -> get_node_subscriptions(NodeId) ->
{result, States} = get_states(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(none, none) -> false;
can_fetch_item(_Affiliation, _Subscription) -> 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) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(NodeId, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(_Host, _Owner) -> get_entity_subscriptions(_Host, Owner) ->
{result, []}. {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) -> get_node_subscriptions(NodeId) ->
%% note: get_node_subscriptions is used for broadcasting %% note: get_node_subscriptions is used for broadcasting
@ -191,11 +212,11 @@ get_node_subscriptions(NodeId) ->
%% DO NOT REMOVE %% DO NOT REMOVE
node_default:get_node_subscriptions(NodeId). node_default:get_node_subscriptions(NodeId).
get_subscription(_NodeId, _Owner) -> get_subscription(NodeId, Owner) ->
{result, none}. node_default:get_subscription(NodeId, Owner).
set_subscription(_NodeId, _Owner, _Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
ok. node_default:set_subscription(NodeId, Owner, Subscription).
get_states(NodeId) -> get_states(NodeId) ->
node_default: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 %%% @doc The module <strong>{@module}</strong> is the PubSub node tree plugin that
%%% allow virtual nodes handling. %%% allow virtual nodes handling.
%%% <p>PubSub node tree plugins are using the {@link gen_nodetree} behaviour.</p> %%% <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 %%% This plugin development is still a work in progress. Due to optimizations in
%%% development is still a work in progress. However, the system is already %%% mod_pubsub, this plugin can not work anymore without altering functioning.
%%% useable and useful as is. Please, send us comments, feedback and %%% Please, send us comments, feedback and improvements.</p>
%%% improvements.</p>
-module(nodetree_virtual). -module(nodetree_virtual).
-author('christophe.romain@process-one.net'). -author('christophe.romain@process-one.net').
@ -83,14 +82,13 @@ options() ->
set_node(_NodeRecord) -> set_node(_NodeRecord) ->
ok. ok.
get_node(Host, Node, _From) ->
get_node(Host, Node).
%% @spec (Host, Node) -> pubsubNode() %% @spec (Host, Node) -> pubsubNode()
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% @doc <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Node record contains default values.</p> %% as existing. Node record contains default values.</p>
get_node(Host, Node, _From) ->
get_node(Host, Node).
get_node(Host, Node) -> get_node(Host, Node) ->
#pubsub_node{nodeid = {Host, Node}}. #pubsub_node{nodeid = {Host, Node}}.

View File

@ -82,8 +82,8 @@
%%% @type pubsubNode() = #pubsub_node{ %%% @type pubsubNode() = #pubsub_node{
%%% nodeid = {Host::host(), Node::pubsubNode()}, %%% nodeid = {Host::host(), Node::pubsubNode()},
%%% parentid = {Host::host(), Node::pubsubNode()}, %%% parentid = Node::pubsubNode(),
%%% nodeidx = int(). %%% nodeidx = int(). % can be anything you want
%%% type = nodeType(), %%% type = nodeType(),
%%% options = [nodeOption()]} %%% options = [nodeOption()]}
%%% <p>This is the format of the <tt>nodes</tt> table. The type of the table %%% <p>This is the format of the <tt>nodes</tt> table. The type of the table
@ -98,7 +98,7 @@
}). }).
%%% @type pubsubState() = #pubsub_state{ %%% @type pubsubState() = #pubsub_state{
%%% stateid = {ljid(), pubsubNodeId()}}, %%% stateid = {ljid(), nodeidx()}},
%%% items = [ItemId::string()], %%% items = [ItemId::string()],
%%% affiliation = affiliation(), %%% affiliation = affiliation(),
%%% subscription = subscription()}. %%% subscription = subscription()}.
@ -111,9 +111,9 @@
}). }).
%%% @type pubsubItem() = #pubsub_item{ %%% @type pubsubItem() = #pubsub_item{
%%% itemid = {ItemId::string(), pubsubNodeId()}}, %%% itemid = {ItemId::string(), nodeidx()}},
%%% creation = {ljid(), now()}, %%% creation = {now(), ljid()},
%%% modification = {ljid(), now()}, %%% modification = {now(), ljid()},
%%% payload = XMLContent::string()}. %%% payload = XMLContent::string()}.
%%% <p>This is the format of the <tt>published items</tt> table. The type of the %%% <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> %%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p>