25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-30 16:36:29 +01:00

clean nodeid/nidx variables names (thanks to Karim)(EJAB-1000)

This commit is contained in:
Christophe Romain 2010-09-10 19:45:28 +02:00
parent 556892aebf
commit 4b5b98b465
25 changed files with 1017 additions and 1019 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -123,8 +123,8 @@ delete_node(Removed) ->
subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -130,8 +130,8 @@ delete_node(Removed) ->
subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) ->
node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -128,8 +128,8 @@ delete_node(Removed) ->
subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) ->
node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -73,33 +73,33 @@ create_node_permission(_Host, _ServerHost, _Node, _ParentNode,
_Owner, _Access) -> _Owner, _Access) ->
{result, true}. {result, true}.
create_node(NodeID, Owner) -> create_node(NodeId, Owner) ->
node_flat:create_node(NodeID, Owner). node_flat:create_node(NodeId, Owner).
delete_node(Removed) -> delete_node(Removed) ->
node_flat:delete_node(Removed). node_flat:delete_node(Removed).
subscribe_node(NodeID, Sender, Subscriber, AccessModel, subscribe_node(NodeId, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup, Options) -> SendLast, PresenceSubscription, RosterGroup, Options) ->
node_flat:subscribe_node(NodeID, Sender, Subscriber, AccessModel, node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup, SendLast, PresenceSubscription, RosterGroup,
Options). Options).
unsubscribe_node(NodeID, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeID, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeID, Publisher, Model, MaxItems, ItemID, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
%% TODO: should look up the NodeTree plugin here. There's no %% TODO: should look up the NodeTree plugin here. There's no
%% access to the Host of the request at this level, so for now we %% access to the Host of the request at this level, so for now we
%% just use nodetree_dag. %% just use nodetree_dag.
case nodetree_dag:get_node(NodeID) of case nodetree_dag:get_node(NodeId) of
#pubsub_node{options = Options} -> #pubsub_node{options = Options} ->
case find_opt(node_type, Options) of case find_opt(node_type, Options) of
collection -> collection ->
{error, mod_pubsub:extended_error('not-allowed', "publish")}; {error, mod_pubsub:extended_error('not-allowed', "publish")};
_ -> _ ->
node_flat:publish_item(NodeID, Publisher, Model, node_flat:publish_item(NodeId, Publisher, Model,
MaxItems, ItemID, Payload) MaxItems, ItemId, Payload)
end; end;
Err -> Err ->
Err Err
@ -109,72 +109,72 @@ find_opt(_, []) -> false;
find_opt(Option, [{Option, Value} | _]) -> Value; find_opt(Option, [{Option, Value} | _]) -> Value;
find_opt(Option, [_ | T]) -> find_opt(Option, T). find_opt(Option, [_ | T]) -> find_opt(Option, T).
remove_extra_items(NodeID, MaxItems, ItemIDs) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_flat:remove_extra_items(NodeID, MaxItems, ItemIDs). node_flat:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(NodeID, Publisher, PublishModel, ItemID) -> delete_item(NodeId, Publisher, PublishModel, ItemId) ->
node_flat:delete_item(NodeID, Publisher, PublishModel, ItemID). node_flat:delete_item(NodeId, Publisher, PublishModel, ItemId).
purge_node(NodeID, Owner) -> purge_node(NodeId, Owner) ->
node_flat:purge_node(NodeID, Owner). node_flat:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_flat:get_entity_affiliations(Host, Owner). node_flat:get_entity_affiliations(Host, Owner).
get_node_affiliations(NodeID) -> get_node_affiliations(NodeId) ->
node_flat:get_node_affiliations(NodeID). node_flat:get_node_affiliations(NodeId).
get_affiliation(NodeID, Owner) -> get_affiliation(NodeId, Owner) ->
node_flat:get_affiliation(NodeID, Owner). node_flat:get_affiliation(NodeId, Owner).
set_affiliation(NodeID, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_flat:set_affiliation(NodeID, Owner, Affiliation). node_flat:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_flat:get_entity_subscriptions(Host, Owner). node_flat:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(NodeID) -> get_node_subscriptions(NodeId) ->
node_flat:get_node_subscriptions(NodeID). node_flat:get_node_subscriptions(NodeId).
get_subscriptions(NodeID, Owner) -> get_subscriptions(NodeId, Owner) ->
node_flat:get_subscriptions(NodeID, Owner). node_flat:get_subscriptions(NodeId, Owner).
set_subscriptions(NodeID, Owner, Subscription, SubID) -> set_subscriptions(NodeId, Owner, Subscription, SubId) ->
node_flat:set_subscriptions(NodeID, Owner, Subscription, SubID). node_flat:set_subscriptions(NodeId, Owner, Subscription, SubId).
get_pending_nodes(Host, Owner) -> get_pending_nodes(Host, Owner) ->
node_flat:get_pending_nodes(Host, Owner). node_flat:get_pending_nodes(Host, Owner).
get_states(NodeID) -> get_states(NodeId) ->
node_flat:get_states(NodeID). node_flat:get_states(NodeId).
get_state(NodeID, JID) -> get_state(NodeId, JID) ->
node_flat:get_state(NodeID, JID). node_flat:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_flat:set_state(State). node_flat:set_state(State).
get_items(NodeID, From) -> get_items(NodeId, From) ->
node_flat:get_items(NodeID, From). node_flat:get_items(NodeId, From).
get_items(NodeID, JID, AccessModel, PresenceSubscription, get_items(NodeId, JID, AccessModel, PresenceSubscription,
RosterGroup, SubID) -> RosterGroup, SubId) ->
node_flat:get_items(NodeID, JID, AccessModel, PresenceSubscription, node_flat:get_items(NodeId, JID, AccessModel, PresenceSubscription,
RosterGroup, SubID). RosterGroup, SubId).
get_item(NodeID, ItemID) -> get_item(NodeId, ItemId) ->
node_flat:get_item(NodeID, ItemID). node_flat:get_item(NodeId, ItemId).
get_item(NodeID, ItemID, JID, AccessModel, PresenceSubscription, get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription,
RosterGroup, SubID) -> RosterGroup, SubId) ->
node_flat:get_item(NodeID, ItemID, JID, AccessModel, node_flat:get_item(NodeId, ItemId, JID, AccessModel,
PresenceSubscription, RosterGroup, SubID). PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_flat:set_item(Item). node_flat:set_item(Item).
get_item_name(Host, Node, ID) -> get_item_name(Host, Node, ItemId) ->
node_flat:get_item_name(Host, Node, ID). node_flat:get_item_name(Host, Node, ItemId).
node_to_path(Node) -> node_to_path(Node) ->
node_flat:node_to_path(Node). node_flat:node_to_path(Node).

View File

@ -126,13 +126,13 @@ subscribe_node(_NodeId, _Sender, _Subscriber, _AccessModel,
_SendLast, _PresenceSubscription, _RosterGroup, _Options) -> _SendLast, _PresenceSubscription, _RosterGroup, _Options) ->
{error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}. {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}.
unsubscribe_node(_NodeId, _Sender, _Subscriber, _SubID) -> unsubscribe_node(_NodeId, _Sender, _Subscriber, _SubId) ->
{error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}. {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}.
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
lists:foreach(fun(SubNode) -> lists:foreach(fun(SubNode) ->
node_flat:publish_item( node_flat:publish_item(
SubNode#pubsub_node.id, Publisher, Model, SubNode#pubsub_node.idx, Publisher, Model,
MaxItems, ItemId, Payload) MaxItems, ItemId, Payload)
end, nodetree_tree:get_subnodes(NodeId, Publisher, Publisher)). end, nodetree_tree:get_subnodes(NodeId, Publisher, Publisher)).

View File

@ -195,30 +195,30 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) ->
%% @spec (NodeId, Owner) -> %% @spec (NodeId, Owner) ->
%% {result, Result} | exit %% {result, Result} | exit
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% @doc <p></p> %% @doc <p></p>
create_node(NodeId, Owner) -> create_node(NodeId, Owner) ->
OwnerKey = jlib:short_prepd_bare_jid(Owner), OwnerKey = jlib:short_prepd_bare_jid(Owner),
set_state(#pubsub_state{stateid = {OwnerKey, NodeId}, affiliation = owner}), set_state(#pubsub_state{id = {OwnerKey, NodeId}, affiliation = owner}),
{result, {default, broadcast}}. {result, {default, broadcast}}.
%% @spec (Removed) -> ok %% @spec (Removed) -> ok
%% Removed = [mod_pubsub:pubsubNode()] %% Removed = [mod_pubsub:pubsub_node()]
%% @doc <p>purge items of deleted nodes after effective deletion.</p> %% @doc <p>purge items of deleted nodes after effective deletion.</p>
delete_node(Removed) -> delete_node(Removed) ->
Tr = fun(#pubsub_state{stateid = {J, _}, subscriptions = Ss}) -> Tr = fun(#pubsub_state{id = {J, _}, subscriptions = Ss}) ->
lists:map(fun(S) -> lists:map(fun(S) ->
{J, S} {J, S}
end, Ss) end, Ss)
end, end,
Reply = lists:map( Reply = lists:map(
fun(#pubsub_node{id = NodeId} = PubsubNode) -> fun(#pubsub_node{idx = Nidx} = PubsubNode) ->
{result, States} = get_states(NodeId), {result, States} = get_states(Nidx),
lists:foreach( lists:foreach(
fun(#pubsub_state{stateid = {LJID, _}, items = Items}) -> fun(#pubsub_state{id = {LJID, _}, items = Items}) ->
del_items(NodeId, Items), del_items(Nidx, Items),
del_state(NodeId, LJID) del_state(Nidx, LJID)
end, States), end, States),
{PubsubNode, lists:flatmap(Tr, States)} {PubsubNode, lists:flatmap(Tr, States)}
end, Removed), end, Removed),
@ -321,9 +321,9 @@ subscribe_node(NodeId, Sender, {U,S,R} = Subscriber, AccessModel,
%% @spec (NodeId, Sender, Subscriber, SubId) -> %% @spec (NodeId, Sender, Subscriber, SubId) ->
%% {error, Reason} | {result, []} %% {error, Reason} | {result, []}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Sender = mod_pubsub:jid() %% Sender = ljid()
%% Subscriber = mod_pubsub:jid() %% Subscriber = ljid()
%% SubId = mod_pubsub:subid() %% SubId = mod_pubsub:subid()
%% Reason = mod_pubsub:stanzaError() %% Reason = mod_pubsub:stanzaError()
%% @doc <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p> %% @doc <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p>
@ -399,11 +399,11 @@ delete_subscriptions(SubKey, NodeId, Subscriptions, SubState) ->
%% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
%% {true, PubsubItem} | {result, Reply} %% {true, PubsubItem} | {result, Reply}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Publisher = mod_pubsub:jid() %% Publisher = ljid()
%% PublishModel = atom() %% PublishModel = atom()
%% MaxItems = integer() %% MaxItems = integer()
%% ItemId = string() %% ItemId = item()
%% Payload = term() %% Payload = term()
%% @doc <p>Publishes the item passed as parameter.</p> %% @doc <p>Publishes the item passed as parameter.</p>
%% <p>The mechanism works as follow: %% <p>The mechanism works as follow:
@ -465,7 +465,7 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
OldItem#pubsub_item{modification = PubId, OldItem#pubsub_item{modification = PubId,
payload = Payload}; payload = Payload};
_ -> _ ->
#pubsub_item{itemid = {ItemId, NodeId}, #pubsub_item{id = {ItemId, NodeId},
creation = {Now, GenKey}, creation = {Now, GenKey},
modification = PubId, modification = PubId,
payload = Payload} payload = Payload}
@ -481,7 +481,7 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
end. end.
%% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} %% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% MaxItems = integer() | unlimited %% MaxItems = integer() | unlimited
%% ItemIds = [ItemId::string()] %% ItemIds = [ItemId::string()]
%% NewItemIds = [ItemId::string()] %% NewItemIds = [ItemId::string()]
@ -508,10 +508,10 @@ remove_extra_items(NodeId, MaxItems, ItemIds) ->
%% @spec (NodeId, Publisher, PublishModel, ItemId) -> %% @spec (NodeId, Publisher, PublishModel, ItemId) ->
%% {error, Reason::stanzaError()} | %% {error, Reason::stanzaError()} |
%% {result, []} %% {result, []}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Publisher = mod_pubsub:jid() %% Publisher = ljid()
%% PublishModel = atom() %% PublishModel = atom()
%% ItemId = string() %% ItemId = item()
%% @doc <p>Triggers item deletion.</p> %% @doc <p>Triggers item deletion.</p>
%% <p>Default plugin: The user performing the deletion must be the node owner %% <p>Default plugin: The user performing the deletion must be the node owner
%% or a publisher, or PublishModel being open.</p> %% or a publisher, or PublishModel being open.</p>
@ -563,8 +563,8 @@ delete_item(NodeId, Publisher, PublishModel, ItemId) ->
%% @spec (NodeId, Owner) -> %% @spec (NodeId, Owner) ->
%% {error, Reason::stanzaError()} | %% {error, Reason::stanzaError()} |
%% {result, {default, broadcast}} %% {result, {default, broadcast}}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
purge_node(NodeId, Owner) -> purge_node(NodeId, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
GenState = get_state(NodeId, GenKey), GenState = get_state(NodeId, GenKey),
@ -586,7 +586,7 @@ purge_node(NodeId, Owner) ->
%% @spec (Host, JID) -> [{Node,Affiliation}] %% @spec (Host, JID) -> [{Node,Affiliation}]
%% Host = host() %% Host = host()
%% JID = mod_pubsub:jid() %% JID = ljid()
%% @doc <p>Return the current affiliations for the given user</p> %% @doc <p>Return the current affiliations for the given user</p>
%% <p>The default module reads affiliations in the main Mnesia %% <p>The default module reads affiliations in the main Mnesia
%% <tt>pubsub_state</tt> table. If a plugin stores its data in the same %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same
@ -596,14 +596,14 @@ purge_node(NodeId, Owner) ->
%% <tt>pubsub_state</tt> table.</p> %% <tt>pubsub_state</tt> table.</p>
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), States = mnesia:match_object(#pubsub_state{id = {GenKey, '_'}, _ = '_'}),
NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of
[{nodetree, N}] -> N; [{nodetree, N}] -> N;
_ -> nodetree_tree _ -> nodetree_tree
end, end,
Reply = lists:foldl(fun(#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> Reply = lists:foldl(fun(#pubsub_state{id = {_, N}, affiliation = A}, Acc) ->
case NodeTree:get_node(N) of case NodeTree:get_node(N) of
#pubsub_node{nodeid = {Host, _}} = Node -> [{Node, A}|Acc]; #pubsub_node{id = {Host, _}} = Node -> [{Node, A}|Acc];
_ -> Acc _ -> Acc
end end
end, [], States), end, [], States),
@ -611,7 +611,7 @@ get_entity_affiliations(Host, Owner) ->
get_node_affiliations(NodeId) -> get_node_affiliations(NodeId) ->
{result, States} = get_states(NodeId), {result, States} = get_states(NodeId),
Tr = fun(#pubsub_state{stateid = {J, _}, affiliation = A}) -> Tr = fun(#pubsub_state{id = {J, _}, affiliation = A}) ->
{J, A} {J, A}
end, end,
{result, lists:map(Tr, States)}. {result, lists:map(Tr, States)}.
@ -633,7 +633,7 @@ set_affiliation(NodeId, Owner, Affiliation) when ?IS_JID(Owner)->
%% @spec (Host, Owner) -> [{Node,Subscription}] %% @spec (Host, Owner) -> [{Node,Subscription}]
%% Host = host() %% Host = host()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% @doc <p>Return the current subscriptions for the given user</p> %% @doc <p>Return the current subscriptions for the given user</p>
%% <p>The default module reads subscriptions in the main Mnesia %% <p>The default module reads subscriptions in the main Mnesia
%% <tt>pubsub_state</tt> table. If a plugin stores its data in the same %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same
@ -646,19 +646,19 @@ get_entity_subscriptions(Host, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = case SubKey of States = case SubKey of
GenKey -> mnesia:match_object( GenKey -> mnesia:match_object(
#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); #pubsub_state{id = {{U, D, '_'}, '_'}, _ = '_'});
_ -> mnesia:match_object( _ -> mnesia:match_object(
#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) #pubsub_state{id = {GenKey, '_'}, _ = '_'})
++ mnesia:match_object( ++ mnesia:match_object(
#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) #pubsub_state{id = {SubKey, '_'}, _ = '_'})
end, end,
NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of
[{nodetree, N}] -> N; [{nodetree, N}] -> N;
_ -> nodetree_tree _ -> nodetree_tree
end, end,
Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> Reply = lists:foldl(fun(#pubsub_state{id = {J, N}, subscriptions = Ss}, Acc) ->
case NodeTree:get_node(N) of case NodeTree:get_node(N) of
#pubsub_node{nodeid = {Host, _}} = Node -> #pubsub_node{id = {Host, _}} = Node ->
lists:foldl(fun({Sub, SubId}, Acc2) -> lists:foldl(fun({Sub, SubId}, Acc2) ->
[{Node, Sub, SubId, J} | Acc2]; [{Node, Sub, SubId, J} | Acc2];
(S, Acc2) -> (S, Acc2) ->
@ -671,7 +671,7 @@ get_entity_subscriptions(Host, Owner) ->
get_node_subscriptions(NodeId) -> get_node_subscriptions(NodeId) ->
{result, States} = get_states(NodeId), {result, States} = get_states(NodeId),
Tr = fun(#pubsub_state{stateid = {J, _}, subscriptions = Subscriptions}) -> Tr = fun(#pubsub_state{id = {J, _}, subscriptions = Subscriptions}) ->
%% TODO: get rid of cases to handle non-list subscriptions %% TODO: get rid of cases to handle non-list subscriptions
case Subscriptions of case Subscriptions of
[_|_] -> [_|_] ->
@ -723,8 +723,8 @@ replace_subscription(NewSub, SubState) ->
replace_subscription(_, [], Acc) -> replace_subscription(_, [], Acc) ->
Acc; Acc;
replace_subscription({Sub, SubId}, [{_, SubID} | T], Acc) -> replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) ->
replace_subscription({Sub, SubId}, T, [{Sub, SubID} | Acc]). replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]).
new_subscription(NodeId, Owner, Subscription, SubState) -> new_subscription(NodeId, Owner, Subscription, SubState) ->
SubId = pubsub_subscription:add_subscription(Owner, NodeId, []), SubId = pubsub_subscription:add_subscription(Owner, NodeId, []),
@ -733,34 +733,34 @@ new_subscription(NodeId, Owner, Subscription, SubState) ->
{Subscription, SubId}. {Subscription, SubId}.
unsub_with_subid(NodeId, SubId, SubState) -> unsub_with_subid(NodeId, SubId, SubState) ->
pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, pubsub_subscription:delete_subscription(SubState#pubsub_state.id,
NodeId, SubId), NodeId, SubId),
NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end, NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end,
SubState#pubsub_state.subscriptions), SubState#pubsub_state.subscriptions),
case {NewSubs, SubState#pubsub_state.affiliation} of case {NewSubs, SubState#pubsub_state.affiliation} of
{[], none} -> {[], none} ->
del_state(NodeId, element(1, SubState#pubsub_state.stateid)); del_state(NodeId, element(1, SubState#pubsub_state.id));
_ -> _ ->
set_state(SubState#pubsub_state{subscriptions = NewSubs}) set_state(SubState#pubsub_state{subscriptions = NewSubs})
end. end.
%% @spec (Host, Owner) -> {result, [Node]} | {error, Reason} %% @spec (Host, Owner) -> {result, [Node]} | {error, Reason}
%% Host = host() %% Host = host()
%% Owner = jid() %% Owner = jid()
%% Node = pubsubNode() %% Node = node()
%% @doc <p>Returns a list of Owner's nodes on Host with pending %% @doc <p>Returns a list of Owner's nodes on Host with pending
%% subscriptions.</p> %% subscriptions.</p>
get_pending_nodes(Host, Owner) -> get_pending_nodes(Host, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, States = mnesia:match_object(#pubsub_state{id = {GenKey, '_'},
affiliation = owner, affiliation = owner,
_ = '_'}), _ = '_'}),
NodeIDs = [ID || #pubsub_state{stateid = {_, ID}} <- States], Nidxs = [Nidx || #pubsub_state{id = {_, Nidx}} <- States],
NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of
[{nodetree, N}] -> N; [{nodetree, N}] -> N;
_ -> nodetree_tree _ -> nodetree_tree
end, end,
Reply = mnesia:foldl(fun(#pubsub_state{stateid = {_, NID}} = S, Acc) -> Reply = mnesia:foldl(fun(#pubsub_state{id = {_, Nidx}} = S, Acc) ->
case lists:member(NID, NodeIDs) of case lists:member(Nidx, Nidxs) of
true -> true ->
case get_nodes_helper(NodeTree, S) of case get_nodes_helper(NodeTree, S) of
{value, Node} -> [Node | Acc]; {value, Node} -> [Node | Acc];
@ -773,7 +773,7 @@ get_pending_nodes(Host, Owner) ->
{result, Reply}. {result, Reply}.
get_nodes_helper(NodeTree, get_nodes_helper(NodeTree,
#pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> #pubsub_state{id = {_, N}, subscriptions = Subs}) ->
HasPending = fun ({pending, _}) -> true; HasPending = fun ({pending, _}) -> true;
(pending) -> true; (pending) -> true;
(_) -> false (_) -> false
@ -781,7 +781,7 @@ get_nodes_helper(NodeTree,
case lists:any(HasPending, Subs) of case lists:any(HasPending, Subs) of
true -> true ->
case NodeTree:get_node(N) of case NodeTree:get_node(N) of
#pubsub_node{nodeid = {_, Node}} -> #pubsub_node{id = {_, Node}} ->
{value, Node}; {value, Node};
_ -> _ ->
false false
@ -791,7 +791,7 @@ get_nodes_helper(NodeTree,
end. end.
%% @spec (NodeId) -> {result, [State] | []} %% @spec (NodeId) -> {result, [State] | []}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% State = mod_pubsub:pubsubState() %% State = mod_pubsub:pubsubState()
%% @doc Returns the list of stored states for a given node. %% @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>For the default PubSub module, states are stored in Mnesia database.</p>
@ -805,26 +805,26 @@ get_nodes_helper(NodeTree,
%% node_default:get_states(NodeId).'''</p> %% node_default:get_states(NodeId).'''</p>
get_states(NodeId) -> get_states(NodeId) ->
States = case catch mnesia:match_object( States = case catch mnesia:match_object(
#pubsub_state{stateid = {'_', NodeId}, _ = '_'}) of #pubsub_state{id = {'_', NodeId}, _ = '_'}) of
List when is_list(List) -> List; List when is_list(List) -> List;
_ -> [] _ -> []
end, end,
{result, States}. {result, States}.
%% @spec (NodeId, JID) -> [State] | [] %% @spec (NodeId, JID) -> [State] | []
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% JID = mod_pubsub:jid() %% JID = ljid()
%% State = mod_pubsub:pubsubItems() %% State = mod_pubsub:pubsub_item()
%% @doc <p>Returns a state (one state list), given its reference.</p> %% @doc <p>Returns a state (one state list), given its reference.</p>
get_state(NodeId, JID) -> get_state(NodeId, JID) ->
StateId = {JID, NodeId}, StateId = {JID, NodeId},
case catch mnesia:read({pubsub_state, StateId}) of case catch mnesia:read({pubsub_state, StateId}) of
[State] when is_record(State, pubsub_state) -> State; [State] when is_record(State, pubsub_state) -> State;
_ -> #pubsub_state{stateid=StateId} _ -> #pubsub_state{id=StateId}
end. end.
%% @spec (State) -> ok | {error, Reason::stanzaError()} %% @spec (State) -> ok | {error, Reason::stanzaError()}
%% State = mod_pubsub:pubsubStates() %% State = mod_pubsub:pubsub_state()
%% @doc <p>Write a state into database.</p> %% @doc <p>Write a state into database.</p>
set_state(State) when is_record(State, pubsub_state) -> set_state(State) when is_record(State, pubsub_state) ->
mnesia:write(State); mnesia:write(State);
@ -832,14 +832,14 @@ set_state(_) ->
{error, 'internal-server-error'}. {error, 'internal-server-error'}.
%% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()} %% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% @doc <p>Delete a state from database.</p> %% @doc <p>Delete a state from database.</p>
del_state(NodeId, JID) -> del_state(NodeId, JID) ->
mnesia:delete({pubsub_state, {JID, NodeId}}). mnesia:delete({pubsub_state, {JID, NodeId}}).
%% @spec (NodeId, From) -> [Items] | [] %% @spec (NodeId, From) -> [Items] | []
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Items = mod_pubsub:pubsubItems() %% Items = mod_pubsub:pubsub_item()
%% @doc Returns the list of stored items for a given node. %% @doc Returns the list of stored items for a given node.
%% <p>For the default PubSub module, items are stored in Mnesia database.</p> %% <p>For the default PubSub module, items are stored in Mnesia database.</p>
%% <p>We can consider that the pubsub_item table have been created by the main %% <p>We can consider that the pubsub_item table have been created by the main
@ -851,7 +851,7 @@ del_state(NodeId, JID) ->
%% ```get_items(NodeId, From) -> %% ```get_items(NodeId, From) ->
%% node_default:get_items(NodeId, From).'''</p> %% node_default:get_items(NodeId, From).'''</p>
get_items(NodeId, _From) -> get_items(NodeId, _From) ->
Items = mnesia:match_object(#pubsub_item{itemid = {'_', NodeId}, _ = '_'}), Items = mnesia:match_object(#pubsub_item{id = {'_', NodeId}, _ = '_'}),
{result, lists:reverse(lists:keysort(#pubsub_item.modification, Items))}. {result, lists:reverse(lists:keysort(#pubsub_item.modification, Items))}.
get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) ->
SubKey = jlib:short_prepd_jid(JID), SubKey = jlib:short_prepd_jid(JID),
@ -891,9 +891,9 @@ get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -
end. end.
%% @spec (NodeId, ItemId) -> [Item] | [] %% @spec (NodeId, ItemId) -> [Item] | []
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% ItemId = string() %% ItemId = item()
%% Item = mod_pubsub:pubsubItems() %% Item = mod_pubsub:pubsub_item()
%% @doc <p>Returns an item (one item list), given its reference.</p> %% @doc <p>Returns an item (one item list), given its reference.</p>
get_item(NodeId, ItemId) -> get_item(NodeId, ItemId) ->
case mnesia:read({pubsub_item, {ItemId, NodeId}}) of case mnesia:read({pubsub_item, {ItemId, NodeId}}) of
@ -912,7 +912,7 @@ get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _S
%%SubId == "", ?? -> %%SubId == "", ?? ->
%% Entity has multiple subscriptions to the node but does not specify a subscription ID %% Entity has multiple subscriptions to the node but does not specify a subscription ID
%{error, ?ERR_EXTENDED('bad-request', "subid-required")}; %{error, ?ERR_EXTENDED('bad-request', "subid-required")};
%%InvalidSubID -> %%InvalidSubId ->
%% Entity is subscribed but specifies an invalid subscription ID %% Entity is subscribed but specifies an invalid subscription ID
%{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")};
Affiliation == outcast -> Affiliation == outcast ->
@ -938,7 +938,7 @@ get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _S
end. end.
%% @spec (Item) -> ok | {error, Reason::stanzaError()} %% @spec (Item) -> ok | {error, Reason::stanzaError()}
%% Item = mod_pubsub:pubsubItems() %% Item = mod_pubsub:pubsub_item()
%% @doc <p>Write an item into database.</p> %% @doc <p>Write an item into database.</p>
set_item(Item) when is_record(Item, pubsub_item) -> set_item(Item) when is_record(Item, pubsub_item) ->
mnesia:write(Item); mnesia:write(Item);
@ -946,8 +946,8 @@ set_item(_) ->
{error, 'internal-server-error'}. {error, 'internal-server-error'}.
%% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()} %% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% ItemId = string() %% ItemId = item()
%% @doc <p>Delete an item from database.</p> %% @doc <p>Delete an item from database.</p>
del_item(NodeId, ItemId) -> del_item(NodeId, ItemId) ->
mnesia:delete({pubsub_item, {ItemId, NodeId}}). mnesia:delete({pubsub_item, {ItemId, NodeId}}).

View File

@ -37,7 +37,7 @@
%%% development is still a work in progress. However, the system is already %%% development is still a work in progress. However, the system is already
%%% useable and useful as is. Please, send us comments, feedback and %%% useable and useful as is. Please, send us comments, feedback and
%%% improvements.</p> %%% improvements.</p>
%%TODO : fix SQL requests with nodeid/id and id/idx changes
-module(node_flat_odbc). -module(node_flat_odbc).
-author('christophe.romain@process-one.net'). -author('christophe.romain@process-one.net').
@ -191,9 +191,9 @@ features() ->
%% @spec (Host, ServerHost, Node, ParentNode, Owner, Access) -> bool() %% @spec (Host, ServerHost, Node, ParentNode, Owner, Access) -> bool()
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% ServerHost = mod_pubsub:host() %% ServerHost = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:node()
%% ParentNode = mod_pubsub:pubsubNode() %% ParentNode = mod_pubsub:node()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% Access = all | atom() %% Access = all | atom()
%% @doc Checks if the current user has the permission to create the requested node %% @doc Checks if the current user has the permission to create the requested node
%% <p>In {@link node_default}, the permission is decided by the place in the %% <p>In {@link node_default}, the permission is decided by the place in the
@ -212,34 +212,27 @@ create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
%% @spec (NodeId, Owner) -> %% @spec (NodeId, Owner) ->
%% {result, Result} | exit %% {result, Result} | exit
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% @doc <p></p> %% @doc <p></p>
create_node(NodeId, Owner) -> create_node(NodeId, Owner) ->
OwnerKey = jlib:short_prepd_bare_jid(Owner), OwnerKey = jlib:short_prepd_bare_jid(Owner),
State = #pubsub_state{stateid = {OwnerKey, NodeId}, affiliation = owner}, State = #pubsub_state{id = {OwnerKey, NodeId}, affiliation = owner},
catch ejabberd_odbc:sql_query_t( catch ejabberd_odbc:sql_query_t(
["insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " ["insert into pubsub_state(nodeid, jid, affiliation, subscriptions) "
"values(", state_to_raw(NodeId, State), ");"]), "values(", state_to_raw(NodeId, State), ");"]),
{result, {default, broadcast}}. {result, {default, broadcast}}.
%% @spec (Removed) -> ok %% @spec (Removed) -> ok
%% Removed = [mod_pubsub:pubsubNode()] %% Removed = [mod_pubsub:node()]
%% @doc <p>purge items of deleted nodes after effective deletion.</p> %% @doc <p>purge items of deleted nodes after effective deletion.</p>
delete_node(Removed) -> delete_node(Removed) ->
%% pablo: TODO, this is present on trunk/node_flat but not on trunk/node_flat_odbc.
%% check what is the desired behaviour
%% Tr = fun(#pubsub_state{stateid = {J, _}, subscriptions = Ss}) ->
%% lists:map(fun(S) ->
%% {J, S}
%% end, Ss)
%% end,
Reply = lists:map( Reply = lists:map(
fun(#pubsub_node{id = NodeId} = PubsubNode) -> fun(#pubsub_node{idx = Nidx} = PubsubNode) ->
Subscriptions = case catch ejabberd_odbc:sql_query_t( Subscriptions = case catch ejabberd_odbc:sql_query_t(
["select jid, subscriptions " ["select jid, subscriptions "
"from pubsub_state " "from pubsub_state "
"where nodeid='", NodeId, ";"]) of "where nodeid='", Nidx, ";"]) of
{selected, ["jid", "subscriptions"], RItems} -> {selected, ["jid", "subscriptions"], RItems} ->
lists:map(fun({SJID, Subscriptions}) -> lists:map(fun({SJID, Subscriptions}) ->
{decode_jid(SJID), decode_subscriptions(Subscriptions)} {decode_jid(SJID), decode_subscriptions(Subscriptions)}
@ -345,9 +338,9 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel,
%% @spec (NodeId, Sender, Subscriber, SubId) -> %% @spec (NodeId, Sender, Subscriber, SubId) ->
%% {error, Reason} | {result, []} %% {error, Reason} | {result, []}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Sender = mod_pubsub:jid() %% Sender = ljid()
%% Subscriber = mod_pubsub:jid() %% Subscriber = ljid()
%% SubId = mod_pubsub:subid() %% SubId = mod_pubsub:subid()
%% Reason = mod_pubsub:stanzaError() %% Reason = mod_pubsub:stanzaError()
%% @doc <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p> %% @doc <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p>
@ -417,11 +410,11 @@ delete_subscription(SubKey, NodeId, {Subscription, SubId}, Affiliation, Subscrip
%% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
%% {true, PubsubItem} | {result, Reply} %% {true, PubsubItem} | {result, Reply}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Publisher = mod_pubsub:jid() %% Publisher = ljid()
%% PublishModel = atom() %% PublishModel = atom()
%% MaxItems = integer() %% MaxItems = integer()
%% ItemId = string() %% ItemId = item()
%% Payload = term() %% Payload = term()
%% @doc <p>Publishes the item passed as parameter.</p> %% @doc <p>Publishes the item passed as parameter.</p>
%% <p>The mechanism works as follow: %% <p>The mechanism works as follow:
@ -474,7 +467,7 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
%% Note: this works cause set_item tries an update before %% Note: this works cause set_item tries an update before
%% the insert, and the update just ignore creation field. %% the insert, and the update just ignore creation field.
PubId = {now(), SubKey}, PubId = {now(), SubKey},
set_item(#pubsub_item{itemid = {ItemId, NodeId}, set_item(#pubsub_item{id = {ItemId, NodeId},
creation = {now(), GenKey}, creation = {now(), GenKey},
modification = PubId, modification = PubId,
payload = Payload}), payload = Payload}),
@ -488,10 +481,10 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
end. end.
%% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} %% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% MaxItems = integer() | unlimited %% MaxItems = integer() | unlimited
%% ItemIds = [ItemId::string()] %% ItemIds = [item()]
%% NewItemIds = [ItemId::string()] %% NewItemIds = [item()]
%% @doc <p>This function is used to remove extra items, most notably when the %% @doc <p>This function is used to remove extra items, most notably when the
%% maximum number of items has been reached.</p> %% maximum number of items has been reached.</p>
%% <p>This function is used internally by the core PubSub module, as no %% <p>This function is used internally by the core PubSub module, as no
@ -515,10 +508,10 @@ remove_extra_items(NodeId, MaxItems, ItemIds) ->
%% @spec (NodeId, Publisher, PublishModel, ItemId) -> %% @spec (NodeId, Publisher, PublishModel, ItemId) ->
%% {error, Reason::stanzaError()} | %% {error, Reason::stanzaError()} |
%% {result, []} %% {result, []}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Publisher = mod_pubsub:jid() %% Publisher = ljid()
%% PublishModel = atom() %% PublishModel = atom()
%% ItemId = string() %% ItemId = item()
%% @doc <p>Triggers item deletion.</p> %% @doc <p>Triggers item deletion.</p>
%% <p>Default plugin: The user performing the deletion must be the node owner %% <p>Default plugin: The user performing the deletion must be the node owner
%% or a publisher, or PublishModel being open.</p> %% or a publisher, or PublishModel being open.</p>
@ -549,8 +542,8 @@ delete_item(NodeId, Publisher, PublishModel, ItemId) ->
%% @spec (NodeId, Owner) -> %% @spec (NodeId, Owner) ->
%% {error, Reason::stanzaError()} | %% {error, Reason::stanzaError()} |
%% {result, {default, broadcast}} %% {result, {default, broadcast}}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
purge_node(NodeId, Owner) -> purge_node(NodeId, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
GenState = get_state(NodeId, GenKey), GenState = get_state(NodeId, GenKey),
@ -569,7 +562,7 @@ purge_node(NodeId, Owner) ->
%% @spec (Host, JID) -> [{Node,Affiliation}] %% @spec (Host, JID) -> [{Node,Affiliation}]
%% Host = host() %% Host = host()
%% JID = mod_pubsub:jid() %% JID = ljid()
%% @doc <p>Return the current affiliations for the given user</p> %% @doc <p>Return the current affiliations for the given user</p>
%% <p>The default module reads affiliations in the main Mnesia %% <p>The default module reads affiliations in the main Mnesia
%% <tt>pubsub_state</tt> table. If a plugin stores its data in the same %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same
@ -632,7 +625,7 @@ set_affiliation(NodeId, Owner, Affiliation) when ?IS_JID(Owner)->
%% @spec (Host, Owner) -> [{Node,Subscription}] %% @spec (Host, Owner) -> [{Node,Subscription}]
%% Host = host() %% Host = host()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% @doc <p>Return the current subscriptions for the given user</p> %% @doc <p>Return the current subscriptions for the given user</p>
%% <p>The default module reads subscriptions in the main Mnesia %% <p>The default module reads subscriptions in the main Mnesia
%% <tt>pubsub_state</tt> table. If a plugin stores its data in the same %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same
@ -664,13 +657,13 @@ get_entity_subscriptions(Host, Owner) ->
{selected, ["node", "type", "nodeid", "jid", "subscriptions"], RItems} -> {selected, ["node", "type", "nodeid", "jid", "subscriptions"], RItems} ->
lists:foldl(fun({N, T, I, J, S}, Acc) -> lists:foldl(fun({N, T, I, J, S}, Acc) ->
Node = nodetree_tree_odbc:raw_to_node(Host, {N, "", T, I}), Node = nodetree_tree_odbc:raw_to_node(Host, {N, "", T, I}),
Jid = decode_jid(J), JID = decode_jid(J),
case decode_subscriptions(S) of case decode_subscriptions(S) of
[] -> [] ->
[{Node, none, Jid}|Acc]; [{Node, none, JID}|Acc];
Subs -> Subs ->
lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, Jid}|Acc2]; lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, JID}|Acc2];
(Sub, Acc2) -> [{Node, Sub, Jid}|Acc2] (Sub, Acc2) -> [{Node, Sub, JID}|Acc2]
end, Acc, Subs) end, Acc, Subs)
end end
end, [], RItems); end, [], RItems);
@ -707,13 +700,13 @@ get_entity_subscriptions_for_send_last(Host, Owner) ->
{selected, ["node", "type", "nodeid", "jid", "subscriptions"], RItems} -> {selected, ["node", "type", "nodeid", "jid", "subscriptions"], RItems} ->
lists:foldl(fun({N, T, I, J, S}, Acc) -> lists:foldl(fun({N, T, I, J, S}, Acc) ->
Node = nodetree_tree_odbc:raw_to_node(Host, {N, "", T, I}), Node = nodetree_tree_odbc:raw_to_node(Host, {N, "", T, I}),
Jid = decode_jid(J), JID = decode_jid(J),
case decode_subscriptions(S) of case decode_subscriptions(S) of
[] -> [] ->
[{Node, none, Jid}|Acc]; [{Node, none, JID}|Acc];
Subs -> Subs ->
lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, Jid}|Acc2]; lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, JID}|Acc2];
(Sub, Acc2) -> [{Node, Sub, Jid}|Acc2] (Sub, Acc2) -> [{Node, Sub, JID}|Acc2]
end, Acc, Subs) end, Acc, Subs)
end end
end, [], RItems); end, [], RItems);
@ -729,13 +722,13 @@ get_node_subscriptions(NodeId) ->
"where nodeid='", NodeId, "';"]) of "where nodeid='", NodeId, "';"]) of
{selected, ["jid", "subscriptions"], RItems} -> {selected, ["jid", "subscriptions"], RItems} ->
lists:foldl(fun({J, S}, Acc) -> lists:foldl(fun({J, S}, Acc) ->
Jid = decode_jid(J), JID = decode_jid(J),
case decode_subscriptions(S) of case decode_subscriptions(S) of
[] -> [] ->
[{Jid, none}|Acc]; [{JID, none}|Acc];
Subs -> Subs ->
lists:foldl(fun({Sub, SubId}, Acc2) -> [{Jid, Sub, SubId}|Acc2]; lists:foldl(fun({Sub, SubId}, Acc2) -> [{JID, Sub, SubId}|Acc2];
(Sub, Acc2) -> [{Jid, Sub}|Acc2] (Sub, Acc2) -> [{JID, Sub}|Acc2]
end, Acc, Subs) end, Acc, Subs)
end end
end, [], RItems); end, [], RItems);
@ -786,8 +779,8 @@ replace_subscription(NewSub, SubState) ->
replace_subscription(_, [], Acc) -> replace_subscription(_, [], Acc) ->
Acc; Acc;
replace_subscription({Sub, SubId}, [{_, SubID} | T], Acc) -> replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) ->
replace_subscription({Sub, SubId}, T, [{Sub, SubID} | Acc]). replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]).
new_subscription(NodeId, Owner, Subscription, SubState) -> new_subscription(NodeId, Owner, Subscription, SubState) ->
case pubsub_subscription_odbc:subscribe_node(Owner, NodeId, []) of case pubsub_subscription_odbc:subscribe_node(Owner, NodeId, []) of
@ -800,13 +793,13 @@ new_subscription(NodeId, Owner, Subscription, SubState) ->
end. end.
unsub_with_subid(NodeId, SubId, SubState) -> unsub_with_subid(NodeId, SubId, SubState) ->
pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.id,
NodeId, SubId), NodeId, SubId),
NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end, NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end,
SubState#pubsub_state.subscriptions), SubState#pubsub_state.subscriptions),
case {NewSubs, SubState#pubsub_state.affiliation} of case {NewSubs, SubState#pubsub_state.affiliation} of
{[], none} -> {[], none} ->
del_state(NodeId, element(1, SubState#pubsub_state.stateid)); del_state(NodeId, element(1, SubState#pubsub_state.id));
_ -> _ ->
set_state(SubState#pubsub_state{subscriptions = NewSubs}) set_state(SubState#pubsub_state{subscriptions = NewSubs})
end. end.
@ -814,21 +807,21 @@ unsub_with_subid(NodeId, SubId, SubState) ->
%% @spec (Host, Owner) -> {result, [Node]} | {error, Reason} %% @spec (Host, Owner) -> {result, [Node]} | {error, Reason}
%% Host = host() %% Host = host()
%% Owner = jid() %% Owner = jid()
%% Node = pubsubNode() %% Node = node()
%% @doc <p>Returns a list of Owner's nodes on Host with pending %% @doc <p>Returns a list of Owner's nodes on Host with pending
%% subscriptions.</p> %% subscriptions.</p>
get_pending_nodes(Host, Owner) -> get_pending_nodes(Host, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, States = mnesia:match_object(#pubsub_state{id = {GenKey, '_'},
affiliation = owner, affiliation = owner,
_ = '_'}), _ = '_'}),
NodeIDs = [ID || #pubsub_state{stateid = {_, ID}} <- States], Nidxs = [Nidx || #pubsub_state{id = {_, Nidx}} <- States],
NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of
[{nodetree, N}] -> N; [{nodetree, N}] -> N;
_ -> nodetree_tree_odbc _ -> nodetree_tree_odbc
end, end,
Reply = mnesia:foldl(fun(#pubsub_state{stateid = {_, NID}} = S, Acc) -> Reply = mnesia:foldl(fun(#pubsub_state{id = {_, Nidx}} = S, Acc) ->
case lists:member(NID, NodeIDs) of case lists:member(Nidx, Nidxs) of
true -> true ->
case get_nodes_helper(NodeTree, S) of case get_nodes_helper(NodeTree, S) of
{value, Node} -> [Node | Acc]; {value, Node} -> [Node | Acc];
@ -841,7 +834,7 @@ get_pending_nodes(Host, Owner) ->
{result, Reply}. {result, Reply}.
get_nodes_helper(NodeTree, get_nodes_helper(NodeTree,
#pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> #pubsub_state{id = {_, N}, subscriptions = Subs}) ->
HasPending = fun ({pending, _}) -> true; HasPending = fun ({pending, _}) -> true;
(pending) -> true; (pending) -> true;
(_) -> false (_) -> false
@ -849,7 +842,7 @@ get_nodes_helper(NodeTree,
case lists:any(HasPending, Subs) of case lists:any(HasPending, Subs) of
true -> true ->
case NodeTree:get_node(N) of case NodeTree:get_node(N) of
#pubsub_node{nodeid = {_, Node}} -> #pubsub_node{id = {_, Node}} ->
{value, Node}; {value, Node};
_ -> _ ->
false false
@ -859,7 +852,7 @@ get_nodes_helper(NodeTree,
end. end.
%% @spec (NodeId) -> {result, [State] | []} %% @spec (NodeId) -> {result, [State] | []}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% State = mod_pubsub:pubsubState() %% State = mod_pubsub:pubsubState()
%% @doc Returns the list of stored states for a given node. %% @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>For the default PubSub module, states are stored in Mnesia database.</p>
@ -878,7 +871,7 @@ get_states(NodeId) ->
"where nodeid='", NodeId, "';"]) of "where nodeid='", NodeId, "';"]) of
{selected, ["jid", "affiliation", "subscriptions"], RItems} -> {selected, ["jid", "affiliation", "subscriptions"], RItems} ->
{result, lists:map(fun({SJID, Affiliation, Subscriptions}) -> {result, lists:map(fun({SJID, Affiliation, Subscriptions}) ->
#pubsub_state{stateid = {decode_jid(SJID), NodeId}, #pubsub_state{id = {decode_jid(SJID), NodeId},
items = itemids(NodeId, SJID), items = itemids(NodeId, SJID),
affiliation = decode_affiliation(Affiliation), affiliation = decode_affiliation(Affiliation),
subscriptions = decode_subscriptions(Subscriptions)} subscriptions = decode_subscriptions(Subscriptions)}
@ -889,13 +882,13 @@ get_states(NodeId) ->
%% @spec (NodeId, JID) -> [State] | [] %% @spec (NodeId, JID) -> [State] | []
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% JID = mod_pubsub:jid() %% JID = ljid()
%% State = mod_pubsub:pubsubItems() %% State = mod_pubsub:pubsub_state()
%% @doc <p>Returns a state (one state list), given its reference.</p> %% @doc <p>Returns a state (one state list), given its reference.</p>
get_state(NodeId, JID) -> get_state(NodeId, JID) ->
State = get_state_without_itemids(NodeId, JID), State = get_state_without_itemids(NodeId, JID),
{SJID, _} = State#pubsub_state.stateid, {SJID, _} = State#pubsub_state.id,
State#pubsub_state{items = itemids(NodeId, SJID)}. State#pubsub_state{items = itemids(NodeId, SJID)}.
get_state_without_itemids(NodeId, JID) -> get_state_without_itemids(NodeId, JID) ->
J = encode_jid(JID), J = encode_jid(JID),
@ -905,25 +898,25 @@ get_state_without_itemids(NodeId, JID) ->
"where jid='", J, "' " "where jid='", J, "' "
"and nodeid='", NodeId, "';"]) of "and nodeid='", NodeId, "';"]) of
{selected, ["jid", "affiliation", "subscriptions"], [{SJID, Affiliation, Subscriptions}]} -> {selected, ["jid", "affiliation", "subscriptions"], [{SJID, Affiliation, Subscriptions}]} ->
#pubsub_state{stateid = {decode_jid(SJID), NodeId}, #pubsub_state{id = {decode_jid(SJID), NodeId},
affiliation = decode_affiliation(Affiliation), affiliation = decode_affiliation(Affiliation),
subscriptions = decode_subscriptions(Subscriptions)}; subscriptions = decode_subscriptions(Subscriptions)};
_ -> _ ->
#pubsub_state{stateid={JID, NodeId}} #pubsub_state{id={JID, NodeId}}
end. end.
%% @spec (State) -> ok | {error, Reason::stanzaError()} %% @spec (State) -> ok | {error, Reason::stanzaError()}
%% State = mod_pubsub:pubsubStates() %% State = mod_pubsub:pubsubStates()
%% @doc <p>Write a state into database.</p> %% @doc <p>Write a state into database.</p>
set_state(State) when is_record(State, pubsub_state) -> set_state(State) when is_record(State, pubsub_state) ->
{_, NodeId} = State#pubsub_state.stateid, {_, NodeId} = State#pubsub_state.id,
set_state(NodeId, State). set_state(NodeId, State).
set_state(NodeId, State) -> set_state(NodeId, State) ->
%% NOTE: in odbc version, as we do not handle item list, %% NOTE: in odbc version, as we do not handle item list,
%% we just need to update affiliation and subscription %% we just need to update affiliation and subscription
%% cause {JID,NodeId} is the key. if it does not exists, then we insert it. %% cause {JID,NodeId} is the key. if it does not exists, then we insert it.
%% MySQL can be optimized using INSERT ... ON DUPLICATE KEY as well %% MySQL can be optimized using INSERT ... ON DUPLICATE KEY as well
{JID, _} = State#pubsub_state.stateid, {JID, _} = State#pubsub_state.id,
J = encode_jid(JID), J = encode_jid(JID),
S = encode_subscriptions(State#pubsub_state.subscriptions), S = encode_subscriptions(State#pubsub_state.subscriptions),
A = encode_affiliation(State#pubsub_state.affiliation), A = encode_affiliation(State#pubsub_state.affiliation),
@ -941,7 +934,7 @@ set_state(NodeId, State) ->
{result, []}. {result, []}.
%% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()} %% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% @doc <p>Delete a state from database.</p> %% @doc <p>Delete a state from database.</p>
del_state(NodeId, JID) -> del_state(NodeId, JID) ->
J = encode_jid(JID), J = encode_jid(JID),
@ -952,8 +945,8 @@ del_state(NodeId, JID) ->
ok. ok.
%% @spec (NodeId, From) -> {[Items], RsmOut} | [] %% @spec (NodeId, From) -> {[Items], RsmOut} | []
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% Items = mod_pubsub:pubsubItems() %% Items = mod_pubsub:pubsub_item()
%% @doc Returns the list of stored items for a given node. %% @doc Returns the list of stored items for a given node.
%% <p>For the default PubSub module, items are stored in Mnesia database.</p> %% <p>For the default PubSub module, items are stored in Mnesia database.</p>
%% <p>We can consider that the pubsub_item table have been created by the main %% <p>We can consider that the pubsub_item table have been created by the main
@ -1100,9 +1093,9 @@ get_last_items(NodeId, _From, Count) ->
end. end.
%% @spec (NodeId, ItemId) -> [Item] | [] %% @spec (NodeId, ItemId) -> [Item] | []
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% ItemId = string() %% ItemId = item()
%% Item = mod_pubsub:pubsubItems() %% Item = mod_pubsub:pubsub_item()
%% @doc <p>Returns an item (one item list), given its reference.</p> %% @doc <p>Returns an item (one item list), given its reference.</p>
get_item(NodeId, ItemId) -> get_item(NodeId, ItemId) ->
I = ?PUBSUB:escape(ItemId), I = ?PUBSUB:escape(ItemId),
@ -1126,7 +1119,7 @@ get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _S
%%SubId == "", ?? -> %%SubId == "", ?? ->
%% Entity has multiple subscriptions to the node but does not specify a subscription ID %% Entity has multiple subscriptions to the node but does not specify a subscription ID
%{error, ?ERR_EXTENDED('bad-request', "subid-required")}; %{error, ?ERR_EXTENDED('bad-request', "subid-required")};
%%InvalidSubID -> %%InvalidSubId ->
%% Entity is subscribed but specifies an invalid subscription ID %% Entity is subscribed but specifies an invalid subscription ID
%{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")};
Affiliation == outcast -> Affiliation == outcast ->
@ -1152,10 +1145,10 @@ get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _S
end. end.
%% @spec (Item) -> ok | {error, Reason::stanzaError()} %% @spec (Item) -> ok | {error, Reason::stanzaError()}
%% Item = mod_pubsub:pubsubItems() %% Item = mod_pubsub:pubsub_item()
%% @doc <p>Write an item into database.</p> %% @doc <p>Write an item into database.</p>
set_item(Item) -> set_item(Item) ->
{ItemId, NodeId} = Item#pubsub_item.itemid, {ItemId, NodeId} = Item#pubsub_item.id,
I = ?PUBSUB:escape(ItemId), I = ?PUBSUB:escape(ItemId),
{C, _} = Item#pubsub_item.creation, {C, _} = Item#pubsub_item.creation,
{M, JID} = Item#pubsub_item.modification, {M, JID} = Item#pubsub_item.modification,
@ -1182,8 +1175,8 @@ set_item(Item) ->
{result, []}. {result, []}.
%% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()} %% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()}
%% NodeId = mod_pubsub:pubsubNodeId() %% NodeId = nodeidx()
%% ItemId = string() %% ItemId = item()
%% @doc <p>Delete an item from database.</p> %% @doc <p>Delete an item from database.</p>
del_item(NodeId, ItemId) -> del_item(NodeId, ItemId) ->
I = ?PUBSUB:escape(ItemId), I = ?PUBSUB:escape(ItemId),
@ -1337,7 +1330,7 @@ encode_subscriptions(Subscriptions) ->
%%% record getter/setter %%% record getter/setter
state_to_raw(NodeId, State) -> state_to_raw(NodeId, State) ->
{JID, _} = State#pubsub_state.stateid, {JID, _} = State#pubsub_state.id,
J = encode_jid(JID), J = encode_jid(JID),
A = encode_affiliation(State#pubsub_state.affiliation), A = encode_affiliation(State#pubsub_state.affiliation),
S = encode_subscriptions(State#pubsub_state.subscriptions), S = encode_subscriptions(State#pubsub_state.subscriptions),
@ -1353,7 +1346,7 @@ raw_to_item(NodeId, {ItemId, SJID, Creation, Modification, XML}) ->
{error, _Reason} -> []; {error, _Reason} -> [];
[El] -> [El] [El] -> [El]
end, end,
#pubsub_item{itemid = {ItemId, NodeId}, #pubsub_item{id = {ItemId, NodeId},
creation={ToTime(Creation), JID}, creation={ToTime(Creation), JID},
modification={ToTime(Modification), JID}, modification={ToTime(Modification), JID},
payload = Payload}. payload = Payload}.

View File

@ -140,8 +140,8 @@ delete_node(Removed) ->
subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) ->
node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -111,8 +111,8 @@ delete_node(Removed) ->
subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) ->
node_flat_odbc:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). node_flat_odbc:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat_odbc:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat_odbc:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -137,8 +137,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel,
NodeId, Sender, Subscriber, AccessModel, SendLast, NodeId, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup, Options). PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_pep:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_pep:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_pep:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_pep:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -156,8 +156,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel,
NodeId, Sender, Subscriber, AccessModel, SendLast, NodeId, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup, Options). PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
case node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID) of case node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{result, _} -> {result, []} {result, _} -> {result, []}
end. end.
@ -177,14 +177,14 @@ purge_node(NodeId, Owner) ->
get_entity_affiliations(_Host, Owner) -> get_entity_affiliations(_Host, Owner) ->
{_, D, _} = jlib:short_prepd_jid(Owner), {_, D, _} = jlib:short_prepd_jid(Owner),
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), States = mnesia:match_object(#pubsub_state{id = {GenKey, '_'}, _ = '_'}),
NodeTree = case catch ets:lookup(gen_mod:get_module_proc(D, config), nodetree) of NodeTree = case catch ets:lookup(gen_mod:get_module_proc(D, config), nodetree) of
[{nodetree, N}] -> N; [{nodetree, N}] -> N;
_ -> nodetree_tree _ -> nodetree_tree
end, end,
Reply = lists:foldl(fun(#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> Reply = lists:foldl(fun(#pubsub_state{id = {_, N}, affiliation = A}, Acc) ->
case NodeTree:get_node(N) of case NodeTree:get_node(N) of
#pubsub_node{nodeid = {{_, D, _}, _}} = Node -> [{Node, A}|Acc]; #pubsub_node{id = {{_, D, _}, _}} = Node -> [{Node, A}|Acc];
_ -> Acc _ -> Acc
end end
end, [], States), end, [], States),
@ -204,22 +204,22 @@ get_entity_subscriptions(_Host, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = case SubKey of States = case SubKey of
GenKey -> mnesia:match_object( GenKey -> mnesia:match_object(
#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); #pubsub_state{id = {{U, D, '_'}, '_'}, _ = '_'});
_ -> mnesia:match_object( _ -> mnesia:match_object(
#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) #pubsub_state{id = {GenKey, '_'}, _ = '_'})
++ mnesia:match_object( ++ mnesia:match_object(
#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) #pubsub_state{id = {SubKey, '_'}, _ = '_'})
end, end,
NodeTree = case catch ets:lookup(gen_mod:get_module_proc(D, config), nodetree) of NodeTree = case catch ets:lookup(gen_mod:get_module_proc(D, config), nodetree) of
[{nodetree, N}] -> N; [{nodetree, N}] -> N;
_ -> nodetree_tree _ -> nodetree_tree
end, end,
Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> Reply = lists:foldl(fun(#pubsub_state{id = {J, N}, subscriptions = Ss}, Acc) ->
case NodeTree:get_node(N) of case NodeTree:get_node(N) of
#pubsub_node{nodeid = {{_, D, _}, _}} = Node -> #pubsub_node{id = {{_, D, _}, _}} = Node ->
lists:foldl(fun({subscribed, SubID}, Acc2) -> lists:foldl(fun({subscribed, SubId}, Acc2) ->
[{Node, subscribed, SubID, J} | Acc2]; [{Node, subscribed, SubId, J} | Acc2];
({pending, _SubID}, Acc2) -> ({pending, _SubId}, Acc2) ->
[{Node, pending, J} | Acc2]; [{Node, pending, J} | Acc2];
(S, Acc2) -> (S, Acc2) ->
[{Node, S, J} | Acc2] [{Node, S, J} | Acc2]

View File

@ -25,7 +25,7 @@
%%% @doc The module <strong>{@module}</strong> is the pep PubSub plugin. %%% @doc The module <strong>{@module}</strong> is the pep PubSub plugin.
%%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p> %%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p>
%%TODO : fix SQL requests with nodeid/id and id/idx changes
-module(node_pep_odbc). -module(node_pep_odbc).
-author('christophe.romain@process-one.net'). -author('christophe.romain@process-one.net').
@ -163,8 +163,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel,
NodeId, Sender, Subscriber, AccessModel, SendLast, NodeId, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup, Options). PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
case node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubID) of case node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubId) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{result, _} -> {result, []} {result, _} -> {result, []}
end. end.

View File

@ -133,8 +133,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast,
SendLast, PresenceSubscription, RosterGroup, SendLast, PresenceSubscription, RosterGroup,
Options). Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -130,8 +130,8 @@ delete_node(Removed) ->
subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) ->
node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options).
unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).

View File

@ -58,26 +58,26 @@ init(Host, ServerHost, Opts) ->
terminate(Host, ServerHost) -> terminate(Host, ServerHost) ->
nodetree_tree:terminate(Host, ServerHost). nodetree_tree:terminate(Host, ServerHost).
create_node(Key, NodeID, Type, Owner, Options, Parents) -> create_node(Key, Node, Type, Owner, Options, Parents) ->
OwnerJID = jlib:short_prepd_bare_jid(Owner), OwnerJID = jlib:short_prepd_bare_jid(Owner),
case find_node(Key, NodeID) of case find_node(Key, Node) of
false -> false ->
ID = pubsub_index:new(node), Nidx = pubsub_index:new(node),
N = #pubsub_node{nodeid = oid(Key, NodeID), N = #pubsub_node{id = oid(Key, Node),
id = ID, idx = Nidx,
type = Type, type = Type,
parents = Parents, parents = Parents,
owners = [OwnerJID], owners = [OwnerJID],
options = Options}, options = Options},
case set_node(N) of case set_node(N) of
ok -> {ok, ID}; ok -> {ok, Nidx};
Other -> Other Other -> Other
end; end;
_ -> _ ->
{error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'conflict')} {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'conflict')}
end. end.
set_node(#pubsub_node{nodeid = {Key, _}, set_node(#pubsub_node{id = {Key, _},
owners = Owners, owners = Owners,
options = Options} = Node) -> options = Options} = Node) ->
Parents = find_opt(collection, ?DEFAULT_PARENTS, Options), Parents = find_opt(collection, ?DEFAULT_PARENTS, Options),
@ -89,43 +89,43 @@ set_node(#pubsub_node{nodeid = {Key, _},
Other Other
end. end.
delete_node(Key, NodeID) -> delete_node(Key, Node) ->
case find_node(Key, NodeID) of case find_node(Key, Node) of
false -> false ->
{error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
Node -> Record ->
%% Find all of N's children, update their configs to %% Find all of N's children, update their configs to
%% remove N from the collection setting. %% remove N from the collection setting.
lists:foreach(fun (#pubsub_node{options = Opts} = Child) -> lists:foreach(fun (#pubsub_node{options = Opts} = Child) ->
NewOpts = remove_config_parent(NodeID, Opts), NewOpts = remove_config_parent(Node, Opts),
Parents = find_opt(collection, ?DEFAULT_PARENTS, NewOpts), Parents = find_opt(collection, ?DEFAULT_PARENTS, NewOpts),
ok = mnesia:write(pubsub_node, ok = mnesia:write(pubsub_node,
Child#pubsub_node{ Child#pubsub_node{
parents = Parents, parents = Parents,
options = NewOpts}, options = NewOpts},
write) write)
end, get_subnodes(Key, NodeID)), end, get_subnodes(Key, Node)),
%% Remove and return the requested node. %% Remove and return the requested node.
pubsub_index:free(node, Node#pubsub_node.id), pubsub_index:free(node, Record#pubsub_node.idx),
mnesia:delete_object(pubsub_node, Node, write), mnesia:delete_object(pubsub_node, Record, write),
[Node] [Record]
end. end.
options() -> options() ->
nodetree_tree:options(). nodetree_tree:options().
get_node(Host, NodeID, _From) -> get_node(Host, Node, _From) ->
get_node(Host, NodeID). get_node(Host, Node).
get_node(Host, NodeID) -> get_node(Host, Node) ->
case find_node(Host, NodeID) of case find_node(Host, Node) of
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
Node -> Node Record -> Record
end. end.
get_node(NodeId) -> get_node(Node) ->
nodetree_tree:get_node(NodeId). nodetree_tree:get_node(Node).
get_nodes(Key, From) -> get_nodes(Key, From) ->
nodetree_tree:get_nodes(Key, From). nodetree_tree:get_nodes(Key, From).
@ -133,49 +133,47 @@ get_nodes(Key, From) ->
get_nodes(Key) -> get_nodes(Key) ->
nodetree_tree:get_nodes(Key). nodetree_tree:get_nodes(Key).
get_parentnodes(Host, NodeID, _From) -> get_parentnodes(Host, Node, _From) ->
case find_node(Host, NodeID) of case find_node(Host, Node) of
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
#pubsub_node{parents = Parents} -> #pubsub_node{parents = Parents} ->
Q = qlc:q([N || #pubsub_node{nodeid = {NHost, NNode}} = N <- mnesia:table(pubsub_node), Q = qlc:q([N || #pubsub_node{id = {NHost, NNode}} = N <- mnesia:table(pubsub_node),
Parent <- Parents, Parent <- Parents,
Host == NHost, Host == NHost,
Parent == NNode]), Parent == NNode]),
qlc:e(Q) qlc:e(Q)
end. end.
get_parentnodes_tree(Host, NodeID, _From) -> get_parentnodes_tree(Host, Node, _From) ->
Pred = fun (NID, #pubsub_node{nodeid = {_, NNodeID}}) -> Pred = fun (Name, #pubsub_node{id = {_, NodeName}}) -> Name == NodeName end,
NID == NNodeID
end,
Tr = fun (#pubsub_node{parents = Parents}) -> Parents end, Tr = fun (#pubsub_node{parents = Parents}) -> Parents end,
traversal_helper(Pred, Tr, Host, [NodeID]). traversal_helper(Pred, Tr, Host, [Node]).
get_subnodes(Host, NodeID, _From) -> get_subnodes(Host, Node, _From) ->
get_subnodes(Host, NodeID). get_subnodes(Host, Node).
get_subnodes(Host, <<>>) -> get_subnodes(Host, <<>>) ->
get_subnodes_helper(Host, <<>>); get_subnodes_helper(Host, <<>>);
get_subnodes(Host, NodeID) -> get_subnodes(Host, Node) ->
case find_node(Host, NodeID) of case find_node(Host, Node) of
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
_ -> get_subnodes_helper(Host, NodeID) _ -> get_subnodes_helper(Host, Node)
end. end.
get_subnodes_helper(Host, NodeID) -> get_subnodes_helper(Host, Node) ->
Q = qlc:q([Node || #pubsub_node{nodeid = {NHost, _}, Q = qlc:q([Record || #pubsub_node{id = {NHost, _},
parents = Parents} = Node <- mnesia:table(pubsub_node), parents = Parents} = Record <- mnesia:table(pubsub_node),
Host == NHost, Host == NHost,
lists:member(NodeID, Parents)]), lists:member(Node, Parents)]),
qlc:e(Q). qlc:e(Q).
get_subnodes_tree(Host, NodeID, From) -> get_subnodes_tree(Host, Node, From) ->
Pred = fun (NID, #pubsub_node{parents = Parents}) -> Pred = fun (N, #pubsub_node{parents = Parents}) ->
lists:member(NID, Parents) lists:member(N, Parents)
end, end,
Tr = fun (#pubsub_node{nodeid = {_, N}}) -> [N] end, Tr = fun (#pubsub_node{id = {_, N}}) -> [N] end,
traversal_helper(Pred, Tr, 1, Host, [NodeID], traversal_helper(Pred, Tr, 1, Host, [Node],
[{0, [get_node(Host, NodeID, From)]}]). [{0, [get_node(Host, Node, From)]}]).
%%==================================================================== %%====================================================================
%% Internal functions %% Internal functions
@ -183,9 +181,9 @@ get_subnodes_tree(Host, NodeID, From) ->
oid(Key, Name) -> {Key, Name}. oid(Key, Name) -> {Key, Name}.
%% Key = jlib:jid() | host() %% Key = jlib:jid() | host()
%% NodeID = string() %% Node = string()
find_node(Key, NodeID) -> find_node(Key, Node) ->
case mnesia:read(pubsub_node, oid(Key, NodeID), read) of case mnesia:read(pubsub_node, oid(Key, Node), read) of
[] -> false; [] -> false;
[Node] -> Node [Node] -> Node
end. end.
@ -199,30 +197,30 @@ find_opt(Key, Default, Options) ->
_ -> Default _ -> Default
end. end.
traversal_helper(Pred, Tr, Host, NodeIDs) -> traversal_helper(Pred, Tr, Host, Nodes) ->
traversal_helper(Pred, Tr, 0, Host, NodeIDs, []). traversal_helper(Pred, Tr, 0, Host, Nodes, []).
traversal_helper(_Pred, _Tr, _Depth, _Host, [], Acc) -> traversal_helper(_Pred, _Tr, _Depth, _Host, [], Acc) ->
Acc; Acc;
traversal_helper(Pred, Tr, Depth, Host, NodeIDs, Acc) -> traversal_helper(Pred, Tr, Depth, Host, Nodes, Acc) ->
Q = qlc:q([Node || #pubsub_node{nodeid = {NHost, _}} = Node <- mnesia:table(pubsub_node), Q = qlc:q([Record || #pubsub_node{id = {NHost, _}} = Record <- mnesia:table(pubsub_node),
NodeID <- NodeIDs, Node <- Nodes,
Host == NHost, Host == NHost,
Pred(NodeID, Node)]), Pred(Node, Node)]),
Nodes = qlc:e(Q), Nodes = qlc:e(Q),
IDs = lists:flatmap(Tr, Nodes), Names = lists:flatmap(Tr, Nodes),
traversal_helper(Pred, Tr, Depth + 1, Host, IDs, [{Depth, Nodes} | Acc]). traversal_helper(Pred, Tr, Depth + 1, Host, Names, [{Depth, Nodes} | Acc]).
remove_config_parent(NodeID, Options) -> remove_config_parent(Node, Options) ->
remove_config_parent(NodeID, Options, []). remove_config_parent(Node, Options, []).
remove_config_parent(_NodeID, [], Acc) -> remove_config_parent(_Node, [], Acc) ->
lists:reverse(Acc); lists:reverse(Acc);
remove_config_parent(NodeID, [{collection, Parents} | T], Acc) -> remove_config_parent(Node, [{collection, Parents} | T], Acc) ->
remove_config_parent(NodeID, T, remove_config_parent(Node, T,
[{collection, lists:delete(NodeID, Parents)} | Acc]); [{collection, lists:delete(Node, Parents)} | Acc]);
remove_config_parent(NodeID, [H | T], Acc) -> remove_config_parent(Node, [H | T], Acc) ->
remove_config_parent(NodeID, T, [H | Acc]). remove_config_parent(Node, T, [H | Acc]).
validate_parentage(_Key, _Owners, []) -> validate_parentage(_Key, _Owners, []) ->
true; true;
@ -230,8 +228,8 @@ validate_parentage(Key, Owners, [[] | T]) ->
validate_parentage(Key, Owners, T); validate_parentage(Key, Owners, T);
validate_parentage(Key, Owners, [<<>> | T]) -> validate_parentage(Key, Owners, [<<>> | T]) ->
validate_parentage(Key, Owners, T); validate_parentage(Key, Owners, T);
validate_parentage(Key, Owners, [ParentID | T]) -> validate_parentage(Key, Owners, [ParentId | T]) ->
case find_node(Key, ParentID) of case find_node(Key, ParentId) of
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item_not_found')}; false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item_not_found')};
#pubsub_node{owners = POwners, options = POptions} -> #pubsub_node{owners = POwners, options = POptions} ->
NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions), NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions),

