aboutsummaryrefslogtreecommitdiff
path: root/src/mod_pubsub
diff options
context:
space:
mode:
authorChristophe Romain <christophe.romain@process-one.net>2009-04-30 05:18:06 +0000
committerChristophe Romain <christophe.romain@process-one.net>2009-04-30 05:18:06 +0000
commitf8780bc6ee15e738807531df2489173b7da19561 (patch)
tree0f03e2da5cdc312336716464125cf702101ebf97 /src/mod_pubsub
parent* src/ejabberd_hooks.erl: Support distributed hooks (EJAB-829) (diff)
PubSub/PEP API change for major optimization
SVN Revision: 2048
Diffstat (limited to 'src/mod_pubsub')
-rw-r--r--src/mod_pubsub/gen_pubsub_node.erl40
-rw-r--r--src/mod_pubsub/gen_pubsub_nodetree.erl2
-rw-r--r--src/mod_pubsub/mod_pubsub.erl830
-rw-r--r--src/mod_pubsub/node.template122
-rw-r--r--src/mod_pubsub/node_buddy.erl120
-rw-r--r--src/mod_pubsub/node_club.erl120
-rw-r--r--src/mod_pubsub/node_default.erl321
-rw-r--r--src/mod_pubsub/node_dispatch.erl108
-rw-r--r--src/mod_pubsub/node_flat.erl120
-rw-r--r--src/mod_pubsub/node_mb.erl122
-rw-r--r--src/mod_pubsub/node_pep.erl126
-rw-r--r--src/mod_pubsub/node_private.erl120
-rw-r--r--src/mod_pubsub/node_public.erl120
-rw-r--r--src/mod_pubsub/nodetree_default.erl80
-rw-r--r--src/mod_pubsub/nodetree_virtual.erl25
-rw-r--r--src/mod_pubsub/pubsub.hrl24
-rw-r--r--src/mod_pubsub/pubsub_index.erl65
17 files changed, 1306 insertions, 1159 deletions
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) ->
%%</ul>
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) ->
%%<li>The specified node does not exist.</li>
%%</ul>
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 <p>Return the items of a given node.</p>
@@ -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 <p>Resend the items of a node to the user.</p>
%% @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).
-
-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;
- _ ->
- {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_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_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_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_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;
- _ ->
+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).
+ 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) ->
%%</ul>
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 <p>node tree plugin call.</p>
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 <p>node plugin call.</p>
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 <p>plugin transaction handling.</p>
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() ->
%% <p>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).'''</p>
+%% ```check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
+%% node_default:check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access).'''</p>
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 <p></p>
-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 <p>purge items of deleted nodes after effective deletion.</p>
-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}}.
-
-%% @spec (Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
+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 (NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
%% {error, Reason} | {result, Result}
%% @doc <p>Accepts or rejects subcription requests on a PubSub node.</p>
%% <p>The mechanism works as follow:
@@ -274,17 +275,18 @@ delete_node(Host, Removed) ->
%% to completly disable persistance.</li></ul>
%% </p>
%% <p>In the default plugin module, the record is unchanged.</p>
-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 <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p>
-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.</li></ul>
%% </p>
%% <p>In the default plugin module, the record is unchanged.</p>
-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.</p>
%% <p>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).'''</p>
-remove_extra_items(_Host, _Node, unlimited, ItemIds) ->
+%% ```remove_extra_items(NodeId, MaxItems, ItemIds) ->
+%% node_default:remove_extra_items(NodeId, MaxItems, ItemIds).'''</p>
+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 <p>Triggers item deletion.</p>
%% <p>Default plugin: The user performing the deletion must be the node owner
%% or a publisher.</p>
-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
%% <tt>pubsub_state</tt> table.</p>
-get_entity_affiliations(Host, Owner) ->
+get_entity_affiliations(_Host, Owner) ->
SubKey = jlib:jid_tolower(Owner),
GenKey = jlib:jid_remove_resource(SubKey),
States = mnesia:match_object(
- #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 <p>Return the current subscriptions for the given user</p>
%% <p>The default module reads subscriptions in the main Mnesia
%% <tt>pubsub_state</tt> 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
%% <tt>pubsub_state</tt> table.</p>
-get_entity_subscriptions(Host, Owner) ->
+get_entity_subscriptions(_Host, Owner) ->
{U, D, _} = SubKey = jlib:jid_tolower(Owner),
GenKey = jlib:jid_remove_resource(SubKey),
States = case SubKey of
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.
%% <p>For the default PubSub module, states are stored in Mnesia database.</p>
%% <p>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).</p>
%% <p>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).'''</p>
-get_states(Host, Node) ->
+%% ```get_states(NodeId) ->
+%% node_default:get_states(NodeId).'''</p>
+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 <p>Returns a state (one state list), given its reference.</p>
-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 <p>Delete a state from database.</p>
-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.
%% <p>For the default PubSub module, items are stored in Mnesia database.</p>
@@ -691,16 +684,16 @@ del_state(StateId) ->
%% relational database), or they can even decide not to persist any items.</p>
%% <p>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).'''</p>
-get_items(Host, Node, _From) ->
+%% ```get_items(NodeId, From) ->
+%% node_default:get_items(NodeId, From).'''</p>
+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 <p>Returns an item (one item list), given its reference.</p>
-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 <p>Delete an item from database.</p>
-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 <p>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) ->
- {result, []}.
+get_node_subscriptions(NodeId) ->
+ %% note: get_node_subscriptions is used for broadcasting
+ %% DO NOT REMOVE
+ node_default:get_node_subscriptions(NodeId).
-get_subscription(_Host, _Node, _Owner) ->
+get_subscription(_NodeId, _Owner) ->
{result, []}.
-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_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 <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Nodes list can not be determined.</p>
-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 <p>Virtual node tree does not handle parent/child. Child list is empty.</p>
-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 <p>Virtual node tree does not handle parent/child. Child list is empty.</p>
+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 <p>No node record is stored on database. Any valid node
%% is considered as already created.</p>
%% <p>default allowed nodes: /home/host/user/any/node/name</p>
-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 <p>Virtual node tree does not handle parent/child.
%% node deletion just affects the corresponding node.</p>
-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()]}
%%% <p>This is the format of the <tt>nodes</tt> table. The type of the table
%%% is: <tt>set</tt>,<tt>ram/disc</tt>.</p>
%%% <p>The <tt>parentid</tt> and <tt>type</tt> fields are indexed.</p>
-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()}.
%%% <p>This is the format of the <tt>published items</tt> table. The type of the
%%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p>
-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 <christophe.romain@process-one.net>
+%%% [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.