From f8780bc6ee15e738807531df2489173b7da19561 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 30 Apr 2009 05:18:06 +0000 Subject: [PATCH] PubSub/PEP API change for major optimization SVN Revision: 2048 --- ChangeLog | 19 + src/mod_pubsub/gen_pubsub_node.erl | 40 +- src/mod_pubsub/gen_pubsub_nodetree.erl | 2 +- src/mod_pubsub/mod_pubsub.erl | 830 ++++++++++++++----------- src/mod_pubsub/node.template | 122 ++-- src/mod_pubsub/node_buddy.erl | 120 ++-- src/mod_pubsub/node_club.erl | 120 ++-- src/mod_pubsub/node_default.erl | 319 +++++----- src/mod_pubsub/node_dispatch.erl | 110 ++-- src/mod_pubsub/node_flat.erl | 120 ++-- src/mod_pubsub/node_mb.erl | 122 ++-- src/mod_pubsub/node_pep.erl | 126 ++-- src/mod_pubsub/node_private.erl | 120 ++-- src/mod_pubsub/node_public.erl | 120 ++-- src/mod_pubsub/nodetree_default.erl | 80 +-- src/mod_pubsub/nodetree_virtual.erl | 25 +- src/mod_pubsub/pubsub.hrl | 24 +- src/mod_pubsub/pubsub_index.erl | 65 ++ 18 files changed, 1325 insertions(+), 1159 deletions(-) create mode 100644 src/mod_pubsub/pubsub_index.erl diff --git a/ChangeLog b/ChangeLog index 7b0ba705d..a71eebde2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2009-04-24 Christophe Romain + + * src/mod_pubsub/mod_pubsub.erl: API change for major optimization + * src/mod_pubsub/pubsub.hrl: Likewise + * src/mod_pubsub/nodetree_default.erl: Likewise + * src/mod_pubsub/nodetree_virtual.erl: Likewise + * src/mod_pubsub/node_mb.erl: Likewise + * src/mod_pubsub/node_dispatch.erl: Likewise + * src/mod_pubsub/node_buddy.erl: Likewise + * src/mod_pubsub/node_private.erl: Likewise + * src/mod_pubsub/node_public.erl: Likewise + * src/mod_pubsub/node_default.erl: Likewise + * src/mod_pubsub/node_pep.erl: Likewise + * src/mod_pubsub/node_club.erl: Likewise + * src/mod_pubsub/node_flat.erl: Likewise + * src/mod_pubsub/node.template: Likewise + * src/mod_pubsub/gen_pubsub_node.erl: Likewise + * src/mod_pubsub/gen_pubsub_nodetree.erl: Likewise + 2009-04-28 Badlop * src/ejabberd_hooks.erl: Support distributed hooks (EJAB-829) diff --git a/src/mod_pubsub/gen_pubsub_node.erl b/src/mod_pubsub/gen_pubsub_node.erl index 91b8163bc..b4264f809 100644 --- a/src/mod_pubsub/gen_pubsub_node.erl +++ b/src/mod_pubsub/gen_pubsub_node.erl @@ -43,29 +43,29 @@ behaviour_info(callbacks) -> {options, 0}, {features, 0}, {create_node_permission, 6}, - {create_node, 3}, - {delete_node, 2}, - {purge_node, 3}, - {subscribe_node, 8}, - {unsubscribe_node, 5}, - {publish_item, 7}, - {delete_item, 4}, - {remove_extra_items, 4}, - {get_node_affiliations, 2}, + {create_node, 2}, + {delete_node, 1}, + {purge_node, 2}, + {subscribe_node, 7}, + {unsubscribe_node, 4}, + {publish_item, 6}, + {delete_item, 3}, + {remove_extra_items, 3}, + {get_node_affiliations, 1}, {get_entity_affiliations, 2}, - {get_affiliation, 3}, - {set_affiliation, 4}, - {get_node_subscriptions, 2}, + {get_affiliation, 2}, + {set_affiliation, 3}, + {get_node_subscriptions, 1}, {get_entity_subscriptions, 2}, - {get_subscription, 3}, - {set_subscription, 4}, - {get_states, 2}, - {get_state, 3}, + {get_subscription, 2}, + {set_subscription, 3}, + {get_states, 1}, + {get_state, 2}, {set_state, 1}, - {get_items, 7}, - {get_items, 3}, - {get_item, 8}, - {get_item, 3}, + {get_items, 6}, + {get_items, 2}, + {get_item, 7}, + {get_item, 2}, {set_item, 1}, {get_item_name, 3} ]; diff --git a/src/mod_pubsub/gen_pubsub_nodetree.erl b/src/mod_pubsub/gen_pubsub_nodetree.erl index 8bd35f51d..941748e68 100644 --- a/src/mod_pubsub/gen_pubsub_nodetree.erl +++ b/src/mod_pubsub/gen_pubsub_nodetree.erl @@ -47,7 +47,7 @@ behaviour_info(callbacks) -> {get_nodes, 2}, {get_nodes, 1}, {get_subnodes, 3}, - {get_subnodes_tree, 2}, + {get_subnodes_tree, 3}, {create_node, 5}, {delete_node, 2} ]; diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index 98ae6b950..b51d7dfeb 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -39,7 +39,7 @@ -module(mod_pubsub). -author('christophe.romain@process-one.net'). --version('1.12-04'). +-version('1.12-05'). -behaviour(gen_server). -behaviour(gen_mod). @@ -75,13 +75,11 @@ unsubscribe_node/5, publish_item/6, delete_item/4, - send_items/4, - broadcast_stanza/6, + send_items/6, + broadcast_stanza/7, get_configure/5, set_configure/5, - get_items/3, tree_action/3, - node_action/3, node_action/4 ]). @@ -165,8 +163,9 @@ init([ServerHost, Opts]) -> Access = gen_mod:get_opt(access_createnode, Opts, all), PepOffline = gen_mod:get_opt(pep_sendlast_offline, Opts, false), IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), - mod_disco:register_feature(ServerHost, ?NS_PUBSUB), + pubsub_index:init(Host, ServerHost, Opts), {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts), + mod_disco:register_feature(ServerHost, ?NS_PUBSUB), ets:new(gen_mod:get_module_proc(Host, pubsub_state), [set, named_table]), ets:insert(gen_mod:get_module_proc(Host, pubsub_state), {nodetree, NodeTree}), ets:insert(gen_mod:get_module_proc(Host, pubsub_state), {plugins, Plugins}), @@ -193,7 +192,7 @@ init([ServerHost, Opts]) -> ok end, ejabberd_router:register_route(Host), - update_database(Host), + update_database(Host, ServerHost), init_nodes(Host, ServerHost), State = #state{host = Host, server_host = ServerHost, @@ -202,7 +201,7 @@ init([ServerHost, Opts]) -> pep_sendlast_offline = PepOffline, nodetree = NodeTree, plugins = Plugins}, - SendLoop = spawn(?MODULE, send_loop, [State]), %% TODO supervise that process + SendLoop = spawn(?MODULE, send_loop, [State]), {ok, State#state{send_loop = SendLoop}}. %% @spec (Host, ServerHost, Opts) -> Plugins @@ -247,7 +246,7 @@ init_nodes(Host, ServerHost) -> create_node(Host, ServerHost, ["home", ServerHost], service_jid(Host), ?STDNODE), ok. -update_database(Host) -> +update_database(Host, ServerHost) -> mnesia:del_table_index(pubsub_node, type), mnesia:del_table_index(pubsub_node, parentid), case catch mnesia:table_info(pubsub_node, attributes) of @@ -255,14 +254,14 @@ update_database(Host) -> ?INFO_MSG("upgrade pubsub tables",[]), F = fun() -> lists:foldl( - fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, RecList) -> + fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, NodeIdx}) -> ItemsList = lists:foldl( fun({item, IID, Publisher, Payload}, Acc) -> - C = {Publisher, unknown}, - M = {Publisher, now()}, + C = {unknown, Publisher}, + M = {now(), Publisher}, mnesia:write( - #pubsub_item{itemid = {IID, NodeId}, + #pubsub_item{itemid = {IID, NodeIdx}, creation = C, modification = M, payload = Payload}), @@ -280,7 +279,7 @@ update_database(Host) -> end end, [], ItemsList), mnesia:write( - #pubsub_state{stateid = {JID, NodeId}, + #pubsub_state{stateid = {JID, NodeIdx}, items = UsrItems, affiliation = Aff, subscription = Sub}), @@ -290,12 +289,13 @@ update_database(Host) -> end end, [], Entities), mnesia:delete({pubsub_node, NodeId}), - [#pubsub_node{nodeid = NodeId, - parentid = ParentId, + {[#pubsub_node{nodeid = NodeId, + id = NodeIdx, + parent = element(2, ParentId), owners = Owners, options = Options} | - RecList] - end, [], + RecList], NodeIdx + 1} + end, {[], 1}, mnesia:match_object( {pubsub_node, {Host, '_'}, '_', '_'})) end, @@ -314,10 +314,62 @@ update_database(Host) -> {aborted, Reason} -> ?ERROR_MSG("Problem updating Pubsub tables:~n~p", [Reason]) end; + [nodeid, parentid, type, owners, options] -> + F = fun({pubsub_node, NodeId, {_, Parent}, Type, Owners, Options}) -> + #pubsub_node{ + nodeid = NodeId, + id = 0, + parent = Parent, + type = Type, + owners = Owners, + options = Options} + end, + mnesia:transform_table(pubsub_node, F, [nodeid, id, parent, type, owners, options]), + FNew = fun() -> + lists:foldl(fun(#pubsub_node{nodeid = NodeId} = PubsubNode, NodeIdx) -> + mnesia:write(PubsubNode#pubsub_node{id = NodeIdx}), + lists:foreach(fun(#pubsub_state{stateid = StateId} = State) -> + {JID, _} = StateId, + mnesia:delete({pubsub_state, StateId}), + mnesia:write(State#pubsub_state{stateid = {JID, NodeIdx}}) + end, mnesia:match_object(#pubsub_state{stateid = {'_', NodeId}, _ = '_'})), + lists:foreach(fun(#pubsub_item{itemid = ItemId} = Item) -> + {IID, _} = ItemId, + {M1, M2} = Item#pubsub_item.modification, + {C1, C2} = Item#pubsub_item.creation, + mnesia:delete({pubsub_item, ItemId}), + mnesia:write(Item#pubsub_item{itemid = {IID, NodeIdx}, + modification = {M2, M1}, + creation = {C2, C1}}) + end, mnesia:match_object(#pubsub_item{itemid = {'_', NodeId}, _ = '_'})), + NodeIdx + 1 + end, 1, mnesia:match_object( + {pubsub_node, {Host, '_'}, '_', '_', '_', '_', '_'}) + ++ mnesia:match_object( + {pubsub_node, {{'_', ServerHost, '_'}, '_'}, '_', '_', '_', '_', '_'})) + end, + case mnesia:transaction(FNew) of + {atomic, Result} -> + ?INFO_MSG("Pubsub tables updated correctly: ~p", [Result]); + {aborted, Reason} -> + ?ERROR_MSG("Problem updating Pubsub tables:~n~p", [Reason]) + end; _ -> ok end. +send_queue(State, Msg) -> + Pid = State#state.send_loop, + case is_process_alive(Pid) of + true -> + Pid ! Msg, + State; + false -> + SendLoop = spawn(?MODULE, send_loop, [State]), + SendLoop ! Msg, + State#state{send_loop = SendLoop} + end. + send_loop(State) -> receive {presence, JID, Pid} -> @@ -327,16 +379,16 @@ send_loop(State) -> BJID = jlib:jid_remove_resource(LJID), %% for each node From is subscribed to %% and if the node is so configured, send the last published item to From - lists:foreach(fun(Type) -> - {result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, JID]), + lists:foreach(fun(PType) -> + {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, JID]), 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} -> + #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, SubJID, last); + send_items(Host, Node, NodeId, Type, SubJID, last); _ -> ok end; @@ -390,7 +442,7 @@ send_loop(State) -> Owner = jlib:jid_remove_resource(jlib:jid_tolower(JID)), Host = State#state.host, ServerHost = State#state.server_host, - lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, options = Options}) -> + lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, type = Type, id = NodeId, options = Options}) -> case get_option(Options, send_last_published_item) of on_sub_and_presence -> lists:foreach(fun(Resource) -> @@ -408,7 +460,7 @@ send_loop(State) -> element(2, get_roster_info(OU, OS, LJID, Grps)) end, if Subscribed -> - send_items(Owner, Node, LJID, last); + send_items(Owner, Node, NodeId, Type, LJID, last); true -> ok end; @@ -482,21 +534,20 @@ disco_sm_features(Acc, From, To, Node, _Lang) -> end. disco_sm_items(Acc, From, To, [], _Lang) -> - %% TODO, use iq_disco_items(Host, [], From) Host = To#jid.lserver, - LJID = jlib:jid_tolower(jlib:jid_remove_resource(To)), case tree_action(Host, get_nodes, [Host, From]) of [] -> Acc; Nodes -> + SBJID = jlib:jid_to_string(jlib:jid_remove_resource(To)), Items = case Acc of {result, I} -> I; _ -> [] end, NodeItems = lists:map( - fun(Node) -> + fun(#pubsub_node{nodeid = {_, Node}}) -> {xmlelement, "item", - [{"jid", jlib:jid_to_string(LJID)}, + [{"jid", SBJID}, {"node", node_to_string(Node)}], []} end, Nodes), @@ -504,28 +555,35 @@ disco_sm_items(Acc, From, To, [], _Lang) -> end; disco_sm_items(Acc, From, To, Node, _Lang) -> - %% TODO, use iq_disco_items(Host, Node, From) Host = To#jid.lserver, - LJID = jlib:jid_tolower(jlib:jid_remove_resource(To)), - case get_items(Host, Node, From) of - [] -> - Acc; - AllItems -> - Items = case Acc of + Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + case node_call(Type, get_items, [NodeId, From]) of + {result, []} -> + none; + {result, AllItems} -> + SBJID = jlib:jid_to_string(jlib:jid_remove_resource(To)), + Items = case Acc of {result, I} -> I; _ -> [] end, - NodeItems = lists:map( - fun(#pubsub_item{itemid = Id}) -> + NodeItems = lists:map( + fun(#pubsub_item{itemid = {Id, _}}) -> %% "jid" is required by XEP-0030, and %% "node" is forbidden by XEP-0060. - {result, Name} = node_action(Host, Node, get_item_name, [Host, Node, Id]), + {result, Name} = node_call(Type, get_item_name, [Host, Node, Id]), {xmlelement, "item", - [{"jid", jlib:jid_to_string(LJID)}, + [{"jid", SBJID}, {"name", Name}], []} end, AllItems), - {result, NodeItems ++ Items} + {result, NodeItems ++ Items}; + _ -> + none + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Items}} -> {result, Items}; + _ -> Acc end. %% ------- @@ -597,20 +655,18 @@ handle_call(stop, _From, State) -> %% @private handle_cast({presence, JID, Pid}, State) -> %% A new resource is available. send last published items - State#state.send_loop ! {presence, JID, Pid}, - {noreply, State}; + {noreply, send_queue(State, {presence, JID, Pid})}; handle_cast({presence, User, Server, Resources, JID}, State) -> %% A new resource is available. send last published PEP items - State#state.send_loop ! {presence, User, Server, Resources, JID}, - {noreply, State}; + {noreply, send_queue(State, {presence, User, Server, Resources, JID})}; handle_cast({remove_user, LUser, LServer}, State) -> Host = State#state.host, Owner = jlib:make_jid(LUser, LServer, ""), %% remove user's subscriptions - lists:foreach(fun(Type) -> - {result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, Owner]), + 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); @@ -807,7 +863,7 @@ node_disco_features(Host, Node, From) -> node_disco_info(Host, Node, From, false, true). node_disco_info(Host, Node, From, Identity, Features) -> Action = - fun(#pubsub_node{type = Type}) -> + fun(#pubsub_node{type = Type, id = NodeId}) -> I = case Identity of false -> []; @@ -817,7 +873,7 @@ node_disco_info(Host, Node, From, Identity, Features) -> [] -> ["leaf"]; %% No sub-nodes: it's a leaf node _ -> - case node_call(Type, get_items, [Host, Node, From]) of + case node_call(Type, get_items, [NodeId, From]) of {result, []} -> ["collection"]; {result, _} -> ["leaf", "collection"]; _ -> [] @@ -840,10 +896,17 @@ node_disco_info(Host, Node, From, Identity, Features) -> %% TODO: add meta-data info (spec section 5.4) {result, I ++ F} end, - transaction(Host, Node, Action, sync_dirty). + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end. iq_disco_info(Host, SNode, From, Lang) -> - Node = string_to_node(SNode), + [RealSNode|_] = case SNode of + [] -> [[]]; + _ -> string:tokens(SNode, "!") + end, + Node = string_to_node(RealSNode), case Node of [] -> {result, @@ -857,7 +920,7 @@ iq_disco_info(Host, SNode, From, Lang) -> {xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++ lists:map(fun(Feature) -> {xmlelement, "feature", [{"var", ?NS_PUBSUB++"#"++Feature}], []} - end, features(Host, SNode))}; + end, features(Host, Node))}; _ -> node_disco_info(Host, Node, From) end. @@ -881,10 +944,10 @@ iq_disco_items(Host, Item, From) -> %% Note: Multiple Node Discovery not supported (mask on pubsub#type) %% TODO this code is also back-compatible with pubsub v1.8 (for client issue) %% TODO make it pubsub v1.12 compliant (breaks client compatibility ?) - %% TODO That is, remove name attribute (or node?, please check) + %% TODO That is, remove name attribute (or node?, please check for 2.1) Action = - fun(#pubsub_node{type = Type}) -> - NodeItems = case node_call(Type, get_items, [Host, Node, From]) of + fun(#pubsub_node{type = Type, id = NodeId}) -> + NodeItems = case node_call(Type, get_items, [NodeId, From]) of {result, I} -> I; _ -> [] end, @@ -904,7 +967,10 @@ iq_disco_items(Host, Item, From) -> end, NodeItems), {result, Nodes ++ Items} end, - transaction(Host, Node, Action, sync_dirty) + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end end. iq_local(From, To, #iq{type = Type, sub_el = SubEl, xmlns = XMLNS, lang = Lang} = IQ) -> @@ -1087,7 +1153,7 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> %%% authorization handling -send_authorization_request(Host, Node, Subscriber) -> +send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, Subscriber) -> Lang = "en", %% TODO fix Stanza = {xmlelement, "message", [], @@ -1114,16 +1180,9 @@ send_authorization_request(Host, Node, Subscriber) -> {"type", "boolean"}, {"label", translate:translate(Lang, "Allow this Jabber ID to subscribe to this pubsub node?")}], [{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]}, - case tree_action(Host, get_node, [Host, Node, Subscriber]) of - #pubsub_node{owners = Owners} -> - lists:foreach( - fun(Owner) -> - ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza} - end, Owners), - ok; - _ -> - ok - end. + lists:foreach(fun(Owner) -> + ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza} + end, Owners). find_authorization_response(Packet) -> {xmlelement, _Name, _Attrs, Els} = Packet, @@ -1188,11 +1247,9 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> "true" -> true; _ -> false end, - Action = fun(#pubsub_node{type = Type, - %%options = Options, - owners = Owners}) -> + Action = fun(#pubsub_node{type = Type, owners = Owners, id = NodeId}) -> IsApprover = lists:member(jlib:jid_tolower(jlib:jid_remove_resource(From)), Owners), - {result, Subscription} = node_call(Type, get_subscription, [Host, Node, Subscriber]), + {result, Subscription} = node_call(Type, get_subscription, [NodeId, Subscriber]), if not IsApprover -> {error, ?ERR_FORBIDDEN}; @@ -1204,7 +1261,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> false -> none end, send_authorization_approval(Host, Subscriber, SNode, NewSubscription), - node_call(Type, set_subscription, [Host, Node, Subscriber, NewSubscription]) + node_call(Type, set_subscription, [NodeId, Subscriber, NewSubscription]) end end, case transaction(Host, Node, Action, sync_dirty) of @@ -1212,7 +1269,7 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> ejabberd_router:route( To, From, jlib:make_error_reply(Packet, Error)); - {result, _NewSubscription} -> + {result, {_, _NewSubscription}} -> %% XXX: notify about subscription state change, section 12.11 ok; _ -> @@ -1292,7 +1349,6 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> %% create_node(Host, ServerHost, Node, Owner, Type) -> create_node(Host, ServerHost, Node, Owner, Type, all, []). - create_node(Host, ServerHost, [], Owner, Type, Access, Configuration) -> case lists:member("instant-nodes", features(Type)) of true -> @@ -1343,13 +1399,10 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of {result, true} -> case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions]) of - ok -> - node_call(Type, create_node, [Host, Node, Owner]); - {error, ?ERR_CONFLICT} -> - case proplists:get_value(virtual_tree, tree_call(Host, options, [])) of - true -> node_call(Type, create_node, [Host, Node, Owner]); - _ -> {error, ?ERR_CONFLICT} - end; + {ok, NodeId} -> + node_call(Type, create_node, [NodeId, Owner]); + {error, {virtual, NodeId}} -> + node_call(Type, create_node, [NodeId, Owner]); Error -> Error end; @@ -1361,12 +1414,6 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> [{xmlelement, "create", [{"node", node_to_string(Node)}], []}]}], case transaction(CreateNode, transaction) of - {error, Error} -> - %% in case we change transaction to sync_dirty... - %%node_action: - %% node_call(Type, delete_node, [Host, Node]), - %% tree_call(Host, delete_node, [Host, Node]), - {error, Error}; {result, {Result, broadcast}} -> %%Lang = "en", %% TODO: fix %%OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), @@ -1381,7 +1428,12 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> {result, default} -> {result, Reply}; {result, Result} -> - {result, Result} + {result, Result}; + Error -> + %% in case we change transaction to sync_dirty... + %% node_call(Type, delete_node, [Host, Node]), + %% tree_call(Host, delete_node, [Host, Node]), + Error end; Error -> Error @@ -1404,11 +1456,11 @@ delete_node(_Host, [], _Owner) -> %% Node is the root {error, ?ERR_NOT_ALLOWED}; delete_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{type = Type}) -> - case node_call(Type, get_affiliation, [Host, Node, Owner]) of + Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + case node_call(Type, get_affiliation, [NodeId, Owner]) of {result, owner} -> Removed = tree_call(Host, delete_node, [Host, Node]), - node_call(Type, delete_node, [Host, Removed]); + node_call(Type, delete_node, [Removed]); _ -> %% Entity is not an owner {error, ?ERR_FORBIDDEN} @@ -1416,28 +1468,29 @@ delete_node(Host, Node, Owner) -> end, Reply = [], case transaction(Host, Node, Action, transaction) of - {error, Error} -> - {error, Error}; - {result, {Result, broadcast, Removed}} -> - lists:foreach(fun(RNode) -> - broadcast_removed_node(Host, RNode) + {result, {_, {Result, broadcast, Removed}}} -> + lists:foreach(fun({RNode, RSubscriptions}) -> + {RH, RN} = RNode#pubsub_node.nodeid, + NodeId = RNode#pubsub_node.id, + Type = RNode#pubsub_node.type, + Options = RNode#pubsub_node.options, + broadcast_removed_node(RH, RN, NodeId, Type, Options, RSubscriptions) end, Removed), case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, {Result, Removed}} -> - lists:foreach(fun(RNode) -> - broadcast_removed_node(Host, RNode) - end, Removed), + {result, {_, {Result, _Removed}}} -> case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, default} -> + {result, {_, default}} -> {result, Reply}; - {result, Result} -> - {result, Result} + {result, {_, Result}} -> + {result, Result}; + Error -> + Error end. %% @spec (Host, Node, From, JID) -> @@ -1468,7 +1521,7 @@ subscribe_node(Host, Node, From, JID) -> J -> jlib:jid_tolower(J) end, SubId = uniqid(), - Action = fun(#pubsub_node{options = Options, type = Type}) -> + Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> Features = features(Type), SubscribeFeature = lists:member("subscribe", Features), SubscribeConfig = get_option(Options, subscribe), @@ -1496,7 +1549,7 @@ subscribe_node(Host, Node, From, JID) -> {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "subscribe")}; true -> node_call(Type, subscribe_node, - [Host, Node, From, Subscriber, + [NodeId, From, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup]) end @@ -1515,26 +1568,28 @@ subscribe_node(Host, Node, From, JID) -> end, []}]}] end, case transaction(Host, Node, Action, sync_dirty) of - {error, Error} -> - {error, Error}; - {result, {Result, subscribed, send_last}} -> - send_items(Host, Node, Subscriber, last), + {result, {TNode, {Result, subscribed, send_last}}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + send_items(Host, Node, NodeId, Type, Subscriber, last), case Result of default -> {result, Reply(subscribed)}; _ -> {result, Result} end; - {result, {Result, Subscription}} -> + {result, {TNode, {Result, Subscription}}} -> case Subscription of - pending -> send_authorization_request(Host, Node, Subscriber); + pending -> send_authorization_request(TNode, Subscriber); _ -> ok end, case Result of default -> {result, Reply(Subscription)}; _ -> {result, Result} end; - {result, Result} -> + {result, {_, Result}} -> %% this case should never occure anyway - {result, Result} + {result, Result}; + Error -> + Error end. %% @spec (Host, Noce, From, JID, SubId) -> {error, Reason} | {result, []} @@ -1560,14 +1615,16 @@ unsubscribe_node(Host, Node, From, JID, SubId) when is_list(JID) -> end, unsubscribe_node(Host, Node, From, Subscriber, SubId); unsubscribe_node(Host, Node, From, Subscriber, SubId) -> - case node_action(Host, Node, unsubscribe_node, - [Host, Node, From, Subscriber, SubId]) of - {error, Error} -> - {error, Error}; - {result, default} -> + Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + node_call(Type, unsubscribe_node, [NodeId, From, Subscriber, SubId]) + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, default}} -> {result, []}; - {result, Result} -> - {result, Result} + {result, {_, Result}} -> + {result, Result}; + Error -> + Error end. %% @spec (Host::host(), ServerHost::host(), JID::jid(), Node::pubsubNode(), ItemId::string(), Payload::term()) -> @@ -1588,7 +1645,7 @@ publish_item(Host, ServerHost, Node, Publisher, "", Payload) -> %% if publisher does not specify an ItemId, the service MUST generate the ItemId publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload); publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> - Action = fun(#pubsub_node{options = Options, type = Type}) -> + Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> Features = features(Type), PublishFeature = lists:member("publish", Features), PublishModel = get_option(Options, publish_model), @@ -1620,12 +1677,37 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> %% Publisher attempts to publish to persistent node with no item {error, extended_error(?ERR_BAD_REQUEST, "item-required")}; true -> - node_call(Type, publish_item, [Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload]) + node_call(Type, publish_item, [NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload]) end end, ejabberd_hooks:run(pubsub_publish_item, ServerHost, [ServerHost, Node, Publisher, service_jid(Host), ItemId, Payload]), Reply = [], %% TODO EJAB-909 case transaction(Host, Node, Action, sync_dirty) of + {result, {TNode, {Result, broadcast, Removed}}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:jid_tolower(Publisher), Payload), + case Result of + default -> {result, Reply}; + _ -> {result, Result} + end; + {result, {TNode, {default, Removed}}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), + {result, Reply}; + {result, {TNode, {Result, Removed}}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), + {result, Result}; + {result, {_, default}} -> + {result, Reply}; + {result, {_, Result}} -> + {result, Result}; {error, ?ERR_ITEM_NOT_FOUND} -> %% handles auto-create feature %% for automatic node creation. we'll take the default node type: @@ -1642,25 +1724,8 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> false -> {error, ?ERR_ITEM_NOT_FOUND} end; - {error, Reason} -> - {error, Reason}; - {result, {Result, broadcast, Removed}} -> - broadcast_retract_items(Host, Node, Removed), - broadcast_publish_item(Host, Node, ItemId, jlib:jid_tolower(Publisher), Payload), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, default, Removed} -> - broadcast_retract_items(Host, Node, Removed), - {result, Reply}; - {result, Result, Removed} -> - broadcast_retract_items(Host, Node, Removed), - {result, Result}; - {result, default} -> - {result, Reply}; - {result, Result} -> - {result, Result} + Error -> + Error end. %% @spec (Host::host(), JID::jid(), Node::pubsubNode(), ItemId::string()) -> @@ -1683,7 +1748,7 @@ delete_item(_, "", _, _, _) -> %% Request does not specify a node {error, extended_error(?ERR_BAD_REQUEST, "node-required")}; delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> - Action = fun(#pubsub_node{type = Type}) -> + Action = fun(#pubsub_node{type = Type, id = NodeId}) -> Features = features(Type), PersistentFeature = lists:member("persistent-items", Features), DeleteFeature = lists:member("delete-items", Features), @@ -1698,23 +1763,26 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %% Service does not support item deletion {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "delete-items")}; true -> - node_call(Type, delete_item, [Host, Node, Publisher, ItemId]) + node_call(Type, delete_item, [NodeId, Publisher, ItemId]) end end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of - {error, Reason} -> - {error, Reason}; - {result, {Result, broadcast}} -> - broadcast_retract_items(Host, Node, [ItemId], ForceNotify), + {result, {TNode, {Result, broadcast}}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_retract_items(Host, Node, NodeId, Type, Options, [ItemId], ForceNotify), case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, default} -> + {result, {_, default}} -> {result, Reply}; - {result, Result} -> - {result, Result} + {result, {_, Result}} -> + {result, Result}; + Error -> + Error end. %% @spec (Host, JID, Node) -> @@ -1732,7 +1800,7 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %%
  • The specified node does not exist.
  • %% purge_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{type = Type, options = Options}) -> + Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> Features = features(Type), PurgeFeature = lists:member("purge-nodes", Features), PersistentFeature = lists:member("persistent-items", Features), @@ -1748,23 +1816,26 @@ purge_node(Host, Node, Owner) -> %% Node is not configured for persistent items {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "persistent-items")}; true -> - node_call(Type, purge_node, [Host, Node, Owner]) + node_call(Type, purge_node, [NodeId, Owner]) end end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of - {error, Reason} -> - {error, Reason}; - {result, {Result, broadcast}} -> - broadcast_purge_node(Host, Node), + {result, {TNode, {Result, broadcast}}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_purge_node(Host, Node, NodeId, Type, Options), case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, default} -> + {result, {_, default}} -> {result, Reply}; - {result, Result} -> - {result, Result} + {result, {_, Result}} -> + {result, Result}; + Error -> + Error end. %% @doc

    Return the items of a given node.

    @@ -1786,7 +1857,7 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> {error, Error} -> {error, Error}; _ -> - Action = fun(#pubsub_node{options = Options, type = Type}) -> + Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> Features = features(Type), RetreiveFeature = lists:member("retrieve-items", Features), PersistentFeature = lists:member("persistent-items", Features), @@ -1809,15 +1880,13 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "persistent-items")}; true -> node_call(Type, get_items, - [Host, Node, From, + [NodeId, From, AccessModel, PresenceSubscription, RosterGroup, SubId]) end end, case transaction(Host, Node, Action, sync_dirty) of - {error, Reason} -> - {error, Reason}; - {result, Items} -> + {result, {_, Items}} -> SendItems = case ItemIDs of [] -> Items; @@ -1830,47 +1899,46 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> %% number of items sent to MaxItems: {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [{xmlelement, "items", [{"node", node_to_string(Node)}], - itemsEls(lists:sublist(SendItems, MaxItems))}]}]} + itemsEls(lists:sublist(SendItems, MaxItems))}]}]}; + Error -> + Error end end. -get_items(Host, Node, From) -> - case node_action(Host, Node, get_items, [Host, Node, From]) of - {result, Items} -> Items; - _ -> [] - end. - -%% @spec (Host, Node, LJID, Number) -> any() -%% Host = host() -%% Node = pubsubNode() +%% @spec (Host, NodeId, Type LJID, Number) -> any() +%% Host = pubsubHost() +%% NodeId = pubsubNodeId() +%% Type = pubsubNodeType() %% LJID = {U, S, []} %% Number = last | integer() %% @doc

    Resend the items of a node to the user.

    %% @todo use cache-last-item feature -send_items(Host, Node, LJID, Number) -> - ToSend = case get_items(Host, Node, LJID) of - [] -> +send_items(Host, Node, NodeId, Type, LJID, Number) -> + ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of + {result, []} -> []; - Items -> + {result, Items} -> case Number of last -> %%% [lists:last(Items)] does not work on clustered table [First|Tail] = Items, [lists:foldl( fun(CurItem, LastItem) -> - {_, LTimeStamp} = LastItem#pubsub_item.creation, - {_, CTimeStamp} = CurItem#pubsub_item.creation, + {LTimeStamp, _} = LastItem#pubsub_item.creation, + {CTimeStamp, _} = CurItem#pubsub_item.creation, if CTimeStamp > LTimeStamp -> CurItem; true -> LastItem end end, First, Tail)]; N when N > 0 -> - %%% This case is buggy on clustered table due to lake of order + %%% This case is buggy on clustered table due to lack of order lists:nthtail(length(Items)-N, Items); - _ -> + _ -> Items - end + end; + _ -> + [] end, Stanza = event_stanza( [{xmlelement, "items", [{"node", node_to_string(Node)}], @@ -1894,7 +1962,7 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> %% Service does not support retreive affiliatons {{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "retrieve-affiliations")}, Acc}; true -> - {result, Affiliations} = node_action(Type, get_entity_affiliations, [Host, JID]), + {result, Affiliations} = node_action(Host, Type, get_entity_affiliations, [Host, JID]), {Status, [Affiliations|Acc]} end end, {ok, []}, Plugins), @@ -1915,10 +1983,10 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> Error end; get_affiliations(Host, Node, JID) -> - Action = fun(#pubsub_node{type = Type}) -> + Action = fun(#pubsub_node{type = Type, id = NodeId}) -> Features = features(Type), RetrieveFeature = lists:member("modify-affiliations", Features), - Affiliation = node_call(Type, get_affiliation, [Host, Node, JID]), + Affiliation = node_call(Type, get_affiliation, [NodeId, JID]), if not RetrieveFeature -> %% Service does not support modify affiliations @@ -1927,15 +1995,13 @@ get_affiliations(Host, Node, JID) -> %% Entity is not an owner {error, ?ERR_FORBIDDEN}; true -> - node_call(Type, get_node_affiliations, [Host, Node]) + node_call(Type, get_node_affiliations, [NodeId]) end end, case transaction(Host, Node, Action, sync_dirty) of - {error, Reason} -> - {error, Reason}; - {result, []} -> + {result, {_, []}} -> {error, ?ERR_ITEM_NOT_FOUND}; - {result, Affiliations} -> + {result, {_, Affiliations}} -> Entities = lists:flatmap( fun({_, none}) -> []; ({AJID, Affiliation}) -> @@ -1946,7 +2012,9 @@ get_affiliations(Host, Node, JID) -> end, Affiliations), {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_OWNER}], [{xmlelement, "affiliations", [{"node", node_to_string(Node)}], - Entities}]}]} + Entities}]}]}; + Error -> + Error end. set_affiliations(Host, Node, From, EntitiesEls) -> @@ -1978,12 +2046,12 @@ set_affiliations(Host, Node, From, EntitiesEls) -> error -> {error, ?ERR_BAD_REQUEST}; _ -> - Action = fun(#pubsub_node{type = Type, owners = Owners}=N) -> + Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}=N) -> case lists:member(Owner, Owners) of true -> lists:foreach( fun({JID, Affiliation}) -> - node_call(Type, set_affiliation, [Host, Node, JID, Affiliation]), + node_call(Type, set_affiliation, [NodeId, JID, Affiliation]), case Affiliation of owner -> NewOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), @@ -2007,7 +2075,10 @@ set_affiliations(Host, Node, From, EntitiesEls) -> {error, ?ERR_FORBIDDEN} end end, - transaction(Host, Node, Action, sync_dirty) + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end end. @@ -2029,7 +2100,7 @@ get_subscriptions(Host, JID, Plugins) when is_list(Plugins) -> {{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "retrieve-subscriptions")}, Acc}; true -> Subscriber = jlib:jid_remove_resource(JID), - {result, Subscriptions} = node_action(Type, get_entity_subscriptions, [Host, Subscriber]), + {result, Subscriptions} = node_action(Host, Type, get_entity_subscriptions, [Host, Subscriber]), {Status, [Subscriptions|Acc]} end end, {ok, []}, Plugins), @@ -2057,10 +2128,10 @@ get_subscriptions(Host, JID, Plugins) when is_list(Plugins) -> Error end; get_subscriptions(Host, Node, JID) -> - Action = fun(#pubsub_node{type = Type}) -> + Action = fun(#pubsub_node{type = Type, id = NodeId}) -> Features = features(Type), RetrieveFeature = lists:member("manage-subscriptions", Features), - Affiliation = node_call(Type, get_affiliation, [Host, Node, JID]), + Affiliation = node_call(Type, get_affiliation, [NodeId, JID]), if not RetrieveFeature -> %% Service does not support manage subscriptions @@ -2069,15 +2140,13 @@ get_subscriptions(Host, Node, JID) -> %% Entity is not an owner {error, ?ERR_FORBIDDEN}; true -> - node_call(Type, get_node_subscriptions, [Host, Node]) + node_call(Type, get_node_subscriptions, [NodeId]) end end, case transaction(Host, Node, Action, sync_dirty) of - {error, Reason} -> - {error, Reason}; - {result, []} -> + {result, {_, []}} -> {error, ?ERR_ITEM_NOT_FOUND}; - {result, Subscriptions} -> + {result, {_, Subscriptions}} -> Entities = lists:flatmap( fun({_, none}) -> []; ({AJID, Subscription}) -> @@ -2094,7 +2163,9 @@ get_subscriptions(Host, Node, JID) -> end, Subscriptions), {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_OWNER}], [{xmlelement, "subscriptions", [{"node", node_to_string(Node)}], - Entities}]}]} + Entities}]}]}; + Error -> + Error end. set_subscriptions(Host, Node, From, EntitiesEls) -> @@ -2126,18 +2197,21 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> error -> {error, ?ERR_BAD_REQUEST}; _ -> - Action = fun(#pubsub_node{type = Type, owners = Owners}) -> + Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}) -> case lists:member(Owner, Owners) of true -> lists:foreach(fun({JID, Subscription}) -> - node_call(Type, set_subscription, [Host, Node, JID, Subscription]) + node_call(Type, set_subscription, [NodeId, JID, Subscription]) end, Entities), {result, []}; _ -> {error, ?ERR_FORBIDDEN} end end, - transaction(Host, Node, Action, sync_dirty) + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end end. @@ -2252,175 +2326,169 @@ event_stanza(Els) -> %%%%%% broadcast functions -broadcast_publish_item(Host, Node, ItemId, _From, Payload) -> - %broadcast(Host, Node, none, true, "items", ItemEls) - Action = - fun(#pubsub_node{options = Options, type = Type}) -> - case node_call(Type, get_states, [Host, Node]) of +broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, _From, Payload) -> + %broadcast(Host, Node, NodeId, Options, none, true, "items", ItemEls) + case node_action(Host, Type, get_node_subscriptions, [NodeId]) of + {result, []} -> + {result, false}; + {result, Subs} -> + Content = case get_option(Options, deliver_payloads) of + true -> Payload; + false -> [] + end, + Stanza = event_stanza( + [{xmlelement, "items", [{"node", node_to_string(Node)}], + [{xmlelement, "item", itemAttr(ItemId), Content}]}]), + broadcast_stanza(Host, Node, NodeId, Type, Options, Subs, Stanza), + case Removed of + [] -> + ok; + _ -> + case get_option(Options, notify_retract) of + true -> + RetractStanza = event_stanza( + [{xmlelement, "items", [{"node", node_to_string(Node)}], + [{xmlelement, "retract", itemAttr(RId), []} || RId <- Removed]}]), + broadcast_stanza(Host, Node, NodeId, Type, Options, Subs, RetractStanza); + _ -> + ok + end + end, + {result, true}; + _ -> + {result, false} + end. + +broadcast_retract_items(Host, Node, NodeId, Type, Options, ItemIds) -> + broadcast_retract_items(Host, Node, NodeId, Type, Options, ItemIds, false). +broadcast_retract_items(_Host, _Node, _NodeId, _Type, _Options, [], _ForceNotify) -> + {result, false}; +broadcast_retract_items(Host, Node, NodeId, Type, Options, ItemIds, ForceNotify) -> + %broadcast(Host, Node, NodeId, Options, notify_retract, ForceNotify, "retract", RetractEls) + case (get_option(Options, notify_retract) or ForceNotify) of + true -> + case node_action(Host, Type, get_node_subscriptions, [NodeId]) of {result, []} -> {result, false}; - {result, States} -> - Content = case get_option(Options, deliver_payloads) of - true -> Payload; - false -> [] - end, + {result, Subs} -> Stanza = event_stanza( [{xmlelement, "items", [{"node", node_to_string(Node)}], - [{xmlelement, "item", itemAttr(ItemId), Content}]}]), - broadcast_stanza(Host, Node, Type, Options, States, Stanza), + [{xmlelement, "retract", itemAttr(ItemId), []} || ItemId <- ItemIds]}]), + broadcast_stanza(Host, Node, NodeId, Type, Options, Subs, Stanza), {result, true}; _ -> {result, false} - end - end, - transaction(Host, Node, Action, sync_dirty). + end; + _ -> + {result, false} + end. -broadcast_retract_items(Host, Node, ItemIds) -> - broadcast_retract_items(Host, Node, ItemIds, false). -broadcast_retract_items(Host, Node, ItemIds, ForceNotify) -> - %broadcast(Host, Node, notify_retract, ForceNotify, "retract", RetractEls) - Action = - fun(#pubsub_node{options = Options, type = Type}) -> - case (get_option(Options, notify_retract) or ForceNotify) of - true -> - case node_call(Type, get_states, [Host, Node]) of - {result, []} -> - {result, false}; - {result, States} -> - RetractEls = [{xmlelement, "retract", itemAttr(ItemId), []} || ItemId <- ItemIds], - Stanza = event_stanza( - [{xmlelement, "items", [{"node", node_to_string(Node)}], - RetractEls}]), - broadcast_stanza(Host, Node, Type, Options, States, Stanza), - {result, true}; - _ -> - {result, false} - end; - _ -> +broadcast_purge_node(Host, Node, NodeId, Type, Options) -> + %broadcast(Host, Node, NodeId, Options, notify_retract, false, "purge", []) + case get_option(Options, notify_retract) of + true -> + case node_action(Host, Type, get_node_subscriptions, [NodeId]) of + {result, []} -> + {result, false}; + {result, Subs} -> + Stanza = event_stanza( + [{xmlelement, "purge", [{"node", node_to_string(Node)}], + []}]), + broadcast_stanza(Host, Node, NodeId, Type, Options, Subs, Stanza), + {result, true}; + _ -> {result, false} - end - end, - transaction(Host, Node, Action, sync_dirty). + end; + _ -> + {result, false} + end. -broadcast_purge_node(Host, Node) -> - %broadcast(Host, Node, notify_retract, false, "purge", []) - Action = - fun(#pubsub_node{options = Options, type = Type}) -> - case get_option(Options, notify_retract) of - true -> - case node_call(Type, get_states, [Host, Node]) of - {result, []} -> - {result, false}; - {result, States} -> - Stanza = event_stanza( - [{xmlelement, "purge", [{"node", node_to_string(Node)}], - []}]), - broadcast_stanza(Host, Node, Type, Options, States, Stanza), - {result, true}; - _ -> - {result, false} - end; +broadcast_removed_node(Host, Node, NodeId, Type, Options, Subs) -> + %broadcast(Host, Node, NodeId, Options, notify_delete, false, "delete", []) + case get_option(Options, notify_delete) of + true -> + case Subs of + [] -> + {result, false}; _ -> - {result, false} - end - end, - transaction(Host, Node, Action, sync_dirty). + Stanza = event_stanza( + [{xmlelement, "delete", [{"node", node_to_string(Node)}], + []}]), + broadcast_stanza(Host, Node, NodeId, Type, Options, Subs, Stanza), + {result, true} + end; + _ -> + {result, false} + end. -broadcast_removed_node(Host, Node) -> - %broadcast(Host, Node, notify_delete, false, "delete", []) - Action = - fun(#pubsub_node{options = Options, type = Type}) -> - case get_option(Options, notify_delete) of - true -> - case node_call(Type, get_states, [Host, Node]) of - {result, []} -> - {result, false}; - {result, States} -> - Stanza = event_stanza( - [{xmlelement, "delete", [{"node", node_to_string(Node)}], - []}]), - broadcast_stanza(Host, Node, Type, Options, States, Stanza), - {result, true}; - _ -> - {result, false} - end; - _ -> +broadcast_config_notification(Host, Node, NodeId, Type, Options, Lang) -> + %broadcast(Host, Node, NodeId, Options, notify_config, false, "items", ConfigEls) + case get_option(Options, notify_config) of + true -> + case node_action(Host, Type, get_node_subscriptions, [NodeId]) of + {result, []} -> + {result, false}; + {result, Subs} -> + Content = case get_option(Options, deliver_payloads) of + true -> + [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], + get_configure_xfields(Type, Options, Lang, [])}]; + false -> + [] + end, + Stanza = event_stanza( + [{xmlelement, "items", [{"node", node_to_string(Node)}], + [{xmlelement, "item", itemAttr("configuration"), Content}]}]), + broadcast_stanza(Host, Node, NodeId, Type, Options, Subs, Stanza), + {result, true}; + _ -> {result, false} - end - end, - transaction(Host, Node, Action, sync_dirty). - -broadcast_config_notification(Host, Node, Lang) -> - %broadcast(Host, Node, notify_config, false, "items", ConfigEls) - Action = - fun(#pubsub_node{options = Options, owners = Owners, type = Type}) -> - case get_option(Options, notify_config) of - true -> - case node_call(Type, get_states, [Host, Node]) of - {result, []} -> - {result, false}; - {result, States} -> - Content = case get_option(Options, deliver_payloads) of - true -> - [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], - get_configure_xfields(Type, Options, Lang, Owners, [])}]; - false -> - [] - end, - Stanza = event_stanza( - [{xmlelement, "items", [{"node", node_to_string(Node)}], - [{xmlelement, "item", itemAttr("configuration"), Content}]}]), - broadcast_stanza(Host, Node, Type, Options, States, Stanza), - {result, true}; - _ -> - {result, false} - end; - _ -> - {result, false} - end - end, - transaction(Host, Node, Action, sync_dirty). + end; + _ -> + {result, false} + end. % TODO: merge broadcast code that way -%broadcast(Host, Node, Feature, Force, ElName, SubEls) -> -% Action = -% fun(#pubsub_node{options = Options, type = Type}) -> -% case (get_option(Options, Feature) or Force) of -% true -> -% case node_call(Type, get_states, [Host, Node]) of -% {result, []} -> -% {result, false}; -% {result, States} -> -% Stanza = event_stanza([{xmlelement, ElName, [{"node", node_to_string(Node)}], SubEls}]), -% broadcast_stanza(Host, Node, Type, Options, States, Stanza), -% {result, true}; -% _ -> -% {result, false} -% end; +%broadcast(Host, Node, NodeId, Type, Options, Feature, Force, ElName, SubEls) -> +% case (get_option(Options, Feature) or Force) of +% true -> +% case node_action(Host, Type, get_node_subscriptions, [NodeId]) of +% {result, []} -> +% {result, false}; +% {result, Subs} -> +% Stanza = event_stanza([{xmlelement, ElName, [{"node", node_to_string(Node)}], SubEls}]), +% broadcast_stanza(Host, Node, Type, Options, Subs, Stanza), +% {result, true}; % _ -> % {result, false} -% end -% end, -% transaction(Host, Node, Action, sync_dirty). +% end; +% _ -> +% {result, false} +% end -broadcast_stanza(Host, Node, _Type, Options, States, Stanza) -> - AccessModel = get_option(Options, access_model), +broadcast_stanza(Host, Node, _NodeId, _Type, Options, Subscriptions, Stanza) -> + %AccessModel = get_option(Options, access_model), PresenceDelivery = get_option(Options, presence_based_delivery), BroadcastAll = get_option(Options, broadcast_all_resources), %% XXX this is not standard, but usefull From = service_jid(Host), %% Handles explicit subscriptions - lists:foreach(fun(#pubsub_state{stateid = {LJID, _}, subscription = Subs}) -> - case is_to_deliver(LJID, Subs, PresenceDelivery) of + lists:foreach(fun({LJID, Subscription}) -> + case is_to_deliver(LJID, Subscription, PresenceDelivery) of true -> - To = case BroadcastAll of - true -> jlib:jid_remove_resource(LJID); - false -> LJID + LJIDs = case BroadcastAll of + true -> + {U, S, _} = LJID, + [{U, S, R} || R <- user_resources(U, S)]; + false -> + [LJID] end, - ejabberd_router ! {route, From, jlib:make_jid(To), Stanza}; + lists:foreach(fun(To) -> + ejabberd_router ! {route, From, jlib:make_jid(To), Stanza} + end, LJIDs); false -> ok end - end, States), + end, Subscriptions), %% Handles implicit presence subscriptions case Host of {LUser, LServer, LResource} -> @@ -2444,16 +2512,16 @@ broadcast_stanza(Host, Node, _Type, Options, States, Stanza) -> Contacts when is_list(Contacts) -> lists:foreach(fun({U, S, _}) -> spawn(fun() -> - JIDs = lists:foldl(fun(R, Acc) -> + LJIDs = lists:foldl(fun(R, Acc) -> LJID = {U, S, R}, case is_caps_notify(LServer, Node, LJID) of true -> [LJID | Acc]; false -> Acc end end, [], user_resources(U, S)), - lists:foreach(fun(JID) -> - ejabberd_router ! {route, Sender, jlib:make_jid(JID), Stanza} - end, JIDs) + lists:foreach(fun(To) -> + ejabberd_router ! {route, Sender, jlib:make_jid(To), Stanza} + end, LJIDs) end) end, Contacts); _ -> @@ -2496,8 +2564,8 @@ is_caps_notify(Host, Node, LJID) -> %% get_configure(Host, ServerHost, Node, From, Lang) -> Action = - fun(#pubsub_node{options = Options, owners = Owners, type = Type}) -> - case node_call(Type, get_affiliation, [Host, Node, From]) of + fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + case node_call(Type, get_affiliation, [NodeId, From]) of {result, owner} -> Groups = ejabberd_hooks:run_fold(roster_groups, ServerHost, [], [ServerHost]), {result, @@ -2507,13 +2575,16 @@ get_configure(Host, ServerHost, Node, From, Lang) -> [{"node", node_to_string(Node)}], [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], - get_configure_xfields(Type, Options, Lang, Owners, Groups) + get_configure_xfields(Type, Options, Lang, Groups) }]}]}]}; _ -> {error, ?ERR_FORBIDDEN} end end, - transaction(Host, Node, Action, sync_dirty). + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end. get_default(Host, Node, _From, Lang) -> Type = select_type(Host, Host, Node), @@ -2521,7 +2592,7 @@ get_default(Host, Node, _From, Lang) -> {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB_OWNER}], [{xmlelement, "default", [], [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}], - get_configure_xfields(Type, Options, Lang, [], []) + get_configure_xfields(Type, Options, Lang, []) }]}]}]}. %% Get node option @@ -2597,7 +2668,7 @@ max_items(Options) -> ?LISTMXFIELD(Label, "pubsub#" ++ atom_to_list(Var), get_option(Options, Var), Opts)). -get_configure_xfields(_Type, Options, Lang, _Owners, Groups) -> +get_configure_xfields(_Type, Options, Lang, Groups) -> [?XFIELD("hidden", "", "FORM_TYPE", ?NS_PUBSUB_NODE_CONFIG), ?BOOL_CONFIG_FIELD("Deliver payloads with event notifications", deliver_payloads), ?BOOL_CONFIG_FIELD("Deliver event notifications", deliver_notifications), @@ -2636,9 +2707,8 @@ set_configure(Host, Node, From, Els, Lang) -> {result, []}; {?NS_XDATA, "submit"} -> Action = - fun(#pubsub_node{options = Options, type = Type}=N) -> - case node_call(Type, get_affiliation, - [Host, Node, From]) of + fun(#pubsub_node{options = Options, type = Type, id = NodeId} = N) -> + case node_call(Type, get_affiliation, [NodeId, From]) of {result, owner} -> case jlib:parse_xdata_submit(XEl) of invalid -> @@ -2650,8 +2720,7 @@ set_configure(Host, Node, From, Els, Lang) -> end, case set_xoption(XData, OldOpts) of NewOpts when is_list(NewOpts) -> - tree_call(Host, set_node, - [N#pubsub_node{options = NewOpts}]), + tree_call(Host, set_node, [N#pubsub_node{options = NewOpts}]), {result, ok}; Err -> Err @@ -2662,8 +2731,11 @@ set_configure(Host, Node, From, Els, Lang) -> end end, case transaction(Host, Node, Action, transaction) of - {result, ok} -> - broadcast_config_notification(Host, Node, Lang), + {result, {TNode, ok}} -> + NodeId = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_config_notification(Host, Node, NodeId, Type, Options, Lang), {result, []}; Other -> Other @@ -2835,13 +2907,17 @@ features(Host, []) -> Acc ++ features(Plugin) end, [], plugins(Host))); features(Host, Node) -> - {result, Features} = node_action(Host, Node, features, []), - lists:usort(features() ++ Features). + Action = fun(#pubsub_node{type = Type}) -> {result, features(Type)} end, + case transaction(Host, Node, Action, sync_dirty) of + {result, Features} -> lists:usort(features() ++ Features); + _ -> features() + end. %% @doc

    node tree plugin call.

    tree_call({_User, Server, _Resource}, Function, Args) -> tree_call(Server, Function, Args); tree_call(Host, Function, Args) -> + ?DEBUG("tree_call ~p ~p ~p",[Host, Function, Args]), Module = case ets:lookup(gen_mod:get_module_proc(Host, pubsub_state), nodetree) of [{nodetree, N}] -> N; _ -> list_to_atom(?TREE_PREFIX ++ ?STDTREE) @@ -2853,6 +2929,7 @@ tree_action(Host, Function, Args) -> %% @doc

    node plugin call.

    node_call(Type, Function, Args) -> + ?DEBUG("node_call ~p ~p ~p",[Type, Function, Args]), Module = list_to_atom(?PLUGIN_PREFIX++Type), case catch apply(Module, Function, Args) of {result, Result} -> {result, Result}; @@ -2866,24 +2943,23 @@ node_call(Type, Function, Args) -> Result -> {result, Result} %% any other return value is forced as result end. -node_action(Type, Function, Args) -> +node_action(_Host, Type, Function, Args) -> transaction(fun() -> node_call(Type, Function, Args) end, sync_dirty). -node_action(Host, Node, Function, Args) -> - transaction(fun() -> - case tree_call(Host, get_node, [Host, Node]) of - #pubsub_node{type=Type} -> node_call(Type, Function, Args); - Other -> Other - end - end, sync_dirty). %% @doc

    plugin transaction handling.

    transaction(Host, Node, Action, Trans) -> transaction(fun() -> case tree_call(Host, get_node, [Host, Node]) of - Record when is_record(Record, pubsub_node) -> Action(Record); - Other -> Other + N when is_record(N, pubsub_node) -> + case Action(N) of + {result, Result} -> {result, {N, Result}}; + {atomic, {result, Result}} -> {result, {N, Result}}; + Other -> Other + end; + Error -> + Error end end, Trans). diff --git a/src/mod_pubsub/node.template b/src/mod_pubsub/node.template index 536f1775b..3879266a9 100644 --- a/src/mod_pubsub/node.template +++ b/src/mod_pubsub/node.template @@ -42,29 +42,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1 ]). @@ -88,7 +88,7 @@ options() -> {roster_groups_allowed, []}, {publish_model, publishers}, {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, never}, + {send_last_published_item, on_sub_and_presence}, {deliver_notifications, true}, {presence_based_delivery, false}]. @@ -112,74 +112,74 @@ features() -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> - node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> + node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_default:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_default:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_default:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_default:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_default:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_default:get_node_subscriptions(NodeId). -get_subscription(Host, Node, Owner) -> - node_default:get_subscription(Host, Node, Owner). +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_buddy.erl b/src/mod_pubsub/node_buddy.erl index 029543dc2..4caa922f3 100644 --- a/src/mod_pubsub/node_buddy.erl +++ b/src/mod_pubsub/node_buddy.erl @@ -43,29 +43,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -115,74 +115,74 @@ features() -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> - node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> + node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_default:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_default:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_default:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_default:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_default:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_default:get_node_subscriptions(NodeId). -get_subscription(Host, Node, Owner) -> - node_default:get_subscription(Host, Node, Owner). +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_club.erl b/src/mod_pubsub/node_club.erl index c164b36b3..a7de3e855 100644 --- a/src/mod_pubsub/node_club.erl +++ b/src/mod_pubsub/node_club.erl @@ -43,29 +43,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -114,74 +114,74 @@ features() -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> - node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> + node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_default:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_default:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_default:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_default:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_default:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_default:get_node_subscriptions(NodeId). -get_subscription(Host, Node, Owner) -> - node_default:get_subscription(Host, Node, Owner). +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_default.erl b/src/mod_pubsub/node_default.erl index cafd2f3e3..ac23cf20f 100644 --- a/src/mod_pubsub/node_default.erl +++ b/src/mod_pubsub/node_default.erl @@ -50,29 +50,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -192,8 +192,8 @@ features() -> %%

    PubSub plugins can redefine the PubSub node creation rights as they %% which. They can simply delegate this check to the {@link node_default} %% module by implementing this function like this: -%% ```check_create_user_permission(Host, Node, Owner, Access) -> -%% node_default:check_create_user_permission(Host, Node, Owner, Access).'''

    +%% ```check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> +%% node_default:check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access).'''

    create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> LOwner = jlib:jid_tolower(Owner), {User, Server, _Resource} = LOwner, @@ -213,35 +213,36 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> end, {result, Allowed}. -%% @spec (Host, Node, Owner) -> +%% @spec (NodeId, Owner) -> %% {result, Result} | exit -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% NodeId = mod_pubsub:pubsubNodeId() %% Owner = mod_pubsub:jid() %% @doc

    -create_node(Host, Node, Owner) -> +create_node(NodeId, Owner) -> OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - set_state(#pubsub_state{stateid = {OwnerKey, {Host, Node}}, affiliation = owner}), + set_state(#pubsub_state{stateid = {OwnerKey, NodeId}, affiliation = owner}), {result, {default, broadcast}}. -%% @spec (Host, Removed) -> ok -%% Host = mod_pubsub:host() +%% @spec (Removed) -> ok %% Removed = [mod_pubsub:pubsubNode()] %% @doc

    purge items of deleted nodes after effective deletion.

    -delete_node(Host, Removed) -> - lists:foreach( - fun(Node) -> - lists:foreach( - fun(#pubsub_state{stateid = StateId, items = Items}) -> - del_items(Host, Node, Items), - del_state(StateId) - end, - mnesia:match_object( - #pubsub_state{stateid = {'_', {Host, Node}}, _ = '_'})) - end, Removed), - {result, {default, broadcast, Removed}}. +delete_node(Removed) -> + Tr = fun(#pubsub_state{stateid = {J, _}, subscription = S}) -> + {J, S} + end, + Reply = lists:map( + fun(#pubsub_node{id = NodeId} = PubsubNode) -> + {result, States} = get_states(NodeId), + lists:foreach( + fun(#pubsub_state{stateid = {LJID, _}, items = Items}) -> + del_items(NodeId, Items), + del_state(NodeId, LJID) + end, States), + {PubsubNode, lists:map(Tr, States)} + end, Removed), + {result, {default, broadcast, Reply}}. -%% @spec (Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> +%% @spec (NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> %% {error, Reason} | {result, Result} %% @doc

    Accepts or rejects subcription requests on a PubSub node.

    %%

    The mechanism works as follow: @@ -274,17 +275,18 @@ delete_node(Host, Removed) -> %% to completly disable persistance. %%

    %%

    In the default plugin module, the record is unchanged.

    -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), Authorized = (jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), SubState = case SubKey of GenKey -> GenState; - _ -> get_state(Host, Node, SubKey) + _ -> get_state(NodeId, SubKey) end, Affiliation = GenState#pubsub_state.affiliation, + Subscription = SubState#pubsub_state.subscription, Whitelisted = lists:member(Affiliation, [member, publisher, owner]), if not Authorized -> @@ -293,7 +295,7 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel, Affiliation == outcast -> %% Requesting entity is blocked {error, ?ERR_FORBIDDEN}; - SubState#pubsub_state.subscription == pending -> + Subscription == pending -> %% Requesting entity has pending subscription {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "pending-subscription")}; (AccessModel == presence) and (not PresenceSubscription) -> @@ -336,23 +338,22 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel, end end. -%% @spec (Host, Node, Sender, Subscriber, SubID) -> +%% @spec (NodeId, Sender, Subscriber, SubID) -> %% {error, Reason} | {result, []} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% NodeId = mod_pubsub:pubsubNodeId() %% Sender = mod_pubsub:jid() %% Subscriber = mod_pubsub:jid() %% SubID = string() %% Reason = mod_pubsub:stanzaError() %% @doc

    Unsubscribe the Subscriber from the Node.

    -unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) -> +unsubscribe_node(NodeId, Sender, Subscriber, _SubId) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), Authorized = (jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), SubState = case SubKey of GenKey -> GenState; - _ -> get_state(Host, Node, SubKey) + _ -> get_state(NodeId, SubKey) end, if %% Requesting entity is prohibited from unsubscribing entity @@ -369,17 +370,16 @@ unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) -> {error, ?ERR_EXTENDED(?ERR_UNEXPECTED_REQUEST, "not-subscribed")}; %% Was just subscriber, remove the record SubState#pubsub_state.affiliation == none -> - del_state(SubState#pubsub_state.stateid), + del_state(NodeId, SubKey), {result, default}; true -> set_state(SubState#pubsub_state{subscription = none}), {result, default} end. -%% @spec (Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) -> +%% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% {true, PubsubItem} | {result, Reply} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% NodeId = mod_pubsub:pubsubNodeId() %% Publisher = mod_pubsub:jid() %% PublishModel = atom() %% MaxItems = integer() @@ -415,13 +415,13 @@ unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) -> %% to completly disable persistance. %%

    %%

    In the default plugin module, the record is unchanged.

    -publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) -> +publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> SubKey = jlib:jid_tolower(Publisher), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), SubState = case SubKey of GenKey -> GenState; - _ -> get_state(Host, Node, SubKey) + _ -> get_state(NodeId, SubKey) end, Affiliation = GenState#pubsub_state.affiliation, Subscription = SubState#pubsub_state.subscription, @@ -434,31 +434,31 @@ publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% Entity does not have sufficient privileges to publish to node {error, ?ERR_FORBIDDEN}; true -> - PubId = {SubKey, now()}, %% TODO, uses {now(),PublisherKey} for sorting (EJAB-824) %% TODO: check creation, presence, roster - Item = case get_item(Host, Node, ItemId) of + if MaxItems > 0 -> + PubId = {now(), SubKey}, + Item = case get_item(NodeId, ItemId) of {result, OldItem} -> OldItem#pubsub_item{modification = PubId, payload = Payload}; _ -> - #pubsub_item{itemid = {ItemId, {Host, Node}}, - creation = {GenKey, now()}, + #pubsub_item{itemid = {ItemId, NodeId}, + creation = {now(), GenKey}, modification = PubId, payload = Payload} end, - Items = [ItemId | GenState#pubsub_state.items--[ItemId]], - {result, {NI, OI}} = remove_extra_items( - Host, Node, MaxItems, Items), - if MaxItems > 0 -> set_item(Item); - true -> ok - end, - set_state(GenState#pubsub_state{items = NI}), - {result, {default, broadcast, OI}} + Items = [ItemId | GenState#pubsub_state.items--[ItemId]], + {result, {NI, OI}} = remove_extra_items(NodeId, MaxItems, Items), + set_item(Item), + set_state(GenState#pubsub_state{items = NI}), + {result, {default, broadcast, OI}}; + true -> + {result, {default, broadcast, []}} + end end. -%% @spec (Host, Node, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} +%% NodeId = mod_pubsub:pubsubNodeId() %% MaxItems = integer() | unlimited %% ItemIds = [ItemId::string()] %% NewItemIds = [ItemId::string()] @@ -470,35 +470,34 @@ publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% rules can be used.

    %%

    If another PubSub plugin wants to delegate the item removal (and if the %% plugin is using the default pubsub storage), it can implements this function like this: -%% ```remove_extra_items(Host, Node, MaxItems, ItemIds) -> -%% node_default:remove_extra_items(Host, Node, MaxItems, ItemIds).'''

    -remove_extra_items(_Host, _Node, unlimited, ItemIds) -> +%% ```remove_extra_items(NodeId, MaxItems, ItemIds) -> +%% node_default:remove_extra_items(NodeId, MaxItems, ItemIds).'''

    +remove_extra_items(_NodeId, unlimited, ItemIds) -> {result, {ItemIds, []}}; -remove_extra_items(Host, Node, MaxItems, ItemIds) -> +remove_extra_items(NodeId, MaxItems, ItemIds) -> NewItems = lists:sublist(ItemIds, MaxItems), OldItems = lists:nthtail(length(NewItems), ItemIds), %% Remove extra items: - del_items(Host, Node, OldItems), + del_items(NodeId, OldItems), %% Return the new items list: {result, {NewItems, OldItems}}. -%% @spec (Host, Node, JID, ItemId) -> +%% @spec (NodeId, JID, ItemId) -> %% {error, Reason::stanzaError()} | %% {result, []} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% NodeId = mod_pubsub:pubsubNodeId() %% JID = mod_pubsub:jid() %% ItemId = string() %% @doc

    Triggers item deletion.

    %%

    Default plugin: The user performing the deletion must be the node owner %% or a publisher.

    -delete_item(Host, Node, Publisher, ItemId) -> +delete_item(NodeId, Publisher, ItemId) -> SubKey = jlib:jid_tolower(Publisher), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), #pubsub_state{affiliation = Affiliation, items = Items} = GenState, Allowed = (Affiliation == publisher) orelse (Affiliation == owner) - orelse case get_item(Host, Node, ItemId) of + orelse case get_item(NodeId, ItemId) of {result, #pubsub_item{creation = {GenKey, _}}} -> true; _ -> false end, @@ -507,31 +506,31 @@ delete_item(Host, Node, Publisher, ItemId) -> %% Requesting entity does not have sufficient privileges {error, ?ERR_FORBIDDEN}; true -> - case get_item(Host, Node, ItemId) of - {result, _} -> - del_item(Host, Node, ItemId), + case lists:member(ItemId, Items) of + true -> + del_item(NodeId, ItemId), NewItems = lists:delete(ItemId, Items), set_state(GenState#pubsub_state{items = NewItems}), {result, {default, broadcast}}; - _ -> + false -> %% Non-existent node or item {error, ?ERR_ITEM_NOT_FOUND} end end. -%% @spec (Host, Node, Owner) -> +%% @spec (NodeId, Owner) -> %% {error, Reason::stanzaError()} | %% {result, {default, broadcast}} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% NodeId = mod_pubsub:pubsubNodeId() %% Owner = mod_pubsub:jid() -purge_node(Host, Node, Owner) -> +purge_node(NodeId, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), case GenState of #pubsub_state{items = Items, affiliation = owner} -> - del_items(Host, Node, Items), + del_items(NodeId, Items), + set_state(GenState#pubsub_state{items = []}), {result, {default, broadcast}}; _ -> %% Entity is not owner @@ -548,45 +547,44 @@ purge_node(Host, Node, 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( - #pubsub_state{stateid = {GenKey, {Host, '_'}}, _ = '_'}), - Tr = fun(#pubsub_state{stateid = {_, {_, N}}, affiliation = A}) -> + %% TODO check if Host needed + #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), + Tr = fun(#pubsub_state{stateid = {_, N}, affiliation = A}) -> {N, A} end, {result, lists:map(Tr, States)}. -get_node_affiliations(Host, Node) -> - {result, States} = get_states(Host, Node), - Tr = fun(#pubsub_state{stateid = {J, {_, _}}, affiliation = A}) -> +get_node_affiliations(NodeId) -> + {result, States} = get_states(NodeId), + Tr = fun(#pubsub_state{stateid = {J, _}, affiliation = A}) -> {J, A} end, {result, lists:map(Tr, States)}. -get_affiliation(Host, Node, Owner) -> +get_affiliation(NodeId, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), {result, GenState#pubsub_state.affiliation}. -set_affiliation(Host, Node, Owner, Affiliation) -> +set_affiliation(NodeId, Owner, Affiliation) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), case {Affiliation, GenState#pubsub_state.subscription} of {none, none} -> - del_state(GenState#pubsub_state.stateid); + del_state(NodeId, GenKey); _ -> set_state(GenState#pubsub_state{affiliation = Affiliation}) - end, - ok. + end. %% @spec (Host, Owner) -> [{Node,Subscription}] %% Host = host() %% Owner = mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() %% @doc

    Return the current subscriptions for the given user

    %%

    The default module reads subscriptions in the main Mnesia %% pubsub_state table. If a plugin stores its data in the same @@ -594,49 +592,46 @@ set_affiliation(Host, Node, 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 GenKey -> mnesia:match_object( - #pubsub_state{stateid = {{U, D, '_'}, {Host, '_'}}, _ = '_'}); + #pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); _ -> mnesia:match_object( - #pubsub_state{stateid = {GenKey, {Host, '_'}}, _ = '_'}) + #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) ++ mnesia:match_object( - #pubsub_state{stateid = {SubKey, {Host, '_'}}, _ = '_'}) + #pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) end, - Tr = fun(#pubsub_state{stateid = {J, {_, N}}, subscription = S}) -> + Tr = fun(#pubsub_state{stateid = {J, N}, subscription = S}) -> {N, S, J} end, {result, lists:map(Tr, States)}. -get_node_subscriptions(Host, Node) -> - {result, States} = get_states(Host, Node), - Tr = fun(#pubsub_state{stateid = {J, {_, _}}, subscription = S}) -> +get_node_subscriptions(NodeId) -> + {result, States} = get_states(NodeId), + Tr = fun(#pubsub_state{stateid = {J, _}, subscription = S}) -> {J, S} end, {result, lists:map(Tr, States)}. -get_subscription(Host, Node, Owner) -> +get_subscription(NodeId, Owner) -> SubKey = jlib:jid_tolower(Owner), - SubState = get_state(Host, Node, SubKey), + SubState = get_state(NodeId, SubKey), {result, SubState#pubsub_state.subscription}. -set_subscription(Host, Node, Owner, Subscription) -> +set_subscription(NodeId, Owner, Subscription) -> SubKey = jlib:jid_tolower(Owner), - SubState = get_state(Host, Node, SubKey), + SubState = get_state(NodeId, SubKey), case {Subscription, SubState#pubsub_state.affiliation} of {none, none} -> - del_state(SubState#pubsub_state.stateid); + del_state(NodeId, SubKey); _ -> set_state(SubState#pubsub_state{subscription = Subscription}) - end, - ok. + end. -%% @spec (Host, Node) -> [States] | [] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% Item = mod_pubsub:pubsubItems() +%% @spec (NodeId) -> [States] | [] +%% NodeId = mod_pubsub:pubsubNodeId() %% @doc Returns the list of stored states for a given node. %%

    For the default PubSub module, states are stored in Mnesia database.

    %%

    We can consider that the pubsub_state table have been created by the main @@ -645,21 +640,20 @@ set_subscription(Host, Node, Owner, Subscription) -> %% relational database).

    %%

    If a PubSub plugin wants to delegate the states storage to the default node, %% they can implement this function like this: -%% ```get_states(Host, Node) -> -%% node_default:get_states(Host, Node).'''

    -get_states(Host, Node) -> +%% ```get_states(NodeId) -> +%% node_default:get_states(NodeId).'''

    +get_states(NodeId) -> States = mnesia:match_object( - #pubsub_state{stateid = {'_', {Host, Node}}, _ = '_'}), + #pubsub_state{stateid = {'_', NodeId}, _ = '_'}), {result, States}. -%% @spec (JID, Host, Node) -> [State] | [] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% @spec (NodeId, JID) -> [State] | [] +%% NodeId = mod_pubsub:pubsubNodeId() %% JID = mod_pubsub:jid() %% State = mod_pubsub:pubsubItems() %% @doc

    Returns a state (one state list), given its reference.

    -get_state(Host, Node, JID) -> - StateId = {JID, {Host, Node}}, +get_state(NodeId, JID) -> + StateId = {JID, NodeId}, case mnesia:read({pubsub_state, StateId}) of [State] when is_record(State, pubsub_state) -> State; _ -> #pubsub_state{stateid=StateId} @@ -676,12 +670,11 @@ set_state(_) -> %% @spec (StateId) -> ok | {error, Reason::stanzaError()} %% StateId = mod_pubsub:pubsubStateId() %% @doc

    Delete a state from database.

    -del_state(StateId) -> - mnesia:delete({pubsub_state, StateId}). +del_state(NodeId, JID) -> + mnesia:delete({pubsub_state, {JID, NodeId}}). -%% @spec (Host, Node, From) -> [Items] | [] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% @spec (NodeId, From) -> [Items] | [] +%% NodeId = mod_pubsub:pubsubNodeId() %% Items = mod_pubsub:pubsubItems() %% @doc Returns the list of stored items for a given node. %%

    For the default PubSub module, items are stored in Mnesia database.

    @@ -691,16 +684,16 @@ del_state(StateId) -> %% relational database), or they can even decide not to persist any items.

    %%

    If a PubSub plugin wants to delegate the item storage to the default node, %% they can implement this function like this: -%% ```get_items(Host, Node, From) -> -%% node_default:get_items(Host, Node, From).'''

    -get_items(Host, Node, _From) -> +%% ```get_items(NodeId, From) -> +%% node_default:get_items(NodeId, From).'''

    +get_items(NodeId, _From) -> Items = mnesia:match_object( - #pubsub_item{itemid = {'_', {Host, Node}}, _ = '_'}), + #pubsub_item{itemid = {'_', NodeId}, _ = '_'}), {result, Items}. -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), Affiliation = GenState#pubsub_state.affiliation, Subscription = GenState#pubsub_state.subscription, Whitelisted = can_fetch_item(Affiliation, Subscription), @@ -730,26 +723,25 @@ get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubI %% % Payment is required for a subscription %% {error, ?ERR_PAYMENT_REQUIRED}; true -> - get_items(Host, Node, JID) + get_items(NodeId, JID) end. -%% @spec (Host, Node, ItemId) -> [Item] | [] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% @spec (NodeId, ItemId) -> [Item] | [] +%% NodeId = mod_pubsub:pubsubNodeId() %% ItemId = string() %% Item = mod_pubsub:pubsubItems() %% @doc

    Returns an item (one item list), given its reference.

    -get_item(Host, Node, ItemId) -> - case mnesia:read({pubsub_item, {ItemId, {Host, Node}}}) of +get_item(NodeId, ItemId) -> + case mnesia:read({pubsub_item, {ItemId, NodeId}}) of [Item] when is_record(Item, pubsub_item) -> {result, Item}; _ -> {error, ?ERR_ITEM_NOT_FOUND} end. -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Host, Node, GenKey), + GenState = get_state(NodeId, GenKey), Affiliation = GenState#pubsub_state.affiliation, Subscription = GenState#pubsub_state.subscription, Whitelisted = can_fetch_item(Affiliation, Subscription), @@ -779,7 +771,7 @@ get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup %% % Payment is required for a subscription %% {error, ?ERR_PAYMENT_REQUIRED}; true -> - get_item(Host, Node, ItemId) + get_item(NodeId, ItemId) end. %% @spec (Item) -> ok | {error, Reason::stanzaError()} @@ -790,16 +782,15 @@ set_item(Item) when is_record(Item, pubsub_item) -> set_item(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. -%% @spec (Host, Node, ItemId) -> ok | {error, Reason::stanzaError()} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()} +%% NodeId = mod_pubsub:pubsubNodeId() %% ItemId = string() %% @doc

    Delete an item from database.

    -del_item(Host, Node, ItemId) -> - mnesia:delete({pubsub_item, {ItemId, {Host, Node}}}). -del_items(Host, Node, ItemIds) -> +del_item(NodeId, ItemId) -> + mnesia:delete({pubsub_item, {ItemId, NodeId}}). +del_items(NodeId, ItemIds) -> lists:foreach(fun(ItemId) -> - del_item(Host, Node, ItemId) + del_item(NodeId, ItemId) end, ItemIds). %% @doc

    Return the name of the node if known: Default is to return diff --git a/src/mod_pubsub/node_dispatch.erl b/src/mod_pubsub/node_dispatch.erl index 3368fd640..3ef07877d 100644 --- a/src/mod_pubsub/node_dispatch.erl +++ b/src/mod_pubsub/node_dispatch.erl @@ -41,29 +41,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -111,79 +111,81 @@ features() -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(_Host, _Node, _Sender, _Subscriber, _AccessModel, +subscribe_node(_NodeId, _Sender, _Subscriber, _AccessModel, _SendLast, _PresenceSubscription, _RosterGroup) -> {error, ?ERR_FORBIDDEN}. -unsubscribe_node(_Host, _Node, _Sender, _Subscriber, _SubID) -> +unsubscribe_node(_NodeId, _Sender, _Subscriber, _SubID) -> {error, ?ERR_FORBIDDEN}. -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> lists:foreach(fun(SubNode) -> node_default:publish_item( - Host, SubNode, Publisher, Model, + SubNode#pubsub_node.id, Publisher, Model, MaxItems, ItemId, Payload) - end, nodetree_default:get_subnodes(Host, Node, Publisher)). + end, nodetree_default:get_subnodes(NodeId, Publisher)). -remove_extra_items(_Host, _Node, _MaxItems, ItemIds) -> +remove_extra_items(_NodeId, _MaxItems, ItemIds) -> {result, {ItemIds, []}}. -delete_item(_Host, _Node, _JID, _ItemId) -> +delete_item(_NodeId, _JID, _ItemId) -> {error, ?ERR_ITEM_NOT_FOUND}. -purge_node(_Host, _Node, _Owner) -> +purge_node(_NodeId, _Owner) -> {error, ?ERR_FORBIDDEN}. get_entity_affiliations(_Host, _Owner) -> {result, []}. -get_node_affiliations(_Host, _Node) -> +get_node_affiliations(_NodeId) -> {result, []}. -get_affiliation(_Host, _Node, _Owner) -> +get_affiliation(_NodeId, _Owner) -> {result, []}. -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(_Host, _Owner) -> {result, []}. -get_node_subscriptions(_Host, _Node) -> +get_node_subscriptions(NodeId) -> + %% note: get_node_subscriptions is used for broadcasting + %% DO NOT REMOVE + node_default:get_node_subscriptions(NodeId). + +get_subscription(_NodeId, _Owner) -> {result, []}. -get_subscription(_Host, _Node, _Owner) -> - {result, []}. +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_states(Host, Node) -> - node_default:get_states(Host, Node). - -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_flat.erl b/src/mod_pubsub/node_flat.erl index a5abb26c1..db8fed519 100644 --- a/src/mod_pubsub/node_flat.erl +++ b/src/mod_pubsub/node_flat.erl @@ -34,29 +34,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -101,74 +101,74 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> end, {result, Allowed}. -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> - node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> + node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_default:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_default:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_default:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_default:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_default:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_default:get_node_subscriptions(NodeId). -get_subscription(Host, Node, Owner) -> - node_default:get_subscription(Host, Node, Owner). +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_mb.erl b/src/mod_pubsub/node_mb.erl index a092102ad..9116f0f12 100644 --- a/src/mod_pubsub/node_mb.erl +++ b/src/mod_pubsub/node_mb.erl @@ -46,29 +46,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -119,77 +119,77 @@ features() -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_pep:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_pep:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_pep:delete_node(Host, Removed). +delete_node(Removed) -> + node_pep:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> node_pep:subscribe_node( - Host, Node, Sender, Subscriber, AccessModel, SendLast, + NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_pep:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_pep:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_pep:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_pep:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_pep:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_pep:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_pep:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_pep:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_pep:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_pep:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_pep:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_pep:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_pep:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_pep:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_pep:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_pep:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_pep:set_affiliation(NodeId, Owner, Affiliation). -get_entity_subscriptions(Host,Owner) -> +get_entity_subscriptions(Host, Owner) -> node_pep:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_pep:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_pep:get_node_subscriptions(NodeId). -get_subscription(Host,Node,Owner) -> - node_pep:get_subscription(Host,Node,Owner). +get_subscription(NodeId, Owner) -> + node_pep:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_pep:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_pep:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_pep:get_states(Host, Node). +get_states(NodeId) -> + node_pep:get_states(NodeId). -get_state(Host, Node, JID) -> - node_pep:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_pep:get_state(NodeId, JID). set_state(State) -> node_pep:set_state(State). -get_items(Host, Node, From) -> - node_pep:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_pep:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_pep:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_pep:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_pep:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_pep:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_pep:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_pep:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_pep:set_item(Item). diff --git a/src/mod_pubsub/node_pep.erl b/src/mod_pubsub/node_pep.erl index 8fd6fa777..6a89aa1ec 100644 --- a/src/mod_pubsub/node_pep.erl +++ b/src/mod_pubsub/node_pep.erl @@ -39,29 +39,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -131,92 +131,92 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> end, {result, Allowed}. -create_node(Host, Node, Owner) -> - case node_default:create_node(Host, Node, Owner) of +create_node(NodeId, Owner) -> + case node_default:create_node(NodeId, Owner) of {result, _} -> {result, []}; Error -> Error end. -delete_node(Host, Removed) -> - case node_default:delete_node(Host, Removed) of +delete_node(Removed) -> + case node_default:delete_node(Removed) of {result, {_, _, Removed}} -> {result, {[], Removed}}; Error -> Error end. -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> node_default:subscribe_node( - Host, Node, Sender, Subscriber, AccessModel, SendLast, + NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - case node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID) of +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + case node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID) of {error, Error} -> {error, Error}; {result, _} -> {result, []} end. -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(_Host, Owner) -> OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), node_default:get_entity_affiliations(OwnerKey, Owner). -get_node_affiliations(Host, Node) -> - OwnerKey = jlib:jid_remove_resource(Host), - node_default:get_node_affiliations(OwnerKey, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(_Host, Node, Owner) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - node_default:get_affiliation(OwnerKey, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(_Host, Node, Owner, Affiliation) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - State = get_state(OwnerKey, Node, OwnerKey), - set_state(State#pubsub_state{affiliation = Affiliation}), - ok. +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(_Host, _Owner) -> {result, []}. -get_node_subscriptions(_Host, _Node) -> - {result, []}. +get_node_subscriptions(NodeId) -> + %% note: get_node_subscriptions is used for broadcasting + %% there should not have any subscriptions + %% but that call returns also all subscription to none + %% and this is required for broadcast to occurs + %% DO NOT REMOVE + node_default:get_node_subscriptions(NodeId). -get_subscription(_Host, _Node, _Owner) -> +get_subscription(_NodeId, _Owner) -> {result, none}. -set_subscription(_Host, _Node, _Owner, _Subscription) -> +set_subscription(_NodeId, _Owner, _Subscription) -> ok. -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_private.erl b/src/mod_pubsub/node_private.erl index 963e40ad2..0a0e1e5f8 100644 --- a/src/mod_pubsub/node_private.erl +++ b/src/mod_pubsub/node_private.erl @@ -43,29 +43,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -115,76 +115,76 @@ create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> - node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, + node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_default:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_default:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_default:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_default:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_default:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_default:get_node_subscriptions(NodeId). -get_subscription(Host, Node, Owner) -> - node_default:get_subscription(Host, Node, Owner). +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/node_public.erl b/src/mod_pubsub/node_public.erl index e237f17e3..6efe41d33 100644 --- a/src/mod_pubsub/node_public.erl +++ b/src/mod_pubsub/node_public.erl @@ -43,29 +43,29 @@ -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, - create_node/3, - delete_node/2, - purge_node/3, - subscribe_node/8, - unsubscribe_node/5, - publish_item/7, - delete_item/4, - remove_extra_items/4, + create_node/2, + delete_node/1, + purge_node/2, + subscribe_node/7, + unsubscribe_node/4, + publish_item/6, + delete_item/3, + remove_extra_items/3, get_entity_affiliations/2, - get_node_affiliations/2, - get_affiliation/3, - set_affiliation/4, + get_node_affiliations/1, + get_affiliation/2, + set_affiliation/3, get_entity_subscriptions/2, - get_node_subscriptions/2, - get_subscription/3, - set_subscription/4, - get_states/2, - get_state/3, + get_node_subscriptions/1, + get_subscription/2, + set_subscription/3, + get_states/1, + get_state/2, set_state/1, - get_items/7, - get_items/3, - get_item/8, - get_item/3, + get_items/6, + get_items/2, + get_item/7, + get_item/2, set_item/1, get_item_name/3 ]). @@ -114,74 +114,74 @@ features() -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(Host, Node, Owner) -> - node_default:create_node(Host, Node, Owner). +create_node(NodeId, Owner) -> + node_default:create_node(NodeId, Owner). -delete_node(Host, Removed) -> - node_default:delete_node(Host, Removed). +delete_node(Removed) -> + node_default:delete_node(Removed). -subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> - node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). +subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> + node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> - node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> + node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID). -publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> - node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). +publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> + node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(Host, Node, MaxItems, ItemIds) -> - node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). +remove_extra_items(NodeId, MaxItems, ItemIds) -> + node_default:remove_extra_items(NodeId, MaxItems, ItemIds). -delete_item(Host, Node, JID, ItemId) -> - node_default:delete_item(Host, Node, JID, ItemId). +delete_item(NodeId, JID, ItemId) -> + node_default:delete_item(NodeId, JID, ItemId). -purge_node(Host, Node, Owner) -> - node_default:purge_node(Host, Node, Owner). +purge_node(NodeId, Owner) -> + node_default:purge_node(NodeId, Owner). get_entity_affiliations(Host, Owner) -> node_default:get_entity_affiliations(Host, Owner). -get_node_affiliations(Host, Node) -> - node_default:get_node_affiliations(Host, Node). +get_node_affiliations(NodeId) -> + node_default:get_node_affiliations(NodeId). -get_affiliation(Host, Node, Owner) -> - node_default:get_affiliation(Host, Node, Owner). +get_affiliation(NodeId, Owner) -> + node_default:get_affiliation(NodeId, Owner). -set_affiliation(Host, Node, Owner, Affiliation) -> - node_default:set_affiliation(Host, Node, Owner, Affiliation). +set_affiliation(NodeId, Owner, Affiliation) -> + node_default:set_affiliation(NodeId, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_default:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(Host, Node) -> - node_default:get_node_subscriptions(Host, Node). +get_node_subscriptions(NodeId) -> + node_default:get_node_subscriptions(NodeId). -get_subscription(Host, Node, Owner) -> - node_default:get_subscription(Host, Node, Owner). +get_subscription(NodeId, Owner) -> + node_default:get_subscription(NodeId, Owner). -set_subscription(Host, Node, Owner, Subscription) -> - node_default:set_subscription(Host, Node, Owner, Subscription). +set_subscription(NodeId, Owner, Subscription) -> + node_default:set_subscription(NodeId, Owner, Subscription). -get_states(Host, Node) -> - node_default:get_states(Host, Node). +get_states(NodeId) -> + node_default:get_states(NodeId). -get_state(Host, Node, JID) -> - node_default:get_state(Host, Node, JID). +get_state(NodeId, JID) -> + node_default:get_state(NodeId, JID). set_state(State) -> node_default:set_state(State). -get_items(Host, Node, From) -> - node_default:get_items(Host, Node, From). +get_items(NodeId, From) -> + node_default:get_items(NodeId, From). -get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). -get_item(Host, Node, ItemId) -> - node_default:get_item(Host, Node, ItemId). +get_item(NodeId, ItemId) -> + node_default:get_item(NodeId, ItemId). -get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> node_default:set_item(Item). diff --git a/src/mod_pubsub/nodetree_default.erl b/src/mod_pubsub/nodetree_default.erl index eff49727e..fa3516950 100644 --- a/src/mod_pubsub/nodetree_default.erl +++ b/src/mod_pubsub/nodetree_default.erl @@ -50,7 +50,7 @@ get_nodes/2, get_nodes/1, get_subnodes/3, - get_subnodes_tree/2, + get_subnodes_tree/3, create_node/5, delete_node/2 ]). @@ -75,9 +75,10 @@ init(_Host, _ServerHost, _Opts) -> {attributes, record_info(fields, pubsub_node)}]), NodesFields = record_info(fields, pubsub_node), case mnesia:table_info(pubsub_node, attributes) of - [host_node, host_parent, info] -> ok; % old schema, updated later by pubsub NodesFields -> ok; - _ -> mnesia:transform_table(pubsub_node, ignore, NodesFields) + _ -> + ok + %% mnesia:transform_table(pubsub_state, ignore, StatesFields) end, ok. terminate(_Host, _ServerHost) -> @@ -96,12 +97,11 @@ set_node(Record) when is_record(Record, pubsub_node) -> set_node(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. -get_node(Host, Node, _From) -> - get_node(Host, Node). - %% @spec (Host, Node) -> pubsubNode() | {error, Reason} %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() +get_node(Host, Node, _From) -> + get_node(Host, Node). get_node(Host, Node) -> case catch mnesia:read({pubsub_node, {Host, Node}}) of [Record] when is_record(Record, pubsub_node) -> Record; @@ -109,44 +109,48 @@ get_node(Host, Node) -> Error -> Error end. -get_nodes(Key, _From) -> - get_nodes(Key). - -%% @spec (Key) -> [pubsubNode()] | {error, Reason} -%% Key = mod_pubsub:host() | mod_pubsub:jid() -get_nodes(Key) -> - mnesia:match_object(#pubsub_node{nodeid = {Key, '_'}, _ = '_'}). +%% @spec (Host) -> [pubsubNode()] | {error, Reason} +%% Host = mod_pubsub:host() | mod_pubsub:jid() +get_nodes(Host, _From) -> + get_nodes(Host). +get_nodes(Host) -> + mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}). %% @spec (Host, Node, From) -> [pubsubNode()] | {error, Reason} %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() %% From = mod_pubsub:jid() get_subnodes(Host, Node, _From) -> - mnesia:match_object(#pubsub_node{parentid = {Host, Node}, _ = '_'}). + get_subnodes(Host, Node). +get_subnodes(Host, Node) -> + mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, parent = Node, _ = '_'}). -%% @spec (Host, Index) -> [pubsubNode()] | {error, Reason} +%% @spec (Host, Index) -> [pubsubNodeIdx()] | {error, Reason} %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() +%% From = mod_pubsub:jid() +get_subnodes_tree(Host, Node, _From) -> + get_subnodes_tree(Host, Node). get_subnodes_tree(Host, Node) -> - mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}}, Acc) -> + mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) -> case lists:prefix(Node, N) and (H == Host) of - true -> [N | Acc]; + true -> [R | Acc]; _ -> Acc end end, [], pubsub_node). -%% @spec (Key, Node, Type, Owner, Options) -> ok | {error, Reason} -%% Key = mod_pubsub:host() | mod_pubsub:jid() +%% @spec (Host, Node, Type, Owner, Options) -> ok | {error, Reason} +%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Node = mod_pubsub:pubsubNode() %% NodeType = mod_pubsub:nodeType() %% Owner = mod_pubsub:jid() %% Options = list() -create_node(Key, Node, Type, Owner, Options) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - case mnesia:read({pubsub_node, {Key, Node}}) of +create_node(Host, Node, Type, Owner, Options) -> + BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + case mnesia:read({pubsub_node, {Host, Node}}) of [] -> {ParentNode, ParentExists} = - case Key of + case Host of {_U, _S, _R} -> %% This is special case for PEP handling %% PEP does not uses hierarchy @@ -157,7 +161,7 @@ create_node(Key, Node, Type, Owner, Options) -> [] -> {[], true}; _ -> - case mnesia:read({pubsub_node, {Key, Parent}}) of + case mnesia:read({pubsub_node, {Host, Parent}}) of [] -> {Parent, false}; _ -> {Parent, true} end @@ -165,13 +169,14 @@ create_node(Key, Node, Type, Owner, Options) -> end, case ParentExists of true -> - %% Service requires registration - %%{error, ?ERR_REGISTRATION_REQUIRED}; - mnesia:write(#pubsub_node{nodeid = {Key, Node}, - parentid = {Key, ParentNode}, + NodeId = pubsub_index:new(node), + mnesia:write(#pubsub_node{nodeid = {Host, Node}, + id = NodeId, + parent = ParentNode, type = Type, - owners = [OwnerKey], - options = Options}); + owners = [BJID], + options = Options}), + {ok, NodeId}; false -> %% Requesting entity is prohibited from creating nodes {error, ?ERR_FORBIDDEN} @@ -181,12 +186,13 @@ create_node(Key, Node, Type, Owner, Options) -> {error, ?ERR_CONFLICT} end. -%% @spec (Key, Node) -> [mod_pubsub:node()] -%% Key = mod_pubsub:host() | mod_pubsub:jid() +%% @spec (Host, Node) -> [mod_pubsub:node()] +%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Node = mod_pubsub:pubsubNode() -delete_node(Key, Node) -> - Removed = get_subnodes_tree(Key, Node), - lists:foreach(fun(N) -> - mnesia:delete({pubsub_node, {Key, N}}) - end, Removed), +delete_node(Host, Node) -> + Removed = get_subnodes_tree(Host, Node), + lists:foreach(fun(#pubsub_node{nodeid = {_, N}, id = I}) -> + pubsub_index:free(node, I), + mnesia:delete({pubsub_node, {Host, N}}) + end, Removed), Removed. diff --git a/src/mod_pubsub/nodetree_virtual.erl b/src/mod_pubsub/nodetree_virtual.erl index dcfd9e5ef..6913b6e43 100644 --- a/src/mod_pubsub/nodetree_virtual.erl +++ b/src/mod_pubsub/nodetree_virtual.erl @@ -48,7 +48,7 @@ get_nodes/2, get_nodes/1, get_subnodes/3, - get_subnodes_tree/2, + get_subnodes_tree/3, create_node/5, delete_node/2 ]). @@ -94,14 +94,13 @@ get_node(Host, Node, _From) -> get_node(Host, Node) -> #pubsub_node{nodeid = {Host, Node}}. -get_nodes(Key, _From) -> - get_nodes(Key). - -%% @spec (Key) -> [pubsubNode()] +%% @spec (Host) -> [pubsubNode()] %% Host = mod_pubsub:host() | mod_pubsub:jid() %% @doc

    Virtual node tree does not handle a node database. Any node is considered %% as existing. Nodes list can not be determined.

    -get_nodes(_Key) -> +get_nodes(Host, _From) -> + get_nodes(Host). +get_nodes(_Host) -> []. %% @spec (Host, Node, From) -> [pubsubNode()] @@ -109,13 +108,17 @@ get_nodes(_Key) -> %% Node = mod_pubsub:pubsubNode() %% From = mod_pubsub:jid() %% @doc

    Virtual node tree does not handle parent/child. Child list is empty.

    -get_subnodes(_Host, _Node, _From) -> +get_subnodes(Host, Node, _From) -> + get_subnodes(Host, Node). +get_subnodes(_Host, _Node) -> []. %% @spec (Host, Index) -> [pubsubNode()] %% Host = mod_pubsub:host() %% Node = mod_pubsub:pubsubNode() %% @doc

    Virtual node tree does not handle parent/child. Child list is empty.

    +get_subnodes_tree(Host, Node, _From) -> + get_subnodes_tree(Host, Node). get_subnodes_tree(_Host, _Node) -> []. @@ -128,11 +131,11 @@ get_subnodes_tree(_Host, _Node) -> %% @doc

    No node record is stored on database. Any valid node %% is considered as already created.

    %%

    default allowed nodes: /home/host/user/any/node/name

    -create_node(_Host, Node, _Type, Owner, _Options) -> +create_node(Host, Node, _Type, Owner, _Options) -> UserName = Owner#jid.luser, UserHost = Owner#jid.lserver, case Node of - ["home", UserHost, UserName | _] -> {error, ?ERR_CONFLICT}; + ["home", UserHost, UserName | _] -> {error, {virtual, {Host, Node}}}; _ -> {error, ?ERR_NOT_ALLOWED} end. @@ -141,5 +144,5 @@ create_node(_Host, Node, _Type, Owner, _Options) -> %% Node = mod_pubsub:pubsubNode() %% @doc

    Virtual node tree does not handle parent/child. %% node deletion just affects the corresponding node.

    -delete_node(_Host, Node) -> - [Node]. +delete_node(Host, Node) -> + [get_node(Host, Node)]. diff --git a/src/mod_pubsub/pubsub.hrl b/src/mod_pubsub/pubsub.hrl index 46cbe9b95..87088eb6a 100644 --- a/src/mod_pubsub/pubsub.hrl +++ b/src/mod_pubsub/pubsub.hrl @@ -77,24 +77,28 @@ %%% @type affiliation() = none | owner | publisher | outcast. %%% @type subscription() = none | pending | unconfigured | subscribed. +%%% internal pubsub index table +-record(pubsub_index, {index, last, free}). + %%% @type pubsubNode() = #pubsub_node{ %%% nodeid = {Host::host(), Node::pubsubNode()}, %%% parentid = {Host::host(), Node::pubsubNode()}, +%%% nodeidx = int(). %%% type = nodeType(), -%%% owners = [ljid()], -%%% options = [nodeOption()]}. +%%% options = [nodeOption()]} %%%

    This is the format of the nodes table. The type of the table %%% is: set,ram/disc.

    %%%

    The parentid and type fields are indexed.

    -record(pubsub_node, {nodeid, - parentid = {}, - type = "", + id, + parent, + type = "default", owners = [], options = [] }). %%% @type pubsubState() = #pubsub_state{ -%%% stateid = {ljid(), {Host::host(), Node::pubsubNode()}}, +%%% stateid = {ljid(), pubsubNodeId()}}, %%% items = [ItemId::string()], %%% affiliation = affiliation(), %%% subscription = subscription()}. @@ -106,11 +110,11 @@ subscription = none }). -%% @type pubsubItem() = #pubsub_item{ -%% itemid = {ItemId::string(), {Host::host(),Node::pubsubNode()}}, -%% creation = {ljid(), now()}, -%% modification = {ljid(), now()}, -%% payload = XMLContent::string()}. +%%% @type pubsubItem() = #pubsub_item{ +%%% itemid = {ItemId::string(), pubsubNodeId()}}, +%%% creation = {ljid(), now()}, +%%% modification = {ljid(), now()}, +%%% payload = XMLContent::string()}. %%%

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

    -record(pubsub_item, {itemid, diff --git a/src/mod_pubsub/pubsub_index.erl b/src/mod_pubsub/pubsub_index.erl new file mode 100644 index 000000000..2ba5d4b20 --- /dev/null +++ b/src/mod_pubsub/pubsub_index.erl @@ -0,0 +1,65 @@ +%%% ==================================================================== +%%% ``The contents of this file are subject to the Erlang Public License, +%%% Version 1.1, (the "License"); you may not use this file except in +%%% compliance with the License. You should have received a copy of the +%%% Erlang Public License along with this software. If not, it can be +%%% retrieved via the world wide web at http://www.erlang.org/. +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and limitations +%%% under the License. +%%% +%%% The Initial Developer of the Original Code is ProcessOne. +%%% Portions created by ProcessOne are Copyright 2006-2009, ProcessOne +%%% All Rights Reserved.'' +%%% This software is copyright 2006-2009, ProcessOne. +%%% +%%% +%%% @copyright 2006-2009 ProcessOne +%%% @author Christophe Romain +%%% [http://www.process-one.net/] +%%% @version {@vsn}, {@date} {@time} +%%% @end +%%% ==================================================================== + +%% important note: +%% new/1 and free/2 MUST be called inside a transaction bloc + +-module(pubsub_index). +-author('christophe.romain@process-one.net'). + +-include("pubsub.hrl"). + +-export([init/3, new/1, free/2]). + +init(_Host, _ServerHost, _Opts) -> + mnesia:create_table(pubsub_index, + [{disc_copies, [node()]}, + {attributes, record_info(fields, pubsub_index)}]). + +new(Index) -> + case mnesia:read({pubsub_index, Index}) of + [I] -> + case I#pubsub_index.free of + [] -> + Id = I#pubsub_index.last + 1, + mnesia:write(I#pubsub_index{last = Id}), + Id; + [Id|Free] -> + mnesia:write(I#pubsub_index{free = Free}), + Id + end; + _ -> + mnesia:write(#pubsub_index{index = Index, last = 1, free = []}), + 1 + end. + +free(Index, Id) -> + case mnesia:read({pubsub_index, Index}) of + [I] -> + Free = I#pubsub_index.free, + mnesia:write(I#pubsub_index{free = [Id|Free]}); + _ -> + ok + end.