View File

@ -78,7 +78,7 @@ init(_Host, _ServerHost, _Opts) ->
mnesia:create_table(pubsub_node, mnesia:create_table(pubsub_node,
[{disc_copies, [node()]}, [{disc_copies, [node()]},
{attributes, record_info(fields, pubsub_node)}]), {attributes, record_info(fields, pubsub_node)}]),
mnesia:add_table_index(pubsub_node, id), mnesia:add_table_index(pubsub_node, idx),
NodesFields = record_info(fields, pubsub_node), NodesFields = record_info(fields, pubsub_node),
case mnesia:table_info(pubsub_node, attributes) of case mnesia:table_info(pubsub_node, attributes) of
NodesFields -> ok; NodesFields -> ok;
@ -105,7 +105,7 @@ set_node(_) ->
%% @spec (Host, Node, From) -> pubsubNode() | {error, Reason} %% @spec (Host, Node, From) -> pubsubNode() | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
get_node(Host, Node, _From) -> get_node(Host, Node, _From) ->
get_node(Host, Node). get_node(Host, Node).
get_node(Host, Node) -> get_node(Host, Node) ->
@ -114,24 +114,24 @@ get_node(Host, Node) ->
[] -> {error, 'item-not-found'}; [] -> {error, 'item-not-found'};
Error -> Error Error -> Error
end. end.
get_node(NodeId) -> get_node(Nidx) ->
case catch mnesia:index_read(pubsub_node, NodeId, #pubsub_node.id) of case catch mnesia:index_read(pubsub_node, Nidx, #pubsub_node.idx) of
[Record] when is_record(Record, pubsub_node) -> Record; [Record] when is_record(Record, pubsub_node) -> Record;
[] -> {error, 'item-not-found'}; [] -> {error, 'item-not-found'};
Error -> Error Error -> Error
end. end.
%% @spec (Host, From) -> [pubsubNode()] | {error, Reason} %% @spec (Host, From) -> [pubsubNode()] | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
get_nodes(Host, _From) -> get_nodes(Host, _From) ->
get_nodes(Host). get_nodes(Host).
get_nodes(Host) -> get_nodes(Host) ->
mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}). mnesia:match_object(#pubsub_node{id = {Host, '_'}, _ = '_'}).
%% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
%% Depth = integer() %% Depth = integer()
%% Record = pubsubNode() %% Record = pubsubNode()
%% @doc <p>Default node tree does not handle parents, return empty list.</p> %% @doc <p>Default node tree does not handle parents, return empty list.</p>
@ -139,9 +139,9 @@ get_parentnodes(_Host, _Node, _From) ->
[]. [].
%% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
%% Depth = integer() %% Depth = integer()
%% Record = pubsubNode() %% Record = pubsubNode()
%% @doc <p>Default node tree does not handle parents, return a list %% @doc <p>Default node tree does not handle parents, return a list
@ -154,27 +154,27 @@ get_parentnodes_tree(Host, Node, From) ->
%% @spec (Host, Node, From) -> [pubsubNode()] | {error, Reason} %% @spec (Host, Node, From) -> [pubsubNode()] | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node, _From) ->
get_subnodes(Host, Node). get_subnodes(Host, Node).
get_subnodes(Host, <<>>) -> get_subnodes(Host, <<>>) ->
Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _}, Q = qlc:q([N || #pubsub_node{id = {NHost, _},
parents = Parents} = N <- mnesia:table(pubsub_node), parents = Parents} = N <- mnesia:table(pubsub_node),
Host == NHost, Host == NHost,
Parents == []]), Parents == []]),
qlc:e(Q); qlc:e(Q);
get_subnodes(Host, Node) -> get_subnodes(Host, Node) ->
Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _}, Q = qlc:q([N || #pubsub_node{id = {NHost, _},
parents = Parents} = N <- mnesia:table(pubsub_node), parents = Parents} = N <- mnesia:table(pubsub_node),
Host == NHost, Host == NHost,
lists:member(Node, Parents)]), lists:member(Node, Parents)]),
qlc:e(Q). qlc:e(Q).
%% @spec (Host, Index, From) -> [pubsubNodeIdx()] | {error, Reason} %% @spec (Host, Index, From) -> [nodeidx()] | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node, _From) ->
get_subnodes_tree(Host, Node). get_subnodes_tree(Host, Node).
get_subnodes_tree(Host, Node) -> get_subnodes_tree(Host, Node) ->
@ -184,7 +184,7 @@ get_subnodes_tree(Host, Node) ->
Rec -> Rec ->
BasePlugin = list_to_atom("node_"++Rec#pubsub_node.type), BasePlugin = list_to_atom("node_"++Rec#pubsub_node.type),
BasePath = BasePlugin:node_to_path(Node), BasePath = BasePlugin:node_to_path(Node),
mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) -> mnesia:foldl(fun(#pubsub_node{id = {H, N}} = R, Acc) ->
Plugin = list_to_atom("node_"++R#pubsub_node.type), Plugin = list_to_atom("node_"++R#pubsub_node.type),
Path = Plugin:node_to_path(N), Path = Plugin:node_to_path(N),
case lists:prefix(BasePath, Path) and (H == Host) of case lists:prefix(BasePath, Path) and (H == Host) of
@ -195,10 +195,10 @@ get_subnodes_tree(Host, Node) ->
end. end.
%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason} %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% NodeType = mod_pubsub:nodeType() %% NodeType = nodeType()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% Options = list() %% Options = list()
create_node(Host, Node, Type, Owner, Options, Parents) -> create_node(Host, Node, Type, Owner, Options, Parents) ->
BJID = jlib:short_prepd_bare_jid(Owner), BJID = jlib:short_prepd_bare_jid(Owner),
@ -226,29 +226,29 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
end, end,
case ParentExists of case ParentExists of
true -> true ->
NodeId = pubsub_index:new(node), Nidx = pubsub_index:new(node),
mnesia:write(#pubsub_node{nodeid = {Host, Node}, mnesia:write(#pubsub_node{id = {Host, Node},
id = NodeId, idx = Nidx,
parents = Parents, parents = Parents,
type = Type, type = Type,
owners = [BJID], owners = [BJID],
options = Options}), options = Options}),
{ok, NodeId}; {ok, Nidx};
false -> false ->
%% Requesting entity is prohibited from creating nodes %% Requesting entity is prohibited from creating nodes
{error, 'forbidden'} {error, 'forbidden'}
end; end;
_ -> _ ->
%% NodeID already exists %% Node already exists
{error, 'conflict'} {error, 'conflict'}
end. end.
%% @spec (Host, Node) -> [mod_pubsub:node()] %% @spec (Host, Node) -> [mod_pubsub:node()]
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
delete_node(Host, Node) -> delete_node(Host, Node) ->
Removed = get_subnodes_tree(Host, Node), Removed = get_subnodes_tree(Host, Node),
lists:foreach(fun(#pubsub_node{nodeid = {_, N}, id = I}) -> lists:foreach(fun(#pubsub_node{id = {_, N}, idx = I}) ->
pubsub_index:free(node, I), pubsub_index:free(node, I),
mnesia:delete({pubsub_node, {Host, N}}) mnesia:delete({pubsub_node, {Host, N}})
end, Removed), end, Removed),

View File

@ -32,7 +32,6 @@
%%% development is still a work in progress. However, the system is already %%% development is still a work in progress. However, the system is already
%%% useable and useful as is. Please, send us comments, feedback and %%% useable and useful as is. Please, send us comments, feedback and
%%% improvements.</p> %%% improvements.</p>
-module(nodetree_tree_odbc). -module(nodetree_tree_odbc).
-author('christophe.romain@process-one.net'). -author('christophe.romain@process-one.net').
@ -84,16 +83,16 @@ terminate(_Host, _ServerHost) ->
ok. ok.
%% @spec () -> [Option] %% @spec () -> [Option]
%% Option = mod_pubsub:nodetreeOption() %% Option = nodetreeOption()
%% @doc Returns the default pubsub node tree options. %% @doc Returns the default pubsub node tree options.
options() -> options() ->
[{virtual_tree, false}, [{virtual_tree, false},
{odbc, true}]. {odbc, true}].
%% @spec (Host, Node, From) -> pubsubNode() | {error, Reason} %% @spec (Host, Node, From) -> node() | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
get_node(Host, Node, _From) -> get_node(Host, Node, _From) ->
get_node(Host, Node). get_node(Host, Node).
get_node(Host, Node) -> get_node(Host, Node) ->
@ -111,22 +110,22 @@ get_node(Host, Node) ->
_ -> _ ->
{error, 'item_not_found'} {error, 'item_not_found'}
end. end.
get_node(NodeId) -> get_node(Nidx) ->
case catch ejabberd_odbc:sql_query_t( case catch ejabberd_odbc:sql_query_t(
["select host, node, parent, type " ["select host, node, parent, type "
"from pubsub_node " "from pubsub_node "
"where nodeid='", NodeId, "';"]) "where nodeid='", Nidx, "';"])
of of
{selected, ["host", "node", "parent", "type"], [{Host, Node, Parent, Type}]} -> {selected, ["host", "node", "parent", "type"], [{Host, Node, Parent, Type}]} ->
raw_to_node(Host, {Node, Parent, Type, NodeId}); raw_to_node(Host, {Node, Parent, Type, Nidx});
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
{error, 'internal_server_error'}; {error, 'internal_server_error'};
_ -> _ ->
{error, 'item_not_found'} {error, 'item_not_found'}
end. end.
%% @spec (Host, From) -> [pubsubNode()] | {error, Reason} %% @spec (Host, From) -> [node()] | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
get_nodes(Host, _From) -> get_nodes(Host, _From) ->
get_nodes(Host). get_nodes(Host).
get_nodes(Host) -> get_nodes(Host) ->
@ -143,21 +142,21 @@ get_nodes(Host) ->
end. end.
%% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
%% Depth = integer() %% Depth = int()
%% Record = pubsubNode() %% Record = mod_pubsub:pubsub_node()
%% @doc <p>Default node tree does not handle parents, return empty list.</p> %% @doc <p>Default node tree does not handle parents, return empty list.</p>
get_parentnodes(_Host, _Node, _From) -> get_parentnodes(_Host, _Node, _From) ->
[]. [].
%% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
%% Depth = integer() %% Depth = int()
%% Record = pubsubNode() %% Record = mod_pubsub:pubsub_node()
%% @doc <p>Default node tree does not handle parents, return a list %% @doc <p>Default node tree does not handle parents, return a list
%% containing just this node.</p> %% containing just this node.</p>
get_parentnodes_tree(Host, Node, From) -> get_parentnodes_tree(Host, Node, From) ->
@ -182,10 +181,10 @@ get_subnodes(Host, Node) ->
[] []
end. end.
%% @spec (Host, Index, From) -> [pubsubNodeIdx()] | {error, Reason} %% @spec (Host, Index, From) -> [nodeidx()] | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node, _From) ->
get_subnodes_tree(Host, Node). get_subnodes_tree(Host, Node).
get_subnodes_tree(Host, Node) -> get_subnodes_tree(Host, Node) ->
@ -203,10 +202,10 @@ get_subnodes_tree(Host, Node) ->
end. end.
%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason} %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason}
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% NodeType = mod_pubsub:nodeType() %% NodeType = nodeType()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% Options = list() %% Options = list()
create_node(Host, Node, Type, Owner, Options, Parents) -> create_node(Host, Node, Type, Owner, Options, Parents) ->
BJID = jlib:short_prepd_bare_jid(Owner), BJID = jlib:short_prepd_bare_jid(Owner),
@ -223,9 +222,9 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
true; true;
[Parent | _] -> [Parent | _] ->
case nodeid(Host, Parent) of case nodeid(Host, Parent) of
{result, PNodeId} -> {result, Pidx} ->
BHost = list_to_binary(Host), BHost = list_to_binary(Host),
case nodeowners(PNodeId) of case nodeowners(Pidx) of
[{undefined, BHost, undefined}] -> true; [{undefined, BHost, undefined}] -> true;
Owners -> lists:member(BJID, Owners) Owners -> lists:member(BJID, Owners)
end; end;
@ -239,11 +238,11 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
case ParentExists of case ParentExists of
true -> true ->
case set_node(#pubsub_node{ case set_node(#pubsub_node{
nodeid={Host, Node}, id={Host, Node},
parents=Parents, parents=Parents,
type=Type, type=Type,
options=Options}) of options=Options}) of
{result, NodeId} -> {ok, NodeId}; {result, Nidx} -> {ok, Nidx};
Other -> Other Other -> Other
end; end;
false -> false ->
@ -251,16 +250,16 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
{error, 'forbidden'} {error, 'forbidden'}
end; end;
{result, _} -> {result, _} ->
%% NodeID already exists %% Node already exists
{error, 'conflict'}; {error, 'conflict'};
Error -> Error ->
Error Error
end. end.
%% @spec (Host, Node) -> [mod_pubsub:node()] %% @spec (Host, Node) -> [node()]
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
delete_node(Host, Node) -> delete_node(Host, Node) ->
H = ?PUBSUB:escape(Host), H = ?PUBSUB:escape(Host),
N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)),
@ -273,11 +272,11 @@ delete_node(Host, Node) ->
%% helpers %% helpers
raw_to_node(Host, {Node, Parent, Type, NodeId}) -> raw_to_node(Host, {Node, Parent, Type, Nidx}) ->
Options = case catch ejabberd_odbc:sql_query_t( Options = case catch ejabberd_odbc:sql_query_t(
["select name,val " ["select name,val "
"from pubsub_node_option " "from pubsub_node_option "
"where nodeid='", NodeId, "';"]) "where nodeid='", Nidx, "';"])
of of
{selected, ["name", "val"], ROptions} -> {selected, ["name", "val"], ROptions} ->
DbOpts = lists:map(fun({Key, Value}) -> DbOpts = lists:map(fun({Key, Value}) ->
@ -295,16 +294,16 @@ raw_to_node(Host, {Node, Parent, Type, NodeId}) ->
[] []
end, end,
#pubsub_node{ #pubsub_node{
nodeid = {Host, ?PUBSUB:string_to_node(Node)}, id = {Host, ?PUBSUB:string_to_node(Node)},
parents = [?PUBSUB:string_to_node(Parent)], parents = [?PUBSUB:string_to_node(Parent)],
id = NodeId, idx = Nidx,
type = Type, type = Type,
options = Options}. options = Options}.
%% @spec (NodeRecord) -> ok | {error, Reason} %% @spec (NodeRecord) -> ok | {error, Reason}
%% Record = mod_pubsub:pubsub_node() %% Record = mod_pubsub:pubsub_node()
set_node(Record) -> set_node(Record) ->
{Host, Node} = Record#pubsub_node.nodeid, {Host, Node} = Record#pubsub_node.id,
Parent = case Record#pubsub_node.parents of Parent = case Record#pubsub_node.parents of
[] -> <<>>; [] -> <<>>;
[First | _] -> First [First | _] -> First
@ -313,29 +312,29 @@ set_node(Record) ->
H = ?PUBSUB:escape(Host), H = ?PUBSUB:escape(Host),
N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)),
P = ?PUBSUB:escape(?PUBSUB:node_to_string(Parent)), P = ?PUBSUB:escape(?PUBSUB:node_to_string(Parent)),
NodeId = case nodeid(Host, Node) of Nidx = case nodeid(Host, Node) of
{result, OldNodeId} -> {result, OldNidx} ->
catch ejabberd_odbc:sql_query_t( catch ejabberd_odbc:sql_query_t(
["delete from pubsub_node_option " ["delete from pubsub_node_option "
"where nodeid='", OldNodeId, "';"]), "where nodeid='", OldNidx, "';"]),
catch ejabberd_odbc:sql_query_t( catch ejabberd_odbc:sql_query_t(
["update pubsub_node " ["update pubsub_node "
"set host='", H, "' " "set host='", H, "' "
"node='", N, "' " "node='", N, "' "
"parent='", P, "' " "parent='", P, "' "
"type='", Type, "' " "type='", Type, "' "
"where nodeid='", OldNodeId, "';"]), "where nodeid='", OldNidx, "';"]),
OldNodeId; OldNidx;
_ -> _ ->
catch ejabberd_odbc:sql_query_t( catch ejabberd_odbc:sql_query_t(
["insert into pubsub_node(host, node, parent, type) " ["insert into pubsub_node(host, node, parent, type) "
"values('", H, "', '", N, "', '", P, "', '", Type, "');"]), "values('", H, "', '", N, "', '", P, "', '", Type, "');"]),
case nodeid(Host, Node) of case nodeid(Host, Node) of
{result, NewNodeId} -> NewNodeId; {result, NewNidx} -> NewNidx;
_ -> none % this should not happen _ -> none % this should not happe
end end
end, end,
case NodeId of case Nidx of
none -> none ->
{error, 'internal_server_error'}; {error, 'internal_server_error'};
_ -> _ ->
@ -344,9 +343,9 @@ set_node(Record) ->
SValue = ?PUBSUB:escape(lists:flatten(io_lib:fwrite("~p",[Value]))), SValue = ?PUBSUB:escape(lists:flatten(io_lib:fwrite("~p",[Value]))),
catch ejabberd_odbc:sql_query_t( catch ejabberd_odbc:sql_query_t(
["insert into pubsub_node_option(nodeid, name, val) " ["insert into pubsub_node_option(nodeid, name, val) "
"values('", NodeId, "', '", SKey, "', '", SValue, "');"]) "values('", Nidx, "', '", SKey, "', '", SValue, "');"])
end, Record#pubsub_node.options), end, Record#pubsub_node.options),
{result, NodeId} {result, Nidx}
end. end.
nodeid(Host, Node) -> nodeid(Host, Node) ->
@ -357,16 +356,16 @@ nodeid(Host, Node) ->
"from pubsub_node " "from pubsub_node "
"where host='", H, "' and node='", N, "';"]) "where host='", H, "' and node='", N, "';"])
of of
{selected, ["nodeid"], [{NodeId}]} -> {selected, ["nodeid"], [{Nidx}]} ->
{result, NodeId}; {result, Nidx};
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
{error, 'internal_server_error'}; {error, 'internal_server_error'};
_ -> _ ->
{error, 'item_not_found'} {error, 'item_not_found'}
end. end.
nodeowners(NodeId) -> nodeowners(Nidx) ->
{result, Res} = node_flat_odbc:get_node_affiliations(NodeId), {result, Res} = node_flat_odbc:get_node_affiliations(Nidx),
lists:foldl(fun({LJID, owner}, Acc) -> [LJID|Acc]; lists:foldl(fun({LJID, owner}, Acc) -> [LJID|Acc];
(_, Acc) -> Acc (_, Acc) -> Acc
end, [], Res). end, [], Res).

View File

@ -86,18 +86,19 @@ set_node(_NodeRecord) ->
%% @spec (Host, Node, From) -> pubsubNode() %% @spec (Host, Node, From) -> pubsubNode()
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% @doc <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Node record contains default values.</p> %% as existing. Node record contains default values.</p>
get_node(Host, Node, _From) -> get_node(Host, Node, _From) ->
get_node(Host, Node). get_node(Host, Node).
get_node(Host, Node) -> get_node(Host, Node) ->
#pubsub_node{nodeid = {Host, Node}, id = {Host, Node}, owners = [{undefined, list_to_binary(Host), undefined}]}. %% TODO : to fix idx
#pubsub_node{id = {Host, Node}, idx = {Host, Node}, owners = [{undefined, list_to_binary(Host), undefined}]}.
get_node({Host, _} = NodeId) -> get_node({Host, _} = NodeId) ->
#pubsub_node{nodeid = NodeId, id = NodeId, owners = [{undefined, list_to_binary(Host), undefined}]}. #pubsub_node{id = NodeId, idx = NodeId, owners = [{undefined, list_to_binary(Host), undefined}]}.
%% @spec (Host, From) -> [pubsubNode()] %% @spec (Host, From) -> [pubsubNode()]
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | ljid()
%% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% @doc <p>Virtual node tree does not handle a node database. Any node is considered
%% as existing. Nodes list can not be determined.</p> %% as existing. Nodes list can not be determined.</p>
get_nodes(Host, _From) -> get_nodes(Host, _From) ->
@ -107,8 +108,8 @@ get_nodes(_Host) ->
%% @spec (Host, Node, From) -> [pubsubNode()] %% @spec (Host, Node, From) -> [pubsubNode()]
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% From = mod_pubsub:jid() %% From = ljid()
%% @doc <p>Virtual node tree does not handle parent/child. Child list is empty.</p> %% @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).
@ -117,7 +118,7 @@ get_subnodes(_Host, _Node) ->
%% @spec (Host, Index, From) -> [pubsubNode()] %% @spec (Host, Index, From) -> [pubsubNode()]
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% @doc <p>Virtual node tree does not handle parent/child. Child list is empty.</p> %% @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, _From) ->
get_subnodes_tree(Host, Node). get_subnodes_tree(Host, Node).
@ -126,9 +127,9 @@ get_subnodes_tree(_Host, _Node) ->
%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% Type = mod_pubsub:nodeType() %% Type = nodeType()
%% Owner = mod_pubsub:jid() %% Owner = ljid()
%% Options = list() %% Options = list()
%% @doc <p>No node record is stored on database. Any valid node %% @doc <p>No node record is stored on database. Any valid node
%% is considered as already created.</p> %% is considered as already created.</p>
@ -143,7 +144,7 @@ create_node(Host, Node, _Type, Owner, _Options, _Parents) ->
%% @spec (Host, Node) -> [mod_pubsub:node()] %% @spec (Host, Node) -> [mod_pubsub:node()]
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = node()
%% @doc <p>Virtual node tree does not handle parent/child. %% @doc <p>Virtual node tree does not handle parent/child.
%% node deletion just affects the corresponding node.</p> %% node deletion just affects the corresponding node.</p>
delete_node(Host, Node) -> delete_node(Host, Node) ->

View File

@ -35,14 +35,25 @@
%% ------------------------------- %% -------------------------------
%% Pubsub types %% Pubsub types
%%% @type host() = string(). %%% @type host() = binary().
%%% <p><tt>host</tt> is the name of the PubSub service. For example, it can be %%% <p><tt>host</tt> is the name of the PubSub service. For example, it can be
%%% <tt>"pubsub.localhost"</tt>.</p> %%% <tt>pubsub.localhost</tt>.</p>
%%% @type pubsubNode() = [string()]. %%% @type node() = binary().
%%% <p>A node is defined by a list of its ancestors. The last element is the name %%% <p>A <tt>node</tt> is the name of a Node. It can be anything and may represent
%%% of the current node. For example: %%% some hierarchical tree depending of the node type.
%%% ```["home", "localhost", "cromain", "node1"]'''</p> %%% For example:
%%% /home/localhost/user/node
%%% princely_musings
%%% http://jabber.org/protocol/tune
%%% My-Own_Node</p>
%%% @type item() = binary().
%%% <p>An <tt>item</tt> is the name of an Item. It can be anything.
%%% For example:
%%% 38964
%%% my-tune
%%% FD6SBE6a27d</p>
%%% @type stanzaError() = #xmlel{}. %%% @type stanzaError() = #xmlel{}.
%%% Example: %%% Example:
@ -82,34 +93,29 @@
%%% plugin to use to manage a given node. For example, it can be %%% plugin to use to manage a given node. For example, it can be
%%% <tt>"flat"</tt>, <tt>"hometree"</tt> or <tt>"blog"</tt>.</p> %%% <tt>"flat"</tt>, <tt>"hometree"</tt> or <tt>"blog"</tt>.</p>
%%% @type jid() = #jid{ %%% @type ljid() = {User::binary(), Server::binary(), Resource::binary()}.
%%% user = string(),
%%% server = string(),
%%% resource = string(),
%%% luser = string(),
%%% lserver = string(),
%%% lresource = string()}.
%%% @type ljid() = {User::string(), Server::string(), Resource::string()}. %%% @type nodeidx() = int()
%%% @type affiliation() = none | owner | publisher | outcast. %%% @type affiliation() = none | owner | publisher | member | outcast.
%%% @type subscription() = none | pending | unconfigured | subscribed. %%% @type subscription() = none | pending | unconfigured | subscribed.
%%% internal pubsub index table %%% internal pubsub index table
-record(pubsub_index, {index, last, free}). -record(pubsub_index, {index, last, free}).
%%% @type pubsubNode() = #pubsub_node{ %%% @type pubsubNode() = #pubsub_node{
%%% nodeid = {Host::host(), Node::pubsubNode()}, %%% id = {host(), node()},
%%% parentid = Node::pubsubNode(), %%% idx = nodeidx(),
%%% nodeidx = int(), %%% parents = [Node::pubsubNode()],
%%% type = nodeType(), %%% type = nodeType(),
%%% owners = [ljid()],
%%% options = [nodeOption()]}. %%% options = [nodeOption()]}.
%%% <p>This is the format of the <tt>nodes</tt> table. The type of the table %%% <p>This is the format of the <tt>nodes</tt> table. The type of the table
%%% is: <tt>set</tt>,<tt>ram/disc</tt>.</p> %%% is: <tt>set</tt>,<tt>ram/disc</tt>.</p>
%%% <p>The <tt>parentid</tt> and <tt>type</tt> fields are indexed.</p> %%% <p>The <tt>parents</tt> and <tt>type</tt> fields are indexed.</p>
%%% <p><tt>nodeidx</tt> can be anything you want.</p> %%% <p><tt>nodeidx</tt> is an integer.</p>
-record(pubsub_node, {nodeid, -record(pubsub_node, {id,
id, idx,
parents = [], parents = [],
type = "flat", type = "flat",
owners = [], owners = [],
@ -117,26 +123,26 @@
}). }).
%%% @type pubsubState() = #pubsub_state{ %%% @type pubsubState() = #pubsub_state{
%%% stateid = {ljid(), nodeidx()}, %%% id = {ljid(), nodeidx()},
%%% items = [ItemId::string()], %%% items = [item()],
%%% affiliation = affiliation(), %%% affiliation = affiliation(),
%%% subscriptions = [subscription()]}. %%% subscriptions = [subscription()]}.
%%% <p>This is the format of the <tt>affiliations</tt> table. The type of the %%% <p>This is the format of the <tt>affiliations</tt> table. The type of the
%%% table is: <tt>set</tt>,<tt>ram/disc</tt>.</p> %%% table is: <tt>set</tt>,<tt>ram/disc</tt>.</p>
-record(pubsub_state, {stateid, -record(pubsub_state, {id,
items = [], items = [],
affiliation = none, affiliation = none,
subscriptions = [] subscriptions = []
}). }).
%%% @type pubsubItem() = #pubsub_item{ %%% @type pubsubItem() = #pubsub_item{
%%% itemid = {ItemId::string(), nodeidx()}, %%% id = {item(), nodeidx()},
%%% creation = {now(), ljid()}, %%% creation = {now(), ljid()},
%%% modification = {now(), ljid()}, %%% modification = {now(), ljid()},
%%% payload = XMLContent::string()}. %%% payload = XMLContent::string()}.
%%% <p>This is the format of the <tt>published items</tt> table. The type of the %%% <p>This is the format of the <tt>published items</tt> table. The type of the
%%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p> %%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p>
-record(pubsub_item, {itemid, -record(pubsub_item, {id,
creation = {unknown,unknown}, creation = {unknown,unknown},
modification = {unknown,unknown}, modification = {unknown,unknown},
payload = [] payload = []
@ -144,7 +150,7 @@
%% @type pubsubSubscription() = #pubsub_subscription{ %% @type pubsubSubscription() = #pubsub_subscription{
%% subid = string(), %% subid = string(),
%% state_key = {ljid(), pubsubNodeId()}, %% state_key = {ljid(), nodeidx()},
%% options = [{atom(), term()}] %% options = [{atom(), term()}]
%% }. %% }.
%% <p>This is the format of the <tt>subscriptions</tt> table. The type of the %% <p>This is the format of the <tt>subscriptions</tt> table. The type of the
@ -153,7 +159,7 @@
%% @type pubsubLastItem() = #pubsub_last_item{ %% @type pubsubLastItem() = #pubsub_last_item{
%% nodeid = nodeidx(), %% nodeid = nodeidx(),
%% itemid = string(), %% itemid = item(),
%% creation = {now(), ljid()}, %% creation = {now(), ljid()},
%% payload = XMLContent::string()}. %% payload = XMLContent::string()}.
%% <p>This is the format of the <tt>last items</tt> table. it stores last item payload %% <p>This is the format of the <tt>last items</tt> table. it stores last item payload

View File

@ -32,27 +32,27 @@
%% Those -spec lines produce errors in old Erlang versions. %% Those -spec lines produce errors in old Erlang versions.
%% They can be enabled again in ejabberd 3.0 because it uses R12B or higher. %% They can be enabled again in ejabberd 3.0 because it uses R12B or higher.
-spec read_subscription(SubID :: string()) -> {ok, #pubsub_subscription{}} | notfound. -spec read_subscription(SubId :: string()) -> {ok, #pubsub_subscription{}} | notfound.
read_subscription(SubID) -> read_subscription(SubId) ->
case ejabberd_odbc:sql_query_t( case ejabberd_odbc:sql_query_t(
["select opt_name, opt_value " ["select opt_name, opt_value "
"from pubsub_subscription_opt " "from pubsub_subscription_opt "
"where subid = '", ejabberd_odbc:escape(SubID), "'"]) of "where subid = '", ejabberd_odbc:escape(SubId), "'"]) of
{selected, ["opt_name", "opt_value"], []} -> {selected, ["opt_name", "opt_value"], []} ->
notfound; notfound;
{selected, ["opt_name", "opt_value"], Options} -> {selected, ["opt_name", "opt_value"], Options} ->
{ok, #pubsub_subscription{subid = SubID, {ok, #pubsub_subscription{subid = SubId,
options = lists:map(fun subscription_opt_from_odbc/1, Options)}} options = lists:map(fun subscription_opt_from_odbc/1, Options)}}
end. end.
-spec delete_subscription(SubID :: string()) -> ok. -spec delete_subscription(SubId :: string()) -> ok.
delete_subscription(SubID) -> delete_subscription(SubId) ->
ejabberd_odbc:sql_query_t(["delete from pubsub_subscription_opt " ejabberd_odbc:sql_query_t(["delete from pubsub_subscription_opt "
"where subid = '", ejabberd_odbc:escape(SubID), "'"]), "where subid = '", ejabberd_odbc:escape(SubId), "'"]),
ok. ok.

View File

@ -1,5 +1,5 @@
--- mod_pubsub.erl 2010-08-04 18:28:18.000000000 +0200 --- mod_pubsub.erl 2010-09-10 18:04:47.000000000 +0200
+++ mod_pubsub_odbc.erl 2010-08-04 18:29:41.000000000 +0200 +++ mod_pubsub_odbc.erl 2010-09-10 19:43:53.000000000 +0200
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
%%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see
%%% XEP-0060 section 12.18. %%% XEP-0060 section 12.18.
@ -49,7 +49,7 @@
init_nodes(Host, ServerHost, NodeTree, Plugins), init_nodes(Host, ServerHost, NodeTree, Plugins),
State = #state{host = Host, State = #state{host = Host,
server_host = ServerHost, server_host = ServerHost,
@@ -280,206 +278,15 @@ @@ -280,209 +278,14 @@
init_nodes(Host, ServerHost, _NodeTree, Plugins) -> init_nodes(Host, ServerHost, _NodeTree, Plugins) ->
%% TODO, this call should be done plugin side %% TODO, this call should be done plugin side
@ -72,18 +72,18 @@
- ?INFO_MSG("upgrade node pubsub tables",[]), - ?INFO_MSG("upgrade node pubsub tables",[]),
- F = fun() -> - F = fun() ->
- {Result, LastIdx} = lists:foldl( - {Result, LastIdx} = lists:foldl(
- fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, NodeIdx}) -> - fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, Nidx}) ->
- ItemsList = - ItemsList =
- lists:foldl( - lists:foldl(
- fun({item, IID, Publisher, Payload}, Acc) -> - fun({item, ItemName, Publisher, Payload}, Acc) ->
- C = {unknown, Publisher}, - C = {unknown, Publisher},
- M = {now(), Publisher}, - M = {now(), Publisher},
- mnesia:write( - mnesia:write(
- #pubsub_item{itemid = {IID, NodeIdx}, - #pubsub_item{id = {ItemName, Nidx},
- creation = C, - creation = C,
- modification = M, - modification = M,
- payload = Payload}), - payload = Payload}),
- [{Publisher, IID} | Acc] - [{Publisher, ItemName} | Acc]
- end, [], Items), - end, [], Items),
- Owners = - Owners =
- dict:fold( - dict:fold(
@ -97,7 +97,7 @@
- end - end
- end, [], ItemsList), - end, [], ItemsList),
- mnesia:write({pubsub_state, - mnesia:write({pubsub_state,
- {JID, NodeIdx}, - {JID, Nidx},
- UsrItems, - UsrItems,
- Aff, - Aff,
- Sub}), - Sub}),
@ -107,12 +107,12 @@
- end - end
- end, [], Entities), - end, [], Entities),
- mnesia:delete({pubsub_node, NodeId}), - mnesia:delete({pubsub_node, NodeId}),
- {[#pubsub_node{nodeid = NodeId, - {[#pubsub_node{id = NodeId,
- id = NodeIdx, - idx = Nidx,
- parents = [element(2, ParentId)], - parents = [element(2, ParentId)],
- owners = Owners, - owners = Owners,
- options = Options} | - options = Options} |
- RecList], NodeIdx + 1} - RecList], Nidx + 1}
- end, {[], 1}, - end, {[], 1},
- mnesia:match_object( - mnesia:match_object(
- {pubsub_node, {Host, '_'}, '_', '_'})), - {pubsub_node, {Host, '_'}, '_', '_'})),
@ -137,32 +137,33 @@
- [nodeid, parentid, type, owners, options] -> - [nodeid, parentid, type, owners, options] ->
- F = fun({pubsub_node, NodeId, {_, Parent}, Type, Owners, Options}) -> - F = fun({pubsub_node, NodeId, {_, Parent}, Type, Owners, Options}) ->
- #pubsub_node{ - #pubsub_node{
- nodeid = NodeId, - id = NodeId,
- id = 0, - idx = 0,
- parents = [Parent], - parents = [Parent],
- type = Type, - type = Type,
- owners = Owners, - owners = Owners,
- options = Options} - options = Options}
- end, - end,
- %% TODO : to change nodeid/id and id/idx or not to change ?
- mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]), - mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]),
- FNew = fun() -> - FNew = fun() ->
- LastIdx = lists:foldl(fun(#pubsub_node{nodeid = NodeId} = PubsubNode, NodeIdx) -> - LastIdx = lists:foldl(fun(#pubsub_node{id = NodeId} = PubsubNode, Nidx) ->
- mnesia:write(PubsubNode#pubsub_node{id = NodeIdx}), - mnesia:write(PubsubNode#pubsub_node{idx = Nidx}),
- lists:foreach(fun(#pubsub_state{stateid = StateId} = State) -> - lists:foreach(fun(#pubsub_state{id = StateId} = State) ->
- {JID, _} = StateId, - {JID, _} = StateId,
- mnesia:delete({pubsub_state, StateId}), - mnesia:delete({pubsub_state, StateId}),
- mnesia:write(State#pubsub_state{stateid = {JID, NodeIdx}}) - mnesia:write(State#pubsub_state{id = {JID, Nidx}})
- end, mnesia:match_object(#pubsub_state{stateid = {'_', NodeId}, _ = '_'})), - end, mnesia:match_object(#pubsub_state{id = {'_', NodeId}, _ = '_'})),
- lists:foreach(fun(#pubsub_item{itemid = ItemId} = Item) -> - lists:foreach(fun(#pubsub_item{id = ItemId} = Item) ->
- {IID, _} = ItemId, - {ItemName, _} = ItemId,
- {M1, M2} = Item#pubsub_item.modification, - {M1, M2} = Item#pubsub_item.modification,
- {C1, C2} = Item#pubsub_item.creation, - {C1, C2} = Item#pubsub_item.creation,
- mnesia:delete({pubsub_item, ItemId}), - mnesia:delete({pubsub_item, ItemId}),
- mnesia:write(Item#pubsub_item{itemid = {IID, NodeIdx}, - mnesia:write(Item#pubsub_item{id = {ItemName, Nidx},
- modification = {M2, M1}, - modification = {M2, M1},
- creation = {C2, C1}}) - creation = {C2, C1}})
- end, mnesia:match_object(#pubsub_item{itemid = {'_', NodeId}, _ = '_'})), - end, mnesia:match_object(#pubsub_item{id = {'_', NodeId}, _ = '_'})),
- NodeIdx + 1 - Nidx + 1
- end, 1, mnesia:match_object( - end, 1, mnesia:match_object(
- {pubsub_node, {Host, '_'}, '_', '_', '_', '_', '_'}) - {pubsub_node, {Host, '_'}, '_', '_', '_', '_', '_'})
- ++ mnesia:match_object( - ++ mnesia:match_object(
@ -179,13 +180,14 @@
- [nodeid, id, parent, type, owners, options] -> - [nodeid, id, parent, type, owners, options] ->
- F = fun({pubsub_node, NodeId, Id, Parent, Type, Owners, Options}) -> - F = fun({pubsub_node, NodeId, Id, Parent, Type, Owners, Options}) ->
- #pubsub_node{ - #pubsub_node{
- nodeid = NodeId, - id = NodeId,
- id = Id, - idx = Id,
- parents = [Parent], - parents = [Parent],
- type = Type, - type = Type,
- owners = Owners, - owners = Owners,
- options = Options} - options = Options}
- end, - end,
- %% TODO : to change nodeid/id and id/idx or not to change ?
- mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]), - mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]),
- rename_default_nodeplugin(); - rename_default_nodeplugin();
- _ -> - _ ->
@ -203,7 +205,7 @@
- [<<>>] -> []; - [<<>>] -> [];
- Parents -> Parents - Parents -> Parents
- end, - end,
- mnesia:write(Node#pubsub_node{nodeid={H, BN}, parents=BP}), - mnesia:write(Node#pubsub_node{id={H, BN}, parents=BP}),
- mnesia:delete({pubsub_node, {H, N}}); - mnesia:delete({pubsub_node, {H, N}});
- (_) -> - (_) ->
- ok - ok
@ -222,15 +224,15 @@
- case catch mnesia:table_info(pubsub_state, attributes) of - case catch mnesia:table_info(pubsub_state, attributes) of
- [stateid, items, affiliation, subscription] -> - [stateid, items, affiliation, subscription] ->
- ?INFO_MSG("upgrade state pubsub tables", []), - ?INFO_MSG("upgrade state pubsub tables", []),
- F = fun ({pubsub_state, {JID, NodeID}, Items, Aff, Sub}, Acc) -> - F = fun ({pubsub_state, {JID, NodeId}, Items, Aff, Sub}, Acc) ->
- Subs = case Sub of - Subs = case Sub of
- none -> - none ->
- []; - [];
- _ -> - _ ->
- {result, SubID} = pubsub_subscription:subscribe_node(JID, NodeID, []), - {result, SubId} = pubsub_subscription:subscribe_node(JID, NodeId, []),
- [{Sub, SubID}] - [{Sub, SubId}]
- end, - end,
- NewState = #pubsub_state{stateid = {JID, NodeID}, - NewState = #pubsub_state{id = {JID, NodeId},
- items = Items, - items = Items,
- affiliation = Aff, - affiliation = Aff,
- subscriptions = Subs}, - subscriptions = Subs},
@ -256,11 +258,11 @@
- _ -> - _ ->
- ok - ok
- end. - end.
+ -
send_loop(State) -> send_loop(State) ->
receive receive
@@ -491,7 +298,10 @@ {presence, JID, Pid} ->
@@ -493,7 +296,10 @@
%% for each node From is subscribed to %% for each node From is subscribed to
%% and if the node is so configured, send the last published item to From %% and if the node is so configured, send the last published item to From
lists:foreach(fun(PType) -> lists:foreach(fun(PType) ->
@ -272,37 +274,37 @@
lists:foreach( lists:foreach(
fun({Node, subscribed, _, SubJID}) -> fun({Node, subscribed, _, SubJID}) ->
if (SubJID == LJID) or (SubJID == BJID) -> if (SubJID == LJID) or (SubJID == BJID) ->
@@ -616,7 +426,8 @@ @@ -618,7 +424,8 @@
[#xmlel{name = 'identity', ns = ?NS_DISCO_INFO, [#xmlel{name = 'identity', ns = ?NS_DISCO_INFO,
attrs = [?XMLATTR('category', <<"pubsub">>), ?XMLATTR('type', <<"pep">>)]}]; attrs = [?XMLATTR('category', <<"pubsub">>), ?XMLATTR('type', <<"pep">>)]}];
disco_identity(Host, Node, From) -> disco_identity(Host, Node, From) ->
- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) ->
+ Owners = node_owners_call(Type, Idx), + Owners = node_owners_call(Type, Nidx),
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, _} -> {result, _} ->
{result, {result,
@@ -647,7 +458,8 @@ @@ -649,7 +456,8 @@
[?NS_PUBSUB_s [?NS_PUBSUB_s
| [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]]; | [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]];
disco_features(Host, Node, From) -> disco_features(Host, Node, From) ->
- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) ->
+ Owners = node_owners_call(Type, Idx), + Owners = node_owners_call(Type, Nidx),
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, _} -> {result, _} ->
{result, [?NS_PUBSUB_s {result, [?NS_PUBSUB_s
@@ -666,7 +478,8 @@ @@ -668,7 +476,8 @@
{result, disco_items(To, Node, From) ++ OtherItems}. {result, disco_items(To, Node, From) ++ OtherItems}.
disco_items(Host, <<>>, From) -> disco_items(Host, <<>>, From) ->
- Action = fun(#pubsub_node{nodeid ={_, NodeID}, options = Options, type = Type, id = Idx, owners = Owners}, Acc) -> - Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx, owners = Owners}, Acc) ->
+ Action = fun(#pubsub_node{nodeid ={_, NodeID}, options = Options, type = Type, id = Idx}, Acc) -> + Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx}, Acc) ->
+ Owners = node_owners_call(Type, Idx), + Owners = node_owners_call(Type, Nidx),
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, _} -> {result, _} ->
[#xmlel{name = 'item', ns = ?NS_DISCO_INFO, [#xmlel{name = 'item', ns = ?NS_DISCO_INFO,
@@ -680,13 +493,14 @@ @@ -682,13 +491,14 @@
_ -> Acc _ -> Acc
end end
end, end,
@ -313,26 +315,26 @@
end; end;
disco_items(Host, Node, From) -> disco_items(Host, Node, From) ->
- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) ->
+ Owners = node_owners_call(Type, Idx), + Owners = node_owners_call(Type, Nidx),
case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
{result, Items} -> {result, Items} ->
{result, {result,
@@ -771,10 +585,10 @@ @@ -774,10 +584,10 @@
lists:foreach(fun(PType) -> lists:foreach(fun(PType) ->
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]),
lists:foreach(fun lists:foreach(fun
- ({#pubsub_node{options = Options, owners = Owners, id = NodeId}, subscribed, _, JID}) -> - ({#pubsub_node{options = Options, owners = Owners, idx = Nidx}, subscribed, _, JID}) ->
+ ({#pubsub_node{options = Options, id = NodeId}, subscribed, _, JID}) -> + ({#pubsub_node{options = Options, idx = Nidx}, subscribed, _, JID}) ->
case get_option(Options, access_model) of case get_option(Options, access_model) of
presence -> presence ->
- case lists:member(BJID, Owners) of - case lists:member(BJID, Owners) of
+ case lists:member(BJID, node_owners(Host, PType, NodeId)) of + case lists:member(BJID, node_owners(Host, PType, Nidx)) of
true -> true ->
node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]); node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]);
false -> false ->
@@ -949,10 +763,11 @@ @@ -952,10 +762,11 @@
end, end,
ejabberd_router:route(To, From, Res); ejabberd_router:route(To, From, Res);
#iq{type = get, ns = ?NS_DISCO_ITEMS, #iq{type = get, ns = ?NS_DISCO_ITEMS,
@ -346,16 +348,16 @@
{result, IQRes} -> {result, IQRes} ->
Result = #xmlel{ns = ?NS_DISCO_ITEMS, Result = #xmlel{ns = ?NS_DISCO_ITEMS,
name = 'query', attrs = QAttrs, name = 'query', attrs = QAttrs,
@@ -1089,7 +904,7 @@ @@ -1092,7 +903,7 @@
[] -> [] ->
["leaf"]; %% No sub-nodes: it's a leaf node ["leaf"]; %% No sub-nodes: it's a leaf node
_ -> _ ->
- case node_call(Type, get_items, [NodeId, From]) of - case node_call(Type, get_items, [Nidx, From]) of
+ case node_call(Type, get_items, [NodeId, From, none]) of + case node_call(Type, get_items, [Nidx, From, none]) of
{result, []} -> ["collection"]; {result, []} -> ["collection"];
{result, _} -> ["leaf", "collection"]; {result, _} -> ["leaf", "collection"];
_ -> [] _ -> []
@@ -1105,8 +920,9 @@ @@ -1108,8 +919,9 @@
[]; [];
true -> true ->
[#xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_PUBSUB_s)]} | [#xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_PUBSUB_s)]} |
@ -367,7 +369,7 @@
end, features(Type))] end, features(Type))]
end, end,
%% TODO: add meta-data info (spec section 5.4) %% TODO: add meta-data info (spec section 5.4)
@@ -1135,8 +951,9 @@ @@ -1138,8 +950,9 @@
#xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_PUBSUB_s)]}, #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_PUBSUB_s)]},
#xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_ADHOC_s)]}, #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_ADHOC_s)]},
#xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_VCARD_s)]}] ++ #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_VCARD_s)]}] ++
@ -379,7 +381,7 @@
end, features(Host, Node))}; end, features(Host, Node))};
?NS_ADHOC_b -> ?NS_ADHOC_b ->
command_disco_info(Host, Node, From); command_disco_info(Host, Node, From);
@@ -1146,7 +963,7 @@ @@ -1149,7 +962,7 @@
node_disco_info(Host, Node, From) node_disco_info(Host, Node, From)
end. end.
@ -388,7 +390,7 @@
case tree_action(Host, get_subnodes, [Host, <<>>, From]) of case tree_action(Host, get_subnodes, [Host, <<>>, From]) of
Nodes when is_list(Nodes) -> Nodes when is_list(Nodes) ->
{result, lists:map( {result, lists:map(
@@ -1163,7 +980,7 @@ @@ -1166,7 +979,7 @@
Other -> Other ->
Other Other
end; end;
@ -397,7 +399,7 @@
%% TODO: support localization of this string %% TODO: support localization of this string
CommandItems = [ CommandItems = [
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item',
@@ -1172,19 +989,20 @@ @@ -1175,19 +988,20 @@
?XMLATTR('name', "Get Pending") ?XMLATTR('name', "Get Pending")
]}], ]}],
{result, CommandItems}; {result, CommandItems};
@ -408,22 +410,22 @@
-iq_disco_items(Host, Item, From) -> -iq_disco_items(Host, Item, From) ->
+iq_disco_items(Host, Item, From, RSM) -> +iq_disco_items(Host, Item, From, RSM) ->
case string:tokens(Item, "!") of case string:tokens(Item, "!") of
[_SNode, _ItemID] -> [_SNode, _ItemId] ->
{result, []}; {result, []};
[SNode] -> [SNode] ->
Node = string_to_node(SNode), Node = string_to_node(SNode),
- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) ->
- NodeItems = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - NodeItems = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of
+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) ->
+ Owners = node_owners_call(Type, Idx), + Owners = node_owners_call(Type, Nidx),
+ {NodeItems, RsmOut} = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners, RSM) of + {NodeItems, RsmOut} = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, RSM) of
{result, R} -> R; {result, R} -> R;
- _ -> [] - _ -> []
+ _ -> {[], none} + _ -> {[], none}
end, end,
Nodes = lists:map( Nodes = lists:map(
fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> fun(#pubsub_node{id = {_, SubNode}, options = SubOptions}) ->
@@ -1202,7 +1020,7 @@ @@ -1205,7 +1019,7 @@
{result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]),
#xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('name', Name)]} #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('name', Name)]}
end, NodeItems), end, NodeItems),
@ -432,30 +434,29 @@
end, end,
case transaction(Host, Node, Action, sync_dirty) of case transaction(Host, Node, Action, sync_dirty) of
{result, {_, Result}} -> {result, Result}; {result, {_, Result}} -> {result, Result};
@@ -1210,12 +1028,6 @@ @@ -1213,12 +1027,6 @@
end end
end. end.
-get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) -> -get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) ->
- AccessModel = get_option(Options, access_model), - AccessModel = get_option(Options, access_model),
- AllowedGroups = get_option(Options, roster_groups_allowed, []), - AllowedGroups = get_option(Options, roster_groups_allowed, []),
- {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), - {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups),
- node_call(Type, get_items, [NodeIdx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]). - node_call(Type, get_items, [Nidx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]).
- -
get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) -> get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) ->
if (AccessModel == presence) or (AccessModel == roster) -> if (AccessModel == presence) or (AccessModel == roster) ->
case Host of case Host of
@@ -1333,7 +1145,8 @@ @@ -1336,7 +1144,7 @@
(_, Acc) -> (_, Acc) ->
Acc Acc
end, [], exmpp_xml:remove_cdata_from_list(Els)), end, [], exmpp_xml:remove_cdata_from_list(Els)),
- get_items(Host, Node, From, SubId, MaxItems, ItemIDs); - get_items(Host, Node, From, SubId, MaxItems, ItemIds);
+ RSM = jlib:rsm_decode(SubEl), + get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(SubEl));
+ get_items(Host, Node, From, SubId, MaxItems, ItemIDs, RSM);
{get, 'subscriptions'} -> {get, 'subscriptions'} ->
get_subscriptions(Host, Node, From, Plugins); get_subscriptions(Host, Node, From, Plugins);
{get, 'affiliations'} -> {get, 'affiliations'} ->
@@ -1490,7 +1303,8 @@ @@ -1493,7 +1301,8 @@
_ -> [] _ -> []
end end
end, end,
@ -465,36 +466,36 @@
sync_dirty) of sync_dirty) of
{result, Res} -> Res; {result, Res} -> Res;
Err -> Err Err -> Err
@@ -1534,7 +1348,7 @@ @@ -1537,7 +1346,7 @@
%%% authorization handling %%% authorization handling
-send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, Subscriber) -> -send_authorization_request(#pubsub_node{owners = Owners, id = {Host, Node}}, Subscriber) ->
+send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = NodeId}, Subscriber) -> +send_authorization_request(#pubsub_node{id = {Host, Node}, type = Type, idx = Nidx}, Subscriber) ->
Lang = <<"en">>, %% TODO fix Lang = <<"en">>, %% TODO fix
{U, S, R} = Subscriber, {U, S, R} = Subscriber,
Stanza = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children = Stanza = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children =
@@ -1564,7 +1378,7 @@ @@ -1567,7 +1376,7 @@
lists:foreach(fun(Owner) -> lists:foreach(fun(Owner) ->
{U, S, R} = Owner, {U, S, R} = Owner,
ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza) ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza)
- end, Owners). - end, Owners).
+ end, node_owners(Host, Type, NodeId)). + end, node_owners(Host, Type, Nidx)).
find_authorization_response(Packet) -> find_authorization_response(Packet) ->
Els = Packet#xmlel.children, Els = Packet#xmlel.children,
@@ -1623,8 +1437,8 @@ @@ -1626,8 +1435,8 @@
"true" -> true; "true" -> true;
_ -> false _ -> false
end, end,
- Action = fun(#pubsub_node{type = Type, owners = Owners, id = NodeId}) -> - Action = fun(#pubsub_node{type = Type, owners = Owners, idx = Nidx}) ->
- IsApprover = lists:member(jlib:short_prepd_bare_jid(From), Owners), - IsApprover = lists:member(jlib:short_prepd_bare_jid(From), Owners),
+ Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) ->
+ IsApprover = lists:member(jlib:short_prepd_bare_jid(From), node_owners_call(Type, NodeId)), + IsApprover = lists:member(jlib:short_prepd_bare_jid(From), node_owners_call(Type, Nidx)),
{result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), {result, Subscriptions} = node_call(Type, get_subscriptions, [Nidx, Subscriber]),
if if
not IsApprover -> not IsApprover ->
@@ -1823,7 +1637,7 @@ @@ -1826,7 +1635,7 @@
end, end,
Reply = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = Reply = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
[#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(Node)}]}, [#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(Node)}]},
@ -503,7 +504,7 @@
{result, {NodeId, SubsByDepth, {Result, broadcast}}} -> {result, {NodeId, SubsByDepth, {Result, broadcast}}} ->
broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth), broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth),
case Result of case Result of
@@ -1927,7 +1741,7 @@ @@ -1930,7 +1739,7 @@
%%<li>The node does not exist.</li> %%<li>The node does not exist.</li>
%%</ul> %%</ul>
subscribe_node(Host, Node, From, JID, Configuration) -> subscribe_node(Host, Node, From, JID, Configuration) ->
@ -512,50 +513,50 @@
{result, GoodSubOpts} -> GoodSubOpts; {result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid _ -> invalid
end, end,
@@ -1937,7 +1751,7 @@ @@ -1940,7 +1749,7 @@
_:_ -> _:_ ->
{undefined, undefined, undefined} {undefined, undefined, undefined}
end, end,
- Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId}) -> - Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, idx = Nidx}) ->
+ Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) ->
Features = features(Type), Features = features(Type),
SubscribeFeature = lists:member("subscribe", Features), SubscribeFeature = lists:member("subscribe", Features),
OptionsFeature = lists:member("subscription-options", Features), OptionsFeature = lists:member("subscription-options", Features),
@@ -1946,6 +1760,7 @@ @@ -1949,6 +1758,7 @@
AccessModel = get_option(Options, access_model), AccessModel = get_option(Options, access_model),
SendLast = get_option(Options, send_last_published_item), SendLast = get_option(Options, send_last_published_item),
AllowedGroups = get_option(Options, roster_groups_allowed, []), AllowedGroups = get_option(Options, roster_groups_allowed, []),
+ Owners = node_owners_call(Type, NodeId), + Owners = node_owners_call(Type, Nidx),
{PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups),
if if
not SubscribeFeature -> not SubscribeFeature ->
@@ -2290,7 +2105,7 @@ @@ -2293,7 +2103,7 @@
%% <p>The permission are not checked in this function.</p> %% <p>The permission are not checked in this function.</p>
%% @todo We probably need to check that the user doing the query has the right %% @todo We probably need to check that the user doing the query has the right
%% to read the items. %% to read the items.
-get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> -get_items(Host, Node, From, SubId, SMaxItems, ItemIds) ->
+get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> +get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) ->
MaxItems = MaxItems =
if if
SMaxItems == "" -> get_max_items_node(Host); SMaxItems == "" -> get_max_items_node(Host);
@@ -2304,12 +2119,13 @@ @@ -2307,12 +2117,13 @@
{error, Error} -> {error, Error} ->
{error, Error}; {error, Error};
_ -> _ ->
- Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId, owners = Owners}) -> - Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx, owners = Owners}) ->
+ Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) ->
Features = features(Type), Features = features(Type),
RetreiveFeature = lists:member("retrieve-items", Features), RetreiveFeature = lists:member("retrieve-items", Features),
PersistentFeature = lists:member("persistent-items", Features), PersistentFeature = lists:member("persistent-items", Features),
AccessModel = get_option(Options, access_model), AccessModel = get_option(Options, access_model),
AllowedGroups = get_option(Options, roster_groups_allowed, []), AllowedGroups = get_option(Options, roster_groups_allowed, []),
+ Owners = node_owners_call(Type, NodeId), + Owners = node_owners_call(Type, Nidx),
{PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups),
if if
not RetreiveFeature -> not RetreiveFeature ->
@@ -2322,11 +2138,11 @@ @@ -2325,11 +2136,11 @@
node_call(Type, get_items, node_call(Type, get_items,
[NodeId, From, [Nidx, From,
AccessModel, PresenceSubscription, RosterGroup, AccessModel, PresenceSubscription, RosterGroup,
- SubId]) - SubId])
+ SubId, RSM]) + SubId, RSM])
@ -564,10 +565,10 @@
case transaction(Host, Node, Action, sync_dirty) of case transaction(Host, Node, Action, sync_dirty) of
- {result, {_, Items}} -> - {result, {_, Items}} ->
+ {result, {_, Items, RSMOut}} -> + {result, {_, Items, RSMOut}} ->
SendItems = case ItemIDs of SendItems = case ItemIds of
[] -> [] ->
Items; Items;
@@ -2339,7 +2155,7 @@ @@ -2342,7 +2153,7 @@
%% number of items sent to MaxItems: %% number of items sent to MaxItems:
{result, #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = {result, #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children =
[#xmlel{ns = ?NS_PUBSUB, name = 'items', attrs = nodeAttr(Node), children = [#xmlel{ns = ?NS_PUBSUB, name = 'items', attrs = nodeAttr(Node), children =
@ -576,7 +577,7 @@
Error -> Error ->
Error Error
end end
@@ -2360,6 +2176,17 @@ @@ -2365,6 +2176,17 @@
{result, {_, Items}} -> Items; {result, {_, Items}} -> Items;
Error -> Error Error -> Error
end. end.
@ -594,7 +595,7 @@
%% @spec (Host, Node, NodeId, Type, LJID, Number) -> any() %% @spec (Host, Node, NodeId, Type, LJID, Number) -> any()
%% Host = pubsubHost() %% Host = pubsubHost()
@@ -2371,16 +2198,29 @@ @@ -2376,16 +2198,29 @@
%% @doc <p>Resend the items of a node to the user.</p> %% @doc <p>Resend the items of a node to the user.</p>
%% @todo use cache-last-item feature %% @todo use cache-last-item feature
send_items(Host, Node, NodeId, Type, LJID, last) -> send_items(Host, Node, NodeId, Type, LJID, last) ->
@ -630,21 +631,21 @@
send_items(Host, Node, NodeId, Type, {LU, LS, LR} = LJID, Number) -> send_items(Host, Node, NodeId, Type, {LU, LS, LR} = LJID, Number) ->
ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of
{result, []} -> {result, []} ->
@@ -2507,7 +2347,8 @@ @@ -2512,7 +2347,8 @@
error -> error ->
{error, 'bad-request'}; {error, 'bad-request'};
_ -> _ ->
- Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}=N) -> - Action = fun(#pubsub_node{owners = Owners, type = Type, idx = Nidx}=N) ->
+ Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) ->
+ Owners = node_owners_call(Type, NodeId), + Owners = node_owners_call(Type, Nidx),
case lists:member(Owner, Owners) of case lists:member(Owner, Owners) of
true -> true ->
OwnerJID = exmpp_jid:make(Owner), OwnerJID = exmpp_jid:make(Owner),
@@ -2517,24 +2358,8 @@ @@ -2522,24 +2358,8 @@
end, end,
lists:foreach( lists:foreach(
fun({JID, Affiliation}) -> fun({JID, Affiliation}) ->
- {result, _} = node_call(Type, set_affiliation, [NodeId, JID, Affiliation]), - {result, _} = node_call(Type, set_affiliation, [Nidx, JID, Affiliation]),
- case Affiliation of - case Affiliation of
- owner -> - owner ->
- NewOwner = jlib:short_prepd_bare_jid(JID), - NewOwner = jlib:short_prepd_bare_jid(JID),
@ -663,16 +664,16 @@
- ok - ok
- end - end
+ % TODO, check if nothing missing here about new owners + % TODO, check if nothing missing here about new owners
+ node_call(Type, set_affiliation, [NodeId, JID, Affiliation]) + node_call(Type, set_affiliation, [Nidx, JID, Affiliation])
end, FilteredEntities), end, FilteredEntities),
{result, []}; {result, []};
_ -> _ ->
@@ -2589,11 +2414,11 @@ @@ -2594,11 +2414,11 @@
end. end.
read_sub(Subscriber, Node, NodeID, SubID, Lang) -> read_sub(Subscriber, Node, NodeId, SubId, Lang) ->
- case pubsub_subscription:get_subscription(Subscriber, NodeID, SubID) of - case pubsub_subscription:get_subscription(Subscriber, NodeId, SubId) of
+ case pubsub_subscription_odbc:get_subscription(Subscriber, NodeID, SubID) of + case pubsub_subscription_odbc:get_subscription(Subscriber, NodeId, SubId) of
{error, notfound} -> {error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")}; {error, extended_error('not-acceptable', "invalid-subid")};
{result, #pubsub_subscription{options = Options}} -> {result, #pubsub_subscription{options = Options}} ->
@ -680,37 +681,37 @@
+ {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options), + {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options),
OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options', OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options',
attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)), attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)),
?XMLATTR('subid', SubID) | nodeAttr(Node)], ?XMLATTR('subid', SubId) | nodeAttr(Node)],
@@ -2620,7 +2445,7 @@ @@ -2625,7 +2445,7 @@
end. end.
set_options_helper(Configuration, JID, NodeID, SubID, Type) -> set_options_helper(Configuration, JID, NodeId, SubId, Type) ->
- SubOpts = case pubsub_subscription:parse_options_xform(Configuration) of - SubOpts = case pubsub_subscription:parse_options_xform(Configuration) of
+ SubOpts = case pubsub_subscription_odbc:parse_options_xform(Configuration) of + SubOpts = case pubsub_subscription_odbc:parse_options_xform(Configuration) of
{result, GoodSubOpts} -> GoodSubOpts; {result, GoodSubOpts} -> GoodSubOpts;
_ -> invalid _ -> invalid
end, end,
@@ -2650,7 +2475,7 @@ @@ -2655,7 +2475,7 @@
write_sub(_Subscriber, _NodeID, _SubID, invalid) -> write_sub(_Subscriber, _NodeId, _SubId, invalid) ->
{error, extended_error('bad-request', "invalid-options")}; {error, extended_error('bad-request', "invalid-options")};
write_sub(Subscriber, NodeID, SubID, Options) -> write_sub(Subscriber, NodeId, SubId, Options) ->
- case pubsub_subscription:set_subscription(Subscriber, NodeID, SubID, Options) of - case pubsub_subscription:set_subscription(Subscriber, NodeId, SubId, Options) of
+ case pubsub_subscription_odbc:set_subscription(Subscriber, NodeID, SubID, Options) of + case pubsub_subscription_odbc:set_subscription(Subscriber, NodeId, SubId, Options) of
{error, notfound} -> {error, notfound} ->
{error, extended_error('not-acceptable', "invalid-subid")}; {error, extended_error('not-acceptable', "invalid-subid")};
{result, _} -> {result, _} ->
@@ -2824,8 +2649,8 @@ @@ -2829,8 +2649,8 @@
?XMLATTR('subsription', subscription_to_string(Sub)) | nodeAttr(Node)]}]}]}, ?XMLATTR('subsription', subscription_to_string(Sub)) | nodeAttr(Node)]}]}]},
ejabberd_router:route(service_jid(Host), JID, Stanza) ejabberd_router:route(service_jid(Host), JID, Stanza)
end, end,
- Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}) -> - Action = fun(#pubsub_node{owners = Owners, type = Type, idx = Nidx}) ->
- case lists:member(Owner, Owners) of - case lists:member(Owner, Owners) of
+ Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) ->
+ case lists:member(Owner, node_owners_call(Type, NodeId)) of + case lists:member(Owner, node_owners_call(Type, Nidx)) of
true -> true ->
Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) ->
@@ -3174,7 +2999,7 @@ @@ -3179,7 +2999,7 @@
{Depth, [{N, get_node_subs(N)} || N <- Nodes]} {Depth, [{N, get_node_subs(N)} || N <- Nodes]}
end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))} end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))}
end, end,
@ -719,19 +720,16 @@
{result, CollSubs} -> CollSubs; {result, CollSubs} -> CollSubs;
_ -> [] _ -> []
end. end.
@@ -3188,9 +3013,9 @@ @@ -3192,7 +3012,7 @@
get_options_for_subs(NodeID, Subs) -> get_options_for_subs(Nidx, Subs) ->
lists:foldl(fun({JID, subscribed, SubID}, Acc) -> lists:foldl(fun({JID, subscribed, SubId}, Acc) ->
- case pubsub_subscription:read_subscription(JID, NodeID, SubID) of - case pubsub_subscription:read_subscription(JID, Nidx, SubId) of
+ case pubsub_subscription_odbc:get_subscription(JID, NodeID, SubID) of + case pubsub_subscription_odbc:read_subscription(JID, Nidx, SubId) of
{error, notfound} -> [{JID, SubID, []} | Acc]; {error, notfound} -> [{JID, SubId, []} | Acc];
- #pubsub_subscription{options = Options} -> [{JID, SubID, Options} | Acc]; #pubsub_subscription{options = Options} -> [{JID, SubId, Options} | Acc];
+ {result, #pubsub_subscription{options = Options}} -> [{JID, SubID, Options} | Acc];
_ -> Acc _ -> Acc
end; @@ -3416,6 +3236,30 @@
(_, Acc) ->
@@ -3412,6 +3237,30 @@
Result Result
end. end.
@ -762,7 +760,7 @@
%% @spec (Host, Options) -> MaxItems %% @spec (Host, Options) -> MaxItems
%% Host = host() %% Host = host()
%% Options = [Option] %% Options = [Option]
@@ -3815,7 +3664,13 @@ @@ -3819,7 +3663,13 @@
tree_action(Host, Function, Args) -> tree_action(Host, Function, Args) ->
?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]), ?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]),
Fun = fun() -> tree_call(Host, Function, Args) end, Fun = fun() -> tree_call(Host, Function, Args) end,
@ -777,7 +775,7 @@
%% @doc <p>node plugin call.</p> %% @doc <p>node plugin call.</p>
node_call(Type, Function, Args) -> node_call(Type, Function, Args) ->
@@ -3835,13 +3690,13 @@ @@ -3839,13 +3689,13 @@
node_action(Host, Type, Function, Args) -> node_action(Host, Type, Function, Args) ->
?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]), ?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]),
@ -793,7 +791,7 @@
case tree_call(Host, get_node, [Host, Node]) of case tree_call(Host, get_node, [Host, Node]) of
N when is_record(N, pubsub_node) -> N when is_record(N, pubsub_node) ->
case Action(N) of case Action(N) of
@@ -3854,13 +3709,20 @@ @@ -3858,13 +3708,20 @@
end end
end, Trans). end, Trans).
@ -818,7 +816,7 @@
{result, Result} -> {result, Result}; {result, Result} -> {result, Result};
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{atomic, {result, Result}} -> {result, Result}; {atomic, {result, Result}} -> {result, Result};
@@ -3868,6 +3730,15 @@ @@ -3872,6 +3729,15 @@
{aborted, Reason} -> {aborted, Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]),
{error, 'internal-server-error'}; {error, 'internal-server-error'};
@ -834,7 +832,7 @@
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]),
{error, 'internal-server-error'}; {error, 'internal-server-error'};
@@ -3876,6 +3747,16 @@ @@ -3880,6 +3746,16 @@
{error, 'internal-server-error'} {error, 'internal-server-error'}
end. end.

View File

@ -89,36 +89,36 @@
init() -> init() ->
ok = create_table(). ok = create_table().
subscribe_node(JID, NodeID, Options) -> subscribe_node(JID, NodeId, Options) ->
try mnesia:sync_dirty(fun add_subscription/3, try mnesia:sync_dirty(fun add_subscription/3,
[JID, NodeID, Options]) of [JID, NodeId, Options]) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
Result -> {result, Result} Result -> {result, Result}
catch catch
Error -> Error Error -> Error
end. end.
unsubscribe_node(JID, NodeID, SubID) -> unsubscribe_node(JID, NodeId, SubId) ->
try mnesia:sync_dirty(fun delete_subscription/3, try mnesia:sync_dirty(fun delete_subscription/3,
[JID, NodeID, SubID]) of [JID, NodeId, SubId]) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
Result -> {result, Result} Result -> {result, Result}
catch catch
Error -> Error Error -> Error
end. end.
get_subscription(JID, NodeID, SubID) -> get_subscription(JID, NodeId, SubId) ->
try mnesia:sync_dirty(fun read_subscription/3, try mnesia:sync_dirty(fun read_subscription/3,
[JID, NodeID, SubID]) of [JID, NodeId, SubId]) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
Result -> {result, Result} Result -> {result, Result}
catch catch
Error -> Error Error -> Error
end. end.
set_subscription(JID, NodeID, SubID, Options) -> set_subscription(JID, NodeId, SubId, Options) ->
try mnesia:sync_dirty(fun write_subscription/4, try mnesia:sync_dirty(fun write_subscription/4,
[JID, NodeID, SubID, Options]) of [JID, NodeId, SubId, Options]) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
Result -> {result, Result} Result -> {result, Result}
catch catch
@ -170,22 +170,22 @@ create_table() ->
Other -> Other Other -> Other
end. end.
add_subscription(_JID, _NodeID, Options) -> add_subscription(_JID, _NodeId, Options) ->
SubID = make_subid(), SubId = make_subid(),
mnesia:write(#pubsub_subscription{subid = SubID, options = Options}), mnesia:write(#pubsub_subscription{subid = SubId, options = Options}),
SubID. SubId.
delete_subscription(_JID, _NodeID, SubID) -> delete_subscription(_JID, _NodeId, SubId) ->
mnesia:delete({pubsub_subscription, SubID}). mnesia:delete({pubsub_subscription, SubId}).
read_subscription(_JID, _NodeID, SubID) -> read_subscription(_JID, _NodeId, SubId) ->
case mnesia:read({pubsub_subscription, SubID}) of case mnesia:read({pubsub_subscription, SubId}) of
[Sub] -> Sub; [Sub] -> Sub;
_ -> {error, notfound} _ -> {error, notfound}
end. end.
write_subscription(JID, NodeID, SubID, Options) -> write_subscription(JID, NodeId, SubId, Options) ->
case read_subscription(JID, NodeID, SubID) of case read_subscription(JID, NodeId, SubId) of
{error, notfound} -> {error, notfound}; {error, notfound} -> {error, notfound};
Sub -> mnesia:write(Sub#pubsub_subscription{options = Options}) Sub -> mnesia:write(Sub#pubsub_subscription{options = Options})
end. end.

View File

@ -89,33 +89,33 @@
init() -> init() ->
ok = create_table(). ok = create_table().
subscribe_node(_JID, _NodeID, Options) -> subscribe_node(_JID, _Nidx, Options) ->
SubID = make_subid(), SubId = make_subid(),
?DB_MOD:add_subscription(#pubsub_subscription{subid = SubID, options = Options}), ?DB_MOD:add_subscription(#pubsub_subscription{subid = SubId, options = Options}),
{result, SubID}. {result, SubId}.
unsubscribe_node(_JID, _NodeID, SubID) -> unsubscribe_node(_JID, _Nidx, SubId) ->
case ?DB_MOD:read_subscription(SubID) of case ?DB_MOD:read_subscription(SubId) of
{ok, Sub} -> {ok, Sub} ->
?DB_MOD:delete_subscription(SubID), ?DB_MOD:delete_subscription(SubId),
{result, Sub}; {result, Sub};
notfound -> notfound ->
{error, notfound} {error, notfound}
end. end.
get_subscription(_JID, _NodeID, SubID) -> get_subscription(_JID, _Nidx, SubId) ->
case ?DB_MOD:read_subscription(SubID) of case ?DB_MOD:read_subscription(SubId) of
{ok, Sub} -> {result, Sub}; {ok, Sub} -> {result, Sub};
notfound -> {error, notfound} notfound -> {error, notfound}
end. end.
set_subscription(_JID, _NodeID, SubID, Options) -> set_subscription(_JID, _Nidx, SubId, Options) ->
case ?DB_MOD:read_subscription(SubID) of case ?DB_MOD:read_subscription(SubId) of
{ok, _} -> {ok, _} ->
?DB_MOD:update_subscription(#pubsub_subscription{subid = SubID, options = Options}), ?DB_MOD:update_subscription(#pubsub_subscription{subid = SubId, options = Options}),
{result, ok}; {result, ok};
notfound -> notfound ->
?DB_MOD:add_subscription(#pubsub_subscription{subid = SubID, options = Options}), ?DB_MOD:add_subscription(#pubsub_subscription{subid = SubId, options = Options}),
{result, ok} {result, ok}
end. end.