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

backport pubsub/pep/caps optimizations from trunk

SVN Revision: 2052
This commit is contained in:
Christophe Romain 2009-04-30 23:17:38 +00:00
parent 3debaf99d8
commit ced30acb20
19 changed files with 1374 additions and 1208 deletions

View File

@ -1,3 +1,24 @@
2009-04-30 Christophe Romain <christophe.romain@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: API change for major optimization
* src/mod_pubsub/pubsub.hrl: Likewise
* src/mod_pubsub/nodetree_default.erl: Likewise
* src/mod_pubsub/nodetree_virtual.erl: Likewise
* src/mod_pubsub/node_mb.erl: Likewise
* src/mod_pubsub/node_dispatch.erl: Likewise
* src/mod_pubsub/node_buddy.erl: Likewise
* src/mod_pubsub/node_private.erl: Likewise
* src/mod_pubsub/node_public.erl: Likewise
* src/mod_pubsub/node_default.erl: Likewise
* src/mod_pubsub/node_pep.erl: Likewise
* src/mod_pubsub/node_club.erl: Likewise
* src/mod_pubsub/node_flat.erl: Likewise
* src/mod_pubsub/node.template: Likewise
* src/mod_pubsub/gen_pubsub_node.erl: Likewise
* src/mod_pubsub/gen_pubsub_nodetree.erl: Likewise
* src/mod_caps.erl: Reduce memory consumption and remove mnesia table
2009-04-28 Badlop <badlop@process-one.net> 2009-04-28 Badlop <badlop@process-one.net>
* src/ejabberd_hooks.erl: Support distributed hooks (EJAB-829) * src/ejabberd_hooks.erl: Support distributed hooks (EJAB-829)

View File

@ -22,6 +22,8 @@
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA %%% 02111-1307 USA
%%% %%%
%%% 2009, improvements from Process-One to support correct PEP handling
%%% through s2s, use less memory, and speedup global caps handling
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
-module(mod_caps). -module(mod_caps).
@ -64,7 +66,7 @@
-define(CAPS_QUERY_TIMEOUT, 60000). % 1mn without answer, consider client never answer -define(CAPS_QUERY_TIMEOUT, 60000). % 1mn without answer, consider client never answer
-record(caps, {node, version, exts}). -record(caps, {node, version, exts}).
-record(caps_features, {node_pair, features}). -record(caps_features, {node_pair, features = []}).
-record(user_caps, {jid, caps}). -record(user_caps, {jid, caps}).
-record(user_caps_resources, {uid, resource}). -record(user_caps_resources, {uid, resource}).
-record(state, {host, -record(state, {host,
@ -190,19 +192,32 @@ receive_packet(_, _, _) ->
receive_packet(_JID, From, To, Packet) -> receive_packet(_JID, From, To, Packet) ->
receive_packet(From, To, Packet). receive_packet(From, To, Packet).
jid_to_binary(JID) ->
list_to_binary(jlib:jid_to_string(JID)).
caps_to_binary(#caps{node = Node, version = Version, exts = Exts}) ->
BExts = [list_to_binary(Ext) || Ext <- Exts],
#caps{node = list_to_binary(Node), version = list_to_binary(Version), exts = BExts}.
node_to_binary(Node, SubNode) ->
{list_to_binary(Node), list_to_binary(SubNode)}.
features_to_binary(L) -> [list_to_binary(I) || I <- L].
binary_to_features(L) -> [binary_to_list(I) || I <- L].
%%==================================================================== %%====================================================================
%% gen_server callbacks %% gen_server callbacks
%%==================================================================== %%====================================================================
init([Host, _Opts]) -> init([Host, _Opts]) ->
mnesia:create_table(caps_features, mnesia:create_table(caps_features,
[{ram_copies, [node()]}, [{disc_copies, [node()]},
{attributes, record_info(fields, caps_features)}]), {attributes, record_info(fields, caps_features)}]),
mnesia:create_table(user_caps, mnesia:create_table(user_caps,
[{disc_copies, [node()]}, [{ram_copies, [node()]},
{attributes, record_info(fields, user_caps)}]), {attributes, record_info(fields, user_caps)}]),
mnesia:create_table(user_caps_resources, mnesia:create_table(user_caps_resources,
[{disc_copies, [node()]}, [{ram_copies, [node()]},
{type, bag}, {type, bag},
{attributes, record_info(fields, user_caps_resources)}]), {attributes, record_info(fields, user_caps_resources)}]),
mnesia:delete_table(user_caps_default), mnesia:delete_table(user_caps_default),
@ -214,26 +229,21 @@ init([Host, _Opts]) ->
maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) -> maybe_get_features(#caps{node = Node, version = Version, exts = Exts}) ->
SubNodes = [Version | Exts], SubNodes = [Version | Exts],
F = fun() ->
%% Make sure that we have all nodes we need to know. %% Make sure that we have all nodes we need to know.
%% If a single one is missing, we wait for more disco %% If a single one is missing, we wait for more disco
%% responses. %% responses.
lists:foldl(fun(SubNode, Acc) -> case lists:foldl(fun(SubNode, Acc) ->
case Acc of case Acc of
fail -> fail; fail -> fail;
_ -> _ ->
case mnesia:read({caps_features, {Node, SubNode}}) of case mnesia:dirty_read({caps_features, {Node, SubNode}}) of
[] -> fail; [] -> fail;
[#caps_features{features = Features}] -> Features ++ Acc [#caps_features{features = Features}] -> Features ++ Acc %% TODO binary
end end
end end
end, [], SubNodes) end, [], SubNodes) of
end, fail -> wait;
case mnesia:transaction(F) of Features -> {ok, Features}
{atomic, fail} ->
wait;
{atomic, Features} ->
{ok, Features}
end. end.
timestamp() -> timestamp() ->
@ -243,7 +253,7 @@ timestamp() ->
handle_call({get_features, Caps}, From, State) -> handle_call({get_features, Caps}, From, State) ->
case maybe_get_features(Caps) of case maybe_get_features(Caps) of
{ok, Features} -> {ok, Features} ->
{reply, Features, State}; {reply, binary_to_features(Features), State};
wait -> wait ->
gen_server:cast(self(), visit_feature_queries), gen_server:cast(self(), visit_feature_queries),
Timeout = timestamp() + 10, Timeout = timestamp() + 10,
@ -266,7 +276,7 @@ handle_cast({note_caps, From,
S = exmpp_jid:ldomain(From), S = exmpp_jid:ldomain(From),
R = exmpp_jid:resource(From), R = exmpp_jid:resource(From),
BJID = exmpp_jid:jid_to_binary(From), BJID = exmpp_jid:jid_to_binary(From),
mnesia:dirty_write(#user_caps{jid = BJID, caps = Caps}), mnesia:dirty_write(#user_caps{jid = BJID, caps = caps_to_binary(Caps)}),
case ejabberd_sm:get_user_resources(U, S) of case ejabberd_sm:get_user_resources(U, S) of
[] -> [] ->
% only store resource of caps aware external contacts % only store resource of caps aware external contacts
@ -275,20 +285,19 @@ handle_cast({note_caps, From,
_ -> _ ->
ok ok
end, end,
SubNodes = [Version | Exts],
%% Now, find which of these are not already in the database. %% Now, find which of these are not already in the database.
Fun = fun() -> SubNodes = [Version | Exts],
lists:foldl(fun(SubNode, Acc) -> case lists:foldl(fun(SubNode, Acc) ->
case mnesia:read({caps_features, {Node, SubNode}}) of case mnesia:dirty_read({caps_features, {Node, SubNode}}) of
[] -> [] ->
[SubNode | Acc]; [SubNode | Acc];
_ -> _ ->
Acc Acc
end end
end, [], SubNodes) end, [], SubNodes) of
end, [] ->
case mnesia:transaction(Fun) of {noreply, State};
{atomic, Missing} -> Missing ->
%% For each unknown caps "subnode", we send a disco request. %% For each unknown caps "subnode", we send a disco request.
NewRequests = lists:foldl( NewRequests = lists:foldl(
fun(SubNode, Dict) -> fun(SubNode, Dict) ->
@ -302,30 +311,23 @@ handle_cast({note_caps, From,
ejabberd_router:route(exmpp_jid:make_jid(Host), ejabberd_router:route(exmpp_jid:make_jid(Host),
From, Stanza), From, Stanza),
timer:send_after(?CAPS_QUERY_TIMEOUT, self(), {disco_timeout, ID}), timer:send_after(?CAPS_QUERY_TIMEOUT, self(), {disco_timeout, ID}),
?DICT:store(ID, {Node, SubNode}, Dict) ?DICT:store(ID, node_to_binary(Node, SubNode), Dict)
end, Requests, Missing), end, Requests, Missing),
{noreply, State#state{disco_requests = NewRequests}}; {noreply, State#state{disco_requests = NewRequests}}
Error ->
?ERROR_MSG("Transaction failed: ~p", [Error]),
{noreply, State}
end; end;
handle_cast({disco_response, From, _To, #iq{id = ID, type = Type, payload = Payload}}, handle_cast({disco_response, From, _To, #iq{id = ID, type = Type, payload = Payload}},
#state{disco_requests = Requests} = State) -> #state{disco_requests = Requests} = State) ->
case {Type, Payload} of case {Type, Payload} of
{result, #xmlel{name = 'query', children = Els}} -> {result, #xmlel{name = 'query', children = Els}} ->
case ?DICT:find(ID, Requests) of case ?DICT:find(ID, Requests) of
{ok, {Node, SubNode}} -> {ok, BinaryNode} ->
Features = Features =
lists:flatmap(fun(#xmlel{name = 'feature'} = F) -> lists:flatmap(fun(#xmlel{name = 'feature'} = F) ->
[exmpp_xml:get_attribute_as_list(F, 'var', "")]; [exmpp_xml:get_attribute_as_list(F, 'var', "")];
(_) -> (_) ->
[] []
end, Els), end, Els),
mnesia:transaction( mnesia:dirty_write(#caps_features{node_pair = BinaryNode, features = features_to_binary(Features)}),
fun() ->
mnesia:write(#caps_features{node_pair = {Node, SubNode},
features = Features})
end),
gen_server:cast(self(), visit_feature_queries); gen_server:cast(self(), visit_feature_queries);
error -> error ->
?ERROR_MSG("ID '~s' matches no query", [ID]) ?ERROR_MSG("ID '~s' matches no query", [ID])
@ -333,13 +335,8 @@ handle_cast({disco_response, From, _To, #iq{id = ID, type = Type, payload = Payl
{error, _} -> {error, _} ->
%% XXX: if we get error, we cache empty feature not to probe the client continuously %% XXX: if we get error, we cache empty feature not to probe the client continuously
case ?DICT:find(ID, Requests) of case ?DICT:find(ID, Requests) of
{ok, {Node, SubNode}} -> {ok, BinaryNode} ->
Features = [], mnesia:dirty_write(#caps_features{node_pair = BinaryNode}),
mnesia:transaction(
fun() ->
mnesia:write(#caps_features{node_pair = {Node, SubNode},
features = Features})
end),
gen_server:cast(self(), visit_feature_queries); gen_server:cast(self(), visit_feature_queries);
error -> error ->
?ERROR_MSG("ID '~s' matches no query", [ID]) ?ERROR_MSG("ID '~s' matches no query", [ID])

View File

@ -43,29 +43,29 @@ behaviour_info(callbacks) ->
{options, 0}, {options, 0},
{features, 0}, {features, 0},
{create_node_permission, 6}, {create_node_permission, 6},
{create_node, 3}, {create_node, 2},
{delete_node, 2}, {delete_node, 1},
{purge_node, 3}, {purge_node, 2},
{subscribe_node, 8}, {subscribe_node, 7},
{unsubscribe_node, 5}, {unsubscribe_node, 4},
{publish_item, 7}, {publish_item, 6},
{delete_item, 4}, {delete_item, 3},
{remove_extra_items, 4}, {remove_extra_items, 3},
{get_node_affiliations, 2}, {get_node_affiliations, 1},
{get_entity_affiliations, 2}, {get_entity_affiliations, 2},
{get_affiliation, 3}, {get_affiliation, 2},
{set_affiliation, 4}, {set_affiliation, 3},
{get_node_subscriptions, 2}, {get_node_subscriptions, 1},
{get_entity_subscriptions, 2}, {get_entity_subscriptions, 2},
{get_subscription, 3}, {get_subscription, 2},
{set_subscription, 4}, {set_subscription, 3},
{get_states, 2}, {get_states, 1},
{get_state, 3}, {get_state, 2},
{set_state, 1}, {set_state, 1},
{get_items, 7}, {get_items, 6},
{get_items, 3}, {get_items, 2},
{get_item, 8}, {get_item, 7},
{get_item, 3}, {get_item, 2},
{set_item, 1}, {set_item, 1},
{get_item_name, 3} {get_item_name, 3}
]; ];

View File

@ -47,7 +47,7 @@ behaviour_info(callbacks) ->
{get_nodes, 2}, {get_nodes, 2},
{get_nodes, 1}, {get_nodes, 1},
{get_subnodes, 3}, {get_subnodes, 3},
{get_subnodes_tree, 2}, {get_subnodes_tree, 3},
{create_node, 5}, {create_node, 5},
{delete_node, 2} {delete_node, 2}
]; ];

File diff suppressed because it is too large Load Diff

View File

@ -41,29 +41,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1 set_item/1
]). ]).
@ -87,7 +87,7 @@ options() ->
{roster_groups_allowed, []}, {roster_groups_allowed, []},
{publish_model, publishers}, {publish_model, publishers},
{max_payload_size, ?MAX_PAYLOAD_SIZE}, {max_payload_size, ?MAX_PAYLOAD_SIZE},
{send_last_published_item, never}, {send_last_published_item, on_sub_and_presence},
{deliver_notifications, true}, {deliver_notifications, true},
{presence_based_delivery, false}]. {presence_based_delivery, false}].
@ -111,74 +111,74 @@ features() ->
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_default:get_entity_affiliations(Host, Owner). node_default:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_default:get_node_affiliations(Host, Node). node_default:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_default:get_affiliation(Host, Node, Owner). node_default:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_default:get_entity_subscriptions(Host, Owner). node_default:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_default:get_node_subscriptions(Host, Node). node_default:get_node_subscriptions(NodeId).
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
node_default:get_subscription(Host, Node, Owner). node_default:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId)
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -44,29 +44,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -116,74 +116,74 @@ features() ->
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_default:get_entity_affiliations(Host, Owner). node_default:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_default:get_node_affiliations(Host, Node). node_default:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_default:get_affiliation(Host, Node, Owner). node_default:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_default:get_entity_subscriptions(Host, Owner). node_default:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_default:get_node_subscriptions(Host, Node). node_default:get_node_subscriptions(NodeId).
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
node_default:get_subscription(Host, Node, Owner). node_default:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -44,29 +44,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -115,74 +115,74 @@ features() ->
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_default:get_entity_affiliations(Host, Owner). node_default:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_default:get_node_affiliations(Host, Node). node_default:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_default:get_affiliation(Host, Node, Owner). node_default:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_default:get_entity_subscriptions(Host, Owner). node_default:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_default:get_node_subscriptions(Host, Node). node_default:get_node_subscriptions(NodeId).
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
node_default:get_subscription(Host, Node, Owner). node_default:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -51,29 +51,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -193,8 +193,8 @@ features() ->
%% <p>PubSub plugins can redefine the PubSub node creation rights as they %% <p>PubSub plugins can redefine the PubSub node creation rights as they
%% which. They can simply delegate this check to the {@link node_default} %% which. They can simply delegate this check to the {@link node_default}
%% module by implementing this function like this: %% module by implementing this function like this:
%% ```check_create_user_permission(Host, Node, Owner, Access) -> %% ```check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
%% node_default:check_create_user_permission(Host, Node, Owner, Access).'''</p> %% node_default:check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access).'''</p>
create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
LOwner = jlib:short_prepd_jid(Owner), LOwner = jlib:short_prepd_jid(Owner),
{User, Server, _Resource} = LOwner, {User, Server, _Resource} = LOwner,
@ -215,35 +215,36 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
end, end,
{result, Allowed}. {result, Allowed}.
%% @spec (Host, Node, Owner) -> %% @spec (NodeId, Owner) ->
%% {result, Result} | exit %% {result, Result} | exit
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% Owner = mod_pubsub:jid() %% Owner = mod_pubsub:jid()
%% @doc <p></p> %% @doc <p></p>
create_node(Host, Node, 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, {Host, Node}}, affiliation = owner}), set_state(#pubsub_state{stateid = {OwnerKey, NodeId}, affiliation = owner}),
{result, {default, broadcast}}. {result, {default, broadcast}}.
%% @spec (Host, Removed) -> ok %% @spec (Removed) -> ok
%% Host = mod_pubsub:host()
%% Removed = [mod_pubsub:pubsubNode()] %% Removed = [mod_pubsub:pubsubNode()]
%% @doc <p>purge items of deleted nodes after effective deletion.</p> %% @doc <p>purge items of deleted nodes after effective deletion.</p>
delete_node(Host, Removed) -> delete_node(Removed) ->
lists:foreach( Tr = fun(#pubsub_state{stateid = {J, _}, subscription = S}) ->
fun(Node) -> {J, S}
lists:foreach(
fun(#pubsub_state{stateid = StateId, items = Items}) ->
del_items(Host, Node, Items),
del_state(StateId)
end, end,
mnesia:match_object( Reply = lists:map(
#pubsub_state{stateid = {'_', {Host, Node}}, _ = '_'})) fun(#pubsub_node{id = NodeId} = PubsubNode) ->
{result, States} = get_states(NodeId),
lists:foreach(
fun(#pubsub_state{stateid = {LJID, _}, items = Items}) ->
del_items(NodeId, Items),
del_state(NodeId, LJID)
end, States),
{PubsubNode, lists:map(Tr, States)}
end, Removed), end, Removed),
{result, {default, broadcast, Removed}}. {result, {default, broadcast, Reply}}.
%% @spec (Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> %% @spec (NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
%% {error, Reason} | {result, Result} %% {error, Reason} | {result, Result}
%% @doc <p>Accepts or rejects subcription requests on a PubSub node.</p> %% @doc <p>Accepts or rejects subcription requests on a PubSub node.</p>
%% <p>The mechanism works as follow: %% <p>The mechanism works as follow:
@ -276,17 +277,18 @@ delete_node(Host, Removed) ->
%% to completly disable persistance.</li></ul> %% to completly disable persistance.</li></ul>
%% </p> %% </p>
%% <p>In the default plugin module, the record is unchanged.</p> %% <p>In the default plugin module, the record is unchanged.</p>
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, subscribe_node(NodeId, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup) -> SendLast, PresenceSubscription, RosterGroup) ->
SubKey = jlib:short_prepd_jid(Subscriber), SubKey = jlib:short_prepd_jid(Subscriber),
GenKey = jlib:short_prepd_bare_jid(SubKey), GenKey = jlib:short_prepd_bare_jid(SubKey),
Authorized = (jlib:short_prepd_bare_jid(Sender) == GenKey), Authorized = (jlib:short_prepd_bare_jid(Sender) == GenKey),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
SubState = case SubKey of SubState = case SubKey of
GenKey -> GenState; GenKey -> GenState;
_ -> get_state(Host, Node, SubKey) _ -> get_state(NodeId, SubKey)
end, end,
Affiliation = GenState#pubsub_state.affiliation, Affiliation = GenState#pubsub_state.affiliation,
Subscription = SubState#pubsub_state.subscription,
Whitelisted = lists:member(Affiliation, [member, publisher, owner]), Whitelisted = lists:member(Affiliation, [member, publisher, owner]),
if if
not Authorized -> not Authorized ->
@ -295,7 +297,7 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel,
Affiliation == outcast -> Affiliation == outcast ->
%% Requesting entity is blocked %% Requesting entity is blocked
{error, 'forbidden'}; {error, 'forbidden'};
SubState#pubsub_state.subscription == pending -> Subscription == pending ->
%% Requesting entity has pending subscription %% Requesting entity has pending subscription
{error, ?ERR_EXTENDED('not-authorized', "pending-subscription")}; {error, ?ERR_EXTENDED('not-authorized', "pending-subscription")};
(AccessModel == presence) and (not PresenceSubscription) -> (AccessModel == presence) and (not PresenceSubscription) ->
@ -338,23 +340,22 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel,
end end
end. end.
%% @spec (Host, Node, Sender, Subscriber, SubID) -> %% @spec (NodeId, Sender, Subscriber, SubID) ->
%% {error, Reason} | {result, []} %% {error, Reason} | {result, []}
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% Sender = mod_pubsub:jid() %% Sender = mod_pubsub:jid()
%% Subscriber = mod_pubsub:jid() %% Subscriber = mod_pubsub:jid()
%% SubID = string() %% SubID = string()
%% 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>
unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) -> unsubscribe_node(NodeId, Sender, Subscriber, _SubId) ->
SubKey = jlib:short_prepd_jid(Subscriber), SubKey = jlib:short_prepd_jid(Subscriber),
GenKey = jlib:short_prepd_bare_jid(SubKey), GenKey = jlib:short_prepd_bare_jid(SubKey),
Authorized = (jlib:short_prepd_bare_jid(Sender) == GenKey), Authorized = (jlib:short_prepd_bare_jid(Sender) == GenKey),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
SubState = case SubKey of SubState = case SubKey of
GenKey -> GenState; GenKey -> GenState;
_ -> get_state(Host, Node, SubKey) _ -> get_state(NodeId, SubKey)
end, end,
if if
%% Requesting entity is prohibited from unsubscribing entity %% Requesting entity is prohibited from unsubscribing entity
@ -371,17 +372,16 @@ unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) ->
{error, ?ERR_EXTENDED('unexpected-request', "not-subscribed")}; {error, ?ERR_EXTENDED('unexpected-request', "not-subscribed")};
%% Was just subscriber, remove the record %% Was just subscriber, remove the record
SubState#pubsub_state.affiliation == none -> SubState#pubsub_state.affiliation == none ->
del_state(SubState#pubsub_state.stateid), del_state(NodeId, SubKey),
{result, default}; {result, default};
true -> true ->
set_state(SubState#pubsub_state{subscription = none}), set_state(SubState#pubsub_state{subscription = none}),
{result, default} {result, default}
end. end.
%% @spec (Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
%% {true, PubsubItem} | {result, Reply} %% {true, PubsubItem} | {result, Reply}
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% Publisher = mod_pubsub:jid() %% Publisher = mod_pubsub:jid()
%% PublishModel = atom() %% PublishModel = atom()
%% MaxItems = integer() %% MaxItems = integer()
@ -417,13 +417,13 @@ unsubscribe_node(Host, Node, Sender, Subscriber, _SubId) ->
%% to completly disable persistance.</li></ul> %% to completly disable persistance.</li></ul>
%% </p> %% </p>
%% <p>In the default plugin module, the record is unchanged.</p> %% <p>In the default plugin module, the record is unchanged.</p>
publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
SubKey = jlib:short_prepd_jid(Publisher), SubKey = jlib:short_prepd_jid(Publisher),
GenKey = jlib:short_prepd_bare_jid(SubKey), GenKey = jlib:short_prepd_bare_jid(SubKey),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
SubState = case SubKey of SubState = case SubKey of
GenKey -> GenState; GenKey -> GenState;
_ -> get_state(Host, Node, SubKey) _ -> get_state(NodeId, SubKey)
end, end,
Affiliation = GenState#pubsub_state.affiliation, Affiliation = GenState#pubsub_state.affiliation,
Subscription = SubState#pubsub_state.subscription, Subscription = SubState#pubsub_state.subscription,
@ -436,31 +436,31 @@ publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
%% Entity does not have sufficient privileges to publish to node %% Entity does not have sufficient privileges to publish to node
{error, 'forbidden'}; {error, 'forbidden'};
true -> true ->
PubId = {SubKey, now()}, %% TODO, uses {now(),PublisherKey} for sorting (EJAB-824)
%% TODO: check creation, presence, roster %% TODO: check creation, presence, roster
Item = case get_item(Host, Node, ItemId) of if MaxItems > 0 ->
PubId = {now(), SubKey},
Item = case get_item(NodeId, ItemId) of
{result, OldItem} -> {result, OldItem} ->
OldItem#pubsub_item{modification = PubId, OldItem#pubsub_item{modification = PubId,
payload = Payload}; payload = Payload};
_ -> _ ->
#pubsub_item{itemid = {ItemId, {Host, Node}}, #pubsub_item{itemid = {ItemId, NodeId},
creation = {GenKey, now()}, creation = {now(), GenKey},
modification = PubId, modification = PubId,
payload = Payload} payload = Payload}
end, end,
Items = [ItemId | GenState#pubsub_state.items--[ItemId]], Items = [ItemId | GenState#pubsub_state.items--[ItemId]],
{result, {NI, OI}} = remove_extra_items( {result, {NI, OI}} = remove_extra_items(NodeId, MaxItems, Items),
Host, Node, MaxItems, Items), set_item(Item),
if MaxItems > 0 -> set_item(Item);
true -> ok
end,
set_state(GenState#pubsub_state{items = NI}), set_state(GenState#pubsub_state{items = NI}),
{result, {default, broadcast, OI}} {result, {default, broadcast, OI}};
true ->
{result, {default, broadcast, []}}
end
end. end.
%% @spec (Host, Node, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} %% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds}
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% MaxItems = integer() | unlimited %% MaxItems = integer() | unlimited
%% ItemIds = [ItemId::string()] %% ItemIds = [ItemId::string()]
%% NewItemIds = [ItemId::string()] %% NewItemIds = [ItemId::string()]
@ -472,34 +472,33 @@ publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
%% rules can be used.</p> %% rules can be used.</p>
%% <p>If another PubSub plugin wants to delegate the item removal (and if the %% <p>If another PubSub plugin wants to delegate the item removal (and if the
%% plugin is using the default pubsub storage), it can implements this function like this: %% plugin is using the default pubsub storage), it can implements this function like this:
%% ```remove_extra_items(Host, Node, MaxItems, ItemIds) -> %% ```remove_extra_items(NodeId, MaxItems, ItemIds) ->
%% node_default:remove_extra_items(Host, Node, MaxItems, ItemIds).'''</p> %% node_default:remove_extra_items(NodeId, MaxItems, ItemIds).'''</p>
remove_extra_items(_Host, _Node, unlimited, ItemIds) -> remove_extra_items(_NodeId, unlimited, ItemIds) ->
{result, {ItemIds, []}}; {result, {ItemIds, []}};
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
NewItems = lists:sublist(ItemIds, MaxItems), NewItems = lists:sublist(ItemIds, MaxItems),
OldItems = lists:nthtail(length(NewItems), ItemIds), OldItems = lists:nthtail(length(NewItems), ItemIds),
%% Remove extra items: %% Remove extra items:
del_items(Host, Node, OldItems), del_items(NodeId, OldItems),
%% Return the new items list: %% Return the new items list:
{result, {NewItems, OldItems}}. {result, {NewItems, OldItems}}.
%% @spec (Host, Node, JID, ItemId) -> %% @spec (NodeId, JID, ItemId) ->
%% {error, Reason::stanzaError()} | %% {error, Reason::stanzaError()} |
%% {result, []} %% {result, []}
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% JID = mod_pubsub:jid() %% JID = mod_pubsub:jid()
%% ItemId = string() %% ItemId = string()
%% @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.</p> %% or a publisher.</p>
delete_item(Host, Node, Publisher, ItemId) -> delete_item(NodeId, Publisher, ItemId) ->
GenKey = jlib:short_prepd_bare_jid(Publisher), GenKey = jlib:short_prepd_bare_jid(Publisher),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
#pubsub_state{affiliation = Affiliation, items = Items} = GenState, #pubsub_state{affiliation = Affiliation, items = Items} = GenState,
Allowed = (Affiliation == publisher) orelse (Affiliation == owner) Allowed = (Affiliation == publisher) orelse (Affiliation == owner)
orelse case get_item(Host, Node, ItemId) of orelse case get_item(NodeId, ItemId) of
{result, #pubsub_item{creation = {GenKey, _}}} -> true; {result, #pubsub_item{creation = {GenKey, _}}} -> true;
_ -> false _ -> false
end, end,
@ -508,30 +507,30 @@ delete_item(Host, Node, Publisher, ItemId) ->
%% Requesting entity does not have sufficient privileges %% Requesting entity does not have sufficient privileges
{error, 'forbidden'}; {error, 'forbidden'};
true -> true ->
case get_item(Host, Node, ItemId) of case lists:member(ItemId, Items) of
{result, _} -> true ->
del_item(Host, Node, ItemId), del_item(NodeId, ItemId),
NewItems = lists:delete(ItemId, Items), NewItems = lists:delete(ItemId, Items),
set_state(GenState#pubsub_state{items = NewItems}), set_state(GenState#pubsub_state{items = NewItems}),
{result, {default, broadcast}}; {result, {default, broadcast}};
_ -> false ->
%% Non-existent node or item %% Non-existent node or item
{error, 'item-not-found'} {error, 'item-not-found'}
end end
end. end.
%% @spec (Host, Node, Owner) -> %% @spec (NodeId, Owner) ->
%% {error, Reason::stanzaError()} | %% {error, Reason::stanzaError()} |
%% {result, {default, broadcast}} %% {result, {default, broadcast}}
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% Owner = mod_pubsub:jid() %% Owner = mod_pubsub:jid()
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
case GenState of case GenState of
#pubsub_state{items = Items, affiliation = owner} -> #pubsub_state{items = Items, affiliation = owner} ->
del_items(Host, Node, Items), del_items(NodeId, Items),
set_state(GenState#pubsub_state{items = []}),
{result, {default, broadcast}}; {result, {default, broadcast}};
_ -> _ ->
%% Entity is not owner %% Entity is not owner
@ -548,42 +547,40 @@ purge_node(Host, Node, Owner) ->
%% the default PubSub module. Otherwise, it should return its own affiliation, %% the default PubSub module. Otherwise, it should return its own affiliation,
%% that will be added to the affiliation stored in the main %% that will be added to the affiliation stored in the main
%% <tt>pubsub_state</tt> table.</p> %% <tt>pubsub_state</tt> table.</p>
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(_Host, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
States = mnesia:match_object( States = mnesia:match_object(
#pubsub_state{stateid = {GenKey, {Host, '_'}}, _ = '_'}), #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}),
Tr = fun(#pubsub_state{stateid = {_, {_, N}}, affiliation = A}) -> Tr = fun(#pubsub_state{stateid = {_, N}, affiliation = A}) ->
{N, A} {N, A}
end, end,
{result, lists:map(Tr, States)}. {result, lists:map(Tr, States)}.
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
{result, States} = get_states(Host, Node), {result, States} = get_states(NodeId),
Tr = fun(#pubsub_state{stateid = {J, {_, _}}, affiliation = A}) -> Tr = fun(#pubsub_state{stateid = {J, {_, _}}, affiliation = A}) ->
{J, A} {J, A}
end, end,
{result, lists:map(Tr, States)}. {result, lists:map(Tr, States)}.
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
{result, GenState#pubsub_state.affiliation}. {result, GenState#pubsub_state.affiliation}.
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
GenKey = jlib:short_prepd_bare_jid(Owner), GenKey = jlib:short_prepd_bare_jid(Owner),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
case {Affiliation, GenState#pubsub_state.subscription} of case {Affiliation, GenState#pubsub_state.subscription} of
{none, none} -> {none, none} ->
del_state(GenState#pubsub_state.stateid); del_state(NodeId, GenKey);
_ -> _ ->
set_state(GenState#pubsub_state{affiliation = Affiliation}) set_state(GenState#pubsub_state{affiliation = Affiliation})
end, end.
ok.
%% @spec (Host, Owner) -> [{Node,Subscription}] %% @spec (Host, Owner) -> [{Node,Subscription}]
%% Host = host() %% Host = host()
%% Owner = mod_pubsub:jid() %% Owner = mod_pubsub:jid()
%% Node = mod_pubsub:pubsubNode()
%% @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
@ -591,49 +588,47 @@ set_affiliation(Host, Node, Owner, Affiliation) ->
%% the default PubSub module. Otherwise, it should return its own affiliation, %% the default PubSub module. Otherwise, it should return its own affiliation,
%% that will be added to the affiliation stored in the main %% that will be added to the affiliation stored in the main
%% <tt>pubsub_state</tt> table.</p> %% <tt>pubsub_state</tt> table.</p>
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(_Host, Owner) ->
{U, D, _} = SubKey = jlib:short_prepd_jid(Owner), {U, D, _} = SubKey = jlib:short_prepd_jid(Owner),
GenKey = jlib:short_prepd_bare_jid(SubKey), GenKey = jlib:short_prepd_bare_jid(SubKey),
States = case SubKey of States = case SubKey of
GenKey -> mnesia:match_object( GenKey -> mnesia:match_object(
#pubsub_state{stateid = {{U, D, '_'}, {Host, '_'}}, _ = '_'}); #pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'});
_ -> mnesia:match_object( _ -> mnesia:match_object(
#pubsub_state{stateid = {GenKey, {Host, '_'}}, _ = '_'}) #pubsub_state{stateid = {GenKey, '_'}, _ = '_'})
++ mnesia:match_object( ++ mnesia:match_object(
#pubsub_state{stateid = {SubKey, {Host, '_'}}, _ = '_'}) #pubsub_state{stateid = {SubKey, '_'}, _ = '_'})
end, end,
Tr = fun(#pubsub_state{stateid = {J, {_, N}}, subscription = S}) -> Tr = fun(#pubsub_state{stateid = {J, N}, subscription = S}) ->
{N, S, J} {N, S, J}
end, end,
{result, lists:map(Tr, States)}. {result, lists:map(Tr, States)}.
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
{result, States} = get_states(Host, Node), {result, States} = get_states(NodeId),
Tr = fun(#pubsub_state{stateid = {J, {_, _}}, subscription = S}) -> Tr = fun(#pubsub_state{stateid = {J, _}, subscription = S}) ->
{J, S} {J, S}
end, end,
{result, lists:map(Tr, States)}. {result, lists:map(Tr, States)}.
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
SubKey = jlib:short_prepd_jid(Owner), SubKey = jlib:short_prepd_jid(Owner),
SubState = get_state(Host, Node, SubKey), SubState = get_state(NodeId, SubKey),
{result, SubState#pubsub_state.subscription}. {result, SubState#pubsub_state.subscription}.
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
SubKey = jlib:short_prepd_jid(Owner), SubKey = jlib:short_prepd_jid(Owner),
SubState = get_state(Host, Node, SubKey), SubState = get_state(NodeId, SubKey),
case {Subscription, SubState#pubsub_state.affiliation} of case {Subscription, SubState#pubsub_state.affiliation} of
{none, none} -> {none, none} ->
del_state(SubState#pubsub_state.stateid); del_state(NodeId, SubKey);
_ -> _ ->
set_state(SubState#pubsub_state{subscription = Subscription}) set_state(SubState#pubsub_state{subscription = Subscription})
end, end,
ok. ok.
%% @spec (Host, Node) -> [States] | [] %% @spec (NodeId) -> [States] | []
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% Item = mod_pubsub:pubsubItems()
%% @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>
%% <p>We can consider that the pubsub_state table have been created by the main %% <p>We can consider that the pubsub_state table have been created by the main
@ -642,21 +637,20 @@ set_subscription(Host, Node, Owner, Subscription) ->
%% relational database).</p> %% relational database).</p>
%% <p>If a PubSub plugin wants to delegate the states storage to the default node, %% <p>If a PubSub plugin wants to delegate the states storage to the default node,
%% they can implement this function like this: %% they can implement this function like this:
%% ```get_states(Host, Node) -> %% ```get_states(NodeId) ->
%% node_default:get_states(Host, Node).'''</p> %% node_default:get_states(NodeId).'''</p>
get_states(Host, Node) -> get_states(NodeId) ->
States = mnesia:match_object( States = mnesia:match_object(
#pubsub_state{stateid = {'_', {Host, Node}}, _ = '_'}), #pubsub_state{stateid = {'_', NodeId}, _ = '_'}),
{result, States}. {result, States}.
%% @spec (JID, Host, Node) -> [State] | [] %% @spec (NodeId, JID) -> [State] | []
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% JID = mod_pubsub:jid() %% JID = mod_pubsub:jid()
%% State = mod_pubsub:pubsubItems() %% State = mod_pubsub:pubsubItems()
%% @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(Host, Node, JID) -> get_state(NodeId, JID) ->
StateId = {JID, {Host, Node}}, StateId = {JID, NodeId},
case mnesia:read({pubsub_state, StateId}) of case 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{stateid=StateId}
@ -673,12 +667,11 @@ set_state(_) ->
%% @spec (StateId) -> ok | {error, Reason::stanzaError()} %% @spec (StateId) -> ok | {error, Reason::stanzaError()}
%% StateId = mod_pubsub:pubsubStateId() %% StateId = mod_pubsub:pubsubStateId()
%% @doc <p>Delete a state from database.</p> %% @doc <p>Delete a state from database.</p>
del_state(StateId) -> del_state(NodeId, JID) ->
mnesia:delete({pubsub_state, StateId}). mnesia:delete({pubsub_state, {JID, NodeId}}).
%% @spec (Host, Node, From) -> [Items] | [] %% @spec (NodeId, From) -> [Items] | []
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% Items = mod_pubsub:pubsubItems() %% Items = mod_pubsub:pubsubItems()
%% @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>
@ -688,15 +681,15 @@ del_state(StateId) ->
%% relational database), or they can even decide not to persist any items.</p> %% relational database), or they can even decide not to persist any items.</p>
%% <p>If a PubSub plugin wants to delegate the item storage to the default node, %% <p>If a PubSub plugin wants to delegate the item storage to the default node,
%% they can implement this function like this: %% they can implement this function like this:
%% ```get_items(Host, Node, From) -> %% ```get_items(NodeId, From) ->
%% node_default:get_items(Host, Node, From).'''</p> %% node_default:get_items(NodeId, From).'''</p>
get_items(Host, Node, _From) -> get_items(NodeId, _From) ->
Items = mnesia:match_object( Items = mnesia:match_object(
#pubsub_item{itemid = {'_', {Host, Node}}, _ = '_'}), #pubsub_item{itemid = {'_', NodeId}, _ = '_'}),
{result, Items}. {result, Items}.
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) ->
GenKey = jlib:short_prepd_bare_jid(JID), GenKey = jlib:short_prepd_bare_jid(JID),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
Affiliation = GenState#pubsub_state.affiliation, Affiliation = GenState#pubsub_state.affiliation,
Subscription = GenState#pubsub_state.subscription, Subscription = GenState#pubsub_state.subscription,
Whitelisted = can_fetch_item(Affiliation, Subscription), Whitelisted = can_fetch_item(Affiliation, Subscription),
@ -726,25 +719,24 @@ get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubI
%% % Payment is required for a subscription %% % Payment is required for a subscription
%% {error, ?ERR_PAYMENT_REQUIRED}; %% {error, ?ERR_PAYMENT_REQUIRED};
true -> true ->
get_items(Host, Node, JID) get_items(NodeId, JID)
end. end.
%% @spec (Host, Node, ItemId) -> [Item] | [] %% @spec (NodeId, ItemId) -> [Item] | []
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% ItemId = string() %% ItemId = string()
%% Item = mod_pubsub:pubsubItems() %% Item = mod_pubsub:pubsubItems()
%% @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(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
case mnesia:read({pubsub_item, {ItemId, {Host, Node}}}) of case mnesia:read({pubsub_item, {ItemId, NodeId}}) of
[Item] when is_record(Item, pubsub_item) -> [Item] when is_record(Item, pubsub_item) ->
{result, Item}; {result, Item};
_ -> _ ->
{error, 'item-not-found'} {error, 'item-not-found'}
end. end.
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) ->
GenKey = jlib:short_prepd_bare_jid(JID), GenKey = jlib:short_prepd_bare_jid(JID),
GenState = get_state(Host, Node, GenKey), GenState = get_state(NodeId, GenKey),
Affiliation = GenState#pubsub_state.affiliation, Affiliation = GenState#pubsub_state.affiliation,
Subscription = GenState#pubsub_state.subscription, Subscription = GenState#pubsub_state.subscription,
Whitelisted = can_fetch_item(Affiliation, Subscription), Whitelisted = can_fetch_item(Affiliation, Subscription),
@ -774,7 +766,7 @@ get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup
%% % Payment is required for a subscription %% % Payment is required for a subscription
%% {error, ?ERR_PAYMENT_REQUIRED}; %% {error, ?ERR_PAYMENT_REQUIRED};
true -> true ->
get_item(Host, Node, ItemId) get_item(NodeId, ItemId)
end. end.
%% @spec (Item) -> ok | {error, Reason::stanzaError()} %% @spec (Item) -> ok | {error, Reason::stanzaError()}
@ -785,21 +777,20 @@ set_item(Item) when is_record(Item, pubsub_item) ->
set_item(_) -> set_item(_) ->
{error, 'internal-server-error'}. {error, 'internal-server-error'}.
%% @spec (Host, Node, ItemId) -> ok | {error, Reason::stanzaError()} %% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()}
%% Host = mod_pubsub:host() %% NodeId = mod_pubsub:pubsubNodeId()
%% Node = mod_pubsub:pubsubNode()
%% ItemId = string() %% ItemId = string()
%% @doc <p>Delete an item from database.</p> %% @doc <p>Delete an item from database.</p>
del_item(Host, Node, ItemId) -> del_item(NodeId, ItemId) ->
mnesia:delete({pubsub_item, {ItemId, {Host, Node}}}). mnesia:delete({pubsub_item, {ItemId, NodeId}}).
del_items(Host, Node, ItemIds) -> del_items(NodeId, ItemIds) ->
lists:foreach(fun(ItemId) -> lists:foreach(fun(ItemId) ->
del_item(Host, Node, ItemId) del_item(NodeId, ItemId)
end, ItemIds). end, ItemIds).
%% @doc <p>Return the name of the node if known: Default is to return %% @doc <p>Return the name of the node if known: Default is to return
%% node id.</p> %% node id.</p>
get_item_name(_Host, _Node, Id) -> get_item_name(_host, _Node, Id) ->
Id. Id.
%% @spec (Affiliation, Subscription) -> true | false %% @spec (Affiliation, Subscription) -> true | false

View File

@ -42,29 +42,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -112,79 +112,81 @@ features() ->
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(_Host, _Node, _Sender, _Subscriber, _AccessModel, subscribe_node(_NodeId, _Sender, _Subscriber, _AccessModel,
_SendLast, _PresenceSubscription, _RosterGroup) -> _SendLast, _PresenceSubscription, _RosterGroup) ->
{error, 'forbidden'}. {error, 'forbidden'}.
unsubscribe_node(_Host, _Node, _Sender, _Subscriber, _SubID) -> unsubscribe_node(_NodeId, _Sender, _Subscriber, _SubID) ->
{error, 'forbidden'}. {error, 'forbidden'}.
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
lists:foreach(fun(SubNode) -> lists:foreach(fun(SubNode) ->
node_default:publish_item( node_default:publish_item(
Host, SubNode, Publisher, Model, SubNode#pubsub_node.id, Publisher, Model,
MaxItems, ItemId, Payload) MaxItems, ItemId, Payload)
end, nodetree_default:get_subnodes(Host, Node, Publisher)). end, nodetree_default:get_subnodes(NodeId, Publisher)).
remove_extra_items(_Host, _Node, _MaxItems, ItemIds) -> remove_extra_items(_NodeId, _MaxItems, ItemIds) ->
{result, {ItemIds, []}}. {result, {ItemIds, []}}.
delete_item(_Host, _Node, _JID, _ItemId) -> delete_item(_NodeId, _JID, _ItemId) ->
{error, 'item-not-found'}. {error, 'item-not-found'}.
purge_node(_Host, _Node, _Owner) -> purge_node(_NodeId, _Owner) ->
{error, 'forbidden'}. {error, 'forbidden'}.
get_entity_affiliations(_Host, _Owner) -> get_entity_affiliations(_Host, _Owner) ->
{result, []}. {result, []}.
get_node_affiliations(_Host, _Node) -> get_node_affiliations(_NodeId) ->
{result, []}. {result, []}.
get_affiliation(_Host, _Node, _Owner) -> get_affiliation(_NodeId, _Owner) ->
{result, []}. {result, []}.
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(_Host, _Owner) -> get_entity_subscriptions(_Host, _Owner) ->
{result, []}. {result, []}.
get_node_subscriptions(_Host, _Node) -> get_node_subscriptions(NodeId) ->
%% note: get_node_subscriptions is used for broadcasting
%% DO NOT REMOVE
node_default:get_node_subscriptions(NodeId).
get_subscription(_NodeId, _Owner) ->
{result, []}. {result, []}.
get_subscription(_Host, _Node, _Owner) -> set_subscription(NodeId, Owner, Subscription) ->
{result, []}. node_default:set_subscription(NodeId, Owner, Subscription).
set_subscription(Host, Node, Owner, Subscription) -> get_states(NodeId) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:get_states(NodeId).
get_states(Host, Node) -> get_state(NodeId, JID) ->
node_default:get_states(Host, Node). node_default:get_state(NodeId, JID).
get_state(Host, Node, JID) ->
node_default:get_state(Host, Node, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -35,29 +35,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -103,74 +103,74 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) ->
end, end,
{result, Allowed}. {result, Allowed}.
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_default:get_entity_affiliations(Host, Owner). node_default:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_default:get_node_affiliations(Host, Node). node_default:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_default:get_affiliation(Host, Node, Owner). node_default:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_default:get_entity_subscriptions(Host, Owner). node_default:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_default:get_node_subscriptions(Host, Node). node_default:get_node_subscriptions(NodeId).
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
node_default:get_subscription(Host, Node, Owner). node_default:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -47,29 +47,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -120,77 +120,77 @@ features() ->
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_pep:create_node(Host, Node, Owner). node_pep:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_pep:delete_node(Host, Removed). node_pep:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, subscribe_node(NodeId, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup) -> SendLast, PresenceSubscription, RosterGroup) ->
node_pep:subscribe_node( node_pep:subscribe_node(
Host, Node, Sender, Subscriber, AccessModel, SendLast, NodeId, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup). PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_pep:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_pep:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_pep:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_pep:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_pep:remove_extra_items(Host, Node, MaxItems, ItemIds). node_pep:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_pep:delete_item(Host, Node, JID, ItemId). node_pep:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_pep:purge_node(Host, Node, Owner). node_pep:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_pep:get_entity_affiliations(Host, Owner). node_pep:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_pep:get_node_affiliations(Host, Node). node_pep:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_pep:get_affiliation(Host, Node, Owner). node_pep:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_pep:set_affiliation(Host, Node, Owner, Affiliation). node_pep:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_pep:get_entity_subscriptions(Host, Owner). node_pep:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_pep:get_node_subscriptions(Host, Node). node_pep:get_node_subscriptions(NodeId).
get_subscription(Host,Node,Owner) -> get_subscription(NodeId, Owner) ->
node_pep:get_subscription(Host,Node,Owner). node_pep:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_pep:set_subscription(Host, Node, Owner, Subscription). node_pep:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_pep:get_states(Host, Node). node_pep:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_pep:get_state(Host, Node, JID). node_pep:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_pep:set_state(State). node_pep:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_pep:get_items(Host, Node, From). node_pep:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_pep:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_pep:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_pep:get_item(Host, Node, ItemId). node_pep:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_pep:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_pep:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_pep:set_item(Item). node_pep:set_item(Item).

View File

@ -40,29 +40,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -133,92 +133,92 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) ->
end, end,
{result, Allowed}. {result, Allowed}.
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
case node_default:create_node(Host, Node, Owner) of case node_default:create_node(NodeId, Owner) of
{result, _} -> {result, []}; {result, _} -> {result, []};
Error -> Error Error -> Error
end. end.
delete_node(Host, Removed) -> delete_node(Removed) ->
case node_default:delete_node(Host, Removed) of case node_default:delete_node(Removed) of
{result, {_, _, Removed}} -> {result, {[], Removed}}; {result, {_, _, Removed}} -> {result, {[], Removed}};
Error -> Error Error -> Error
end. end.
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, subscribe_node(NodeId, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup) -> SendLast, PresenceSubscription, RosterGroup) ->
node_default:subscribe_node( node_default:subscribe_node(
Host, Node, Sender, Subscriber, AccessModel, SendLast, NodeId, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup). PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
case node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID) of case node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID) of
{error, Error} -> {error, Error}; {error, Error} -> {error, Error};
{result, _} -> {result, []} {result, _} -> {result, []}
end. end.
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(_Host, Owner) -> get_entity_affiliations(_Host, Owner) ->
OwnerKey = jlib:short_prepd_bare_jid(Owner), OwnerKey = jlib:short_prepd_bare_jid(Owner),
node_default:get_entity_affiliations(OwnerKey, Owner). node_default:get_entity_affiliations(OwnerKey, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
OwnerKey = jlib:short_bare_jid(Host), node_default:get_node_affiliations(NodeId).
node_default:get_node_affiliations(OwnerKey, Node).
get_affiliation(_Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
OwnerKey = jlib:short_prepd_bare_jid(Owner), node_default:get_affiliation(NodeId, Owner).
node_default:get_affiliation(OwnerKey, Node, Owner).
set_affiliation(_Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
OwnerKey = jlib:short_prepd_bare_jid(Owner), node_default:set_affiliation(NodeId, Owner, Affiliation).
State = get_state(OwnerKey, Node, OwnerKey),
set_state(State#pubsub_state{affiliation = Affiliation}),
ok.
get_entity_subscriptions(_Host, _Owner) -> get_entity_subscriptions(_Host, _Owner) ->
{result, []}. {result, []}.
get_node_subscriptions(_Host, _Node) -> get_node_subscriptions(NodeId) ->
{result, []}. %% note: get_node_subscriptions is used for broadcasting
%% there should not have any subscriptions
%% but that call returns also all subscription to none
%% and this is required for broadcast to occurs
%% DO NOT REMOVE
node_default:get_node_subscriptions(NodeId).
get_subscription(_Host, _Node, _Owner) -> get_subscription(_NodeId, _Owner) ->
{result, none}. {result, none}.
set_subscription(_Host, _Node, _Owner, _Subscription) -> set_subscription(_NodeId, _Owner, _Subscription) ->
ok. ok.
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -44,29 +44,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -116,76 +116,76 @@ create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_default:create_node_permission(Host, ServerHost, Node, ParentNode, node_default:create_node_permission(Host, ServerHost, Node, ParentNode,
Owner, Access). Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast,
PresenceSubscription, RosterGroup) -> PresenceSubscription, RosterGroup) ->
node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel,
SendLast, PresenceSubscription, RosterGroup). SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_default:get_entity_affiliations(Host, Owner). node_default:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_default:get_node_affiliations(Host, Node). node_default:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_default:get_affiliation(Host, Node, Owner). node_default:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_default:get_entity_subscriptions(Host, Owner). node_default:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_default:get_node_subscriptions(Host, Node). node_default:get_node_subscriptions(NodeId).
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
node_default:get_subscription(Host, Node, Owner). node_default:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -44,29 +44,29 @@
-export([init/3, terminate/2, -export([init/3, terminate/2,
options/0, features/0, options/0, features/0,
create_node_permission/6, create_node_permission/6,
create_node/3, create_node/2,
delete_node/2, delete_node/1,
purge_node/3, purge_node/2,
subscribe_node/8, subscribe_node/7,
unsubscribe_node/5, unsubscribe_node/4,
publish_item/7, publish_item/6,
delete_item/4, delete_item/3,
remove_extra_items/4, remove_extra_items/3,
get_entity_affiliations/2, get_entity_affiliations/2,
get_node_affiliations/2, get_node_affiliations/1,
get_affiliation/3, get_affiliation/2,
set_affiliation/4, set_affiliation/3,
get_entity_subscriptions/2, get_entity_subscriptions/2,
get_node_subscriptions/2, get_node_subscriptions/1,
get_subscription/3, get_subscription/2,
set_subscription/4, set_subscription/3,
get_states/2, get_states/1,
get_state/3, get_state/2,
set_state/1, set_state/1,
get_items/7, get_items/6,
get_items/3, get_items/2,
get_item/8, get_item/7,
get_item/3, get_item/2,
set_item/1, set_item/1,
get_item_name/3 get_item_name/3
]). ]).
@ -115,74 +115,74 @@ features() ->
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). node_default:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
create_node(Host, Node, Owner) -> create_node(NodeId, Owner) ->
node_default:create_node(Host, Node, Owner). node_default:create_node(NodeId, Owner).
delete_node(Host, Removed) -> delete_node(Removed) ->
node_default:delete_node(Host, Removed). node_default:delete_node(Removed).
subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). node_default:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
unsubscribe_node(Host, Node, Sender, Subscriber, SubID) -> unsubscribe_node(NodeId, Sender, Subscriber, SubID) ->
node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID). node_default:unsubscribe_node(NodeId, Sender, Subscriber, SubID).
publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) -> publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload). node_default:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload).
remove_extra_items(Host, Node, MaxItems, ItemIds) -> remove_extra_items(NodeId, MaxItems, ItemIds) ->
node_default:remove_extra_items(Host, Node, MaxItems, ItemIds). node_default:remove_extra_items(NodeId, MaxItems, ItemIds).
delete_item(Host, Node, JID, ItemId) -> delete_item(NodeId, JID, ItemId) ->
node_default:delete_item(Host, Node, JID, ItemId). node_default:delete_item(NodeId, JID, ItemId).
purge_node(Host, Node, Owner) -> purge_node(NodeId, Owner) ->
node_default:purge_node(Host, Node, Owner). node_default:purge_node(NodeId, Owner).
get_entity_affiliations(Host, Owner) -> get_entity_affiliations(Host, Owner) ->
node_default:get_entity_affiliations(Host, Owner). node_default:get_entity_affiliations(Host, Owner).
get_node_affiliations(Host, Node) -> get_node_affiliations(NodeId) ->
node_default:get_node_affiliations(Host, Node). node_default:get_node_affiliations(NodeId).
get_affiliation(Host, Node, Owner) -> get_affiliation(NodeId, Owner) ->
node_default:get_affiliation(Host, Node, Owner). node_default:get_affiliation(NodeId, Owner).
set_affiliation(Host, Node, Owner, Affiliation) -> set_affiliation(NodeId, Owner, Affiliation) ->
node_default:set_affiliation(Host, Node, Owner, Affiliation). node_default:set_affiliation(NodeId, Owner, Affiliation).
get_entity_subscriptions(Host, Owner) -> get_entity_subscriptions(Host, Owner) ->
node_default:get_entity_subscriptions(Host, Owner). node_default:get_entity_subscriptions(Host, Owner).
get_node_subscriptions(Host, Node) -> get_node_subscriptions(NodeId) ->
node_default:get_node_subscriptions(Host, Node). node_default:get_node_subscriptions(NodeId).
get_subscription(Host, Node, Owner) -> get_subscription(NodeId, Owner) ->
node_default:get_subscription(Host, Node, Owner). node_default:get_subscription(NodeId, Owner).
set_subscription(Host, Node, Owner, Subscription) -> set_subscription(NodeId, Owner, Subscription) ->
node_default:set_subscription(Host, Node, Owner, Subscription). node_default:set_subscription(NodeId, Owner, Subscription).
get_states(Host, Node) -> get_states(NodeId) ->
node_default:get_states(Host, Node). node_default:get_states(NodeId).
get_state(Host, Node, JID) -> get_state(NodeId, JID) ->
node_default:get_state(Host, Node, JID). node_default:get_state(NodeId, JID).
set_state(State) -> set_state(State) ->
node_default:set_state(State). node_default:set_state(State).
get_items(Host, Node, From) -> get_items(NodeId, From) ->
node_default:get_items(Host, Node, From). node_default:get_items(NodeId, From).
get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
get_item(Host, Node, ItemId) -> get_item(NodeId, ItemId) ->
node_default:get_item(Host, Node, ItemId). node_default:get_item(NodeId, ItemId).
get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). node_default:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
set_item(Item) -> set_item(Item) ->
node_default:set_item(Item). node_default:set_item(Item).

View File

@ -51,7 +51,7 @@
get_nodes/2, get_nodes/2,
get_nodes/1, get_nodes/1,
get_subnodes/3, get_subnodes/3,
get_subnodes_tree/2, get_subnodes_tree/3,
create_node/5, create_node/5,
delete_node/2 delete_node/2
]). ]).
@ -76,9 +76,10 @@ init(_Host, _ServerHost, _Opts) ->
{attributes, record_info(fields, pubsub_node)}]), {attributes, record_info(fields, pubsub_node)}]),
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
[host_node, host_parent, info] -> ok; % old schema, updated later by pubsub
NodesFields -> ok; NodesFields -> ok;
_ -> mnesia:transform_table(pubsub_node, ignore, NodesFields) _ ->
ok
%% mnesia:transform_table(pubsub_state, ignore, StatesFields)
end, end,
ok. ok.
terminate(_Host, _ServerHost) -> terminate(_Host, _ServerHost) ->
@ -97,12 +98,11 @@ set_node(Record) when is_record(Record, pubsub_node) ->
set_node(_) -> set_node(_) ->
{error, 'internal-server-error'}. {error, 'internal-server-error'}.
get_node(Host, Node, _From) ->
get_node(Host, Node).
%% @spec (Host, Node) -> pubsubNode() | {error, Reason} %% @spec (Host, Node) -> pubsubNode() | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
get_node(Host, Node, _From) ->
get_node(Host, Node).
get_node(Host, Node) -> get_node(Host, Node) ->
case catch mnesia:read({pubsub_node, {Host, Node}}) of case catch mnesia:read({pubsub_node, {Host, Node}}) of
[Record] when is_record(Record, pubsub_node) -> Record; [Record] when is_record(Record, pubsub_node) -> Record;
@ -110,44 +110,48 @@ get_node(Host, Node) ->
Error -> Error Error -> Error
end. end.
get_nodes(Key, _From) -> %% @spec (Host) -> [pubsubNode()] | {error, Reason}
get_nodes(Key). %% Host = mod_pubsub:host() | mod_pubsub:jid()
get_nodes(Host, _From) ->
%% @spec (Key) -> [pubsubNode()] | {error, Reason} get_nodes(Host).
%% Key = mod_pubsub:host() | mod_pubsub:jid() get_nodes(Host) ->
get_nodes(Key) -> mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}).
mnesia:match_object(#pubsub_node{nodeid = {Key, '_'}, _ = '_'}).
%% @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 = mod_pubsub:pubsubNode()
%% From = mod_pubsub:jid() %% From = mod_pubsub:jid()
get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node, _From) ->
mnesia:match_object(#pubsub_node{parentid = {Host, Node}, _ = '_'}). get_subnodes(Host, Node).
get_subnodes(Host, Node) ->
mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, parent = Node, _ = '_'}).
%% @spec (Host, Index) -> [pubsubNode()] | {error, Reason} %% @spec (Host, Index) -> [pubsubNode()] | {error, Reason}
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% From = mod_pubsub:jid()
get_subnodes_tree(Host, Node, _From) ->
get_subnodes_tree(Host, Node).
get_subnodes_tree(Host, Node) -> get_subnodes_tree(Host, Node) ->
mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}}, Acc) -> mnesia:foldl(fun(#pubsub_node{nodeid = {H, N} = R}, Acc) ->
case lists:prefix(Node, N) and (H == Host) of case lists:prefix(Node, N) and (H == Host) of
true -> [N | Acc]; true -> [R | Acc];
_ -> Acc _ -> Acc
end end
end, [], pubsub_node). end, [], pubsub_node).
%% @spec (Key, Node, Type, Owner, Options) -> ok | {error, Reason} %% @spec (Host, Node, Type, Owner, Options) -> ok | {error, Reason}
%% Key = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | mod_pubsub:jid()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% NodeType = mod_pubsub:nodeType() %% NodeType = mod_pubsub:nodeType()
%% Owner = mod_pubsub:jid() %% Owner = mod_pubsub:jid()
%% Options = list() %% Options = list()
create_node(Key, Node, Type, Owner, Options) -> create_node(Host, Node, Type, Owner, Options) ->
OwnerKey = jlib:short_prepd_bare_jid(Owner), BJID = jlib:short_prepd_bare_jid(Owner),
case mnesia:read({pubsub_node, {Key, Node}}) of case mnesia:read({pubsub_node, {Host, Node}}) of
[] -> [] ->
{ParentNode, ParentExists} = {ParentNode, ParentExists} =
case Key of case Host of
{_U, _S, _R} -> {_U, _S, _R} ->
%% This is special case for PEP handling %% This is special case for PEP handling
%% PEP does not uses hierarchy %% PEP does not uses hierarchy
@ -158,7 +162,7 @@ create_node(Key, Node, Type, Owner, Options) ->
[] -> [] ->
{[], true}; {[], true};
_ -> _ ->
case mnesia:read({pubsub_node, {Key, Parent}}) of case mnesia:read({pubsub_node, {Host, Parent}}) of
[] -> {Parent, false}; [] -> {Parent, false};
_ -> {Parent, true} _ -> {Parent, true}
end end
@ -166,13 +170,14 @@ create_node(Key, Node, Type, Owner, Options) ->
end, end,
case ParentExists of case ParentExists of
true -> true ->
%% Service requires registration NodeId = pubsub_index:new(node),
%%{error, ?ERR_REGISTRATION_REQUIRED}; mnesia:write(#pubsub_node{nodeid = {Host, Node},
mnesia:write(#pubsub_node{nodeid = {Key, Node}, id = NodeId,
parentid = {Key, ParentNode}, parent = ParentNode,
type = Type, type = Type,
owners = [OwnerKey], owners = [BJID],
options = Options}); options = Options}),
{ok, NodeId};
false -> false ->
%% Requesting entity is prohibited from creating nodes %% Requesting entity is prohibited from creating nodes
{error, 'forbidden'} {error, 'forbidden'}
@ -182,12 +187,13 @@ create_node(Key, Node, Type, Owner, Options) ->
{error, 'conflict'} {error, 'conflict'}
end. end.
%% @spec (Key, Node) -> [mod_pubsub:node()] %% @spec (Host, Node) -> [mod_pubsub:node()]
%% Key = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | mod_pubsub:jid()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
delete_node(Key, Node) -> delete_node(Host, Node) ->
Removed = get_subnodes_tree(Key, Node), Removed = get_subnodes_tree(Host, Node),
lists:foreach(fun(N) -> lists:foreach(fun(#pubsub_node{nodeid = {_, N}, id = I}) ->
mnesia:delete({pubsub_node, {Key, N}}) pubsub_index:free(node, I),
mnesia:delete({pubsub_node, {Host, N}})
end, Removed), end, Removed),
Removed. Removed.

View File

@ -49,7 +49,7 @@
get_nodes/2, get_nodes/2,
get_nodes/1, get_nodes/1,
get_subnodes/3, get_subnodes/3,
get_subnodes_tree/2, get_subnodes_tree/3,
create_node/5, create_node/5,
delete_node/2 delete_node/2
]). ]).
@ -95,14 +95,13 @@ get_node(Host, Node, _From) ->
get_node(Host, Node) -> get_node(Host, Node) ->
#pubsub_node{nodeid = {Host, Node}}. #pubsub_node{nodeid = {Host, Node}}.
get_nodes(Key, _From) -> %% @spec (Host) -> [pubsubNode()]
get_nodes(Key).
%% @spec (Key) -> [pubsubNode()]
%% Host = mod_pubsub:host() | mod_pubsub:jid() %% Host = mod_pubsub:host() | mod_pubsub:jid()
%% @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(_Key) -> get_nodes(Host, _From) ->
get_nodes(Host).
get_nodes(_Host) ->
[]. [].
%% @spec (Host, Node, From) -> [pubsubNode()] %% @spec (Host, Node, From) -> [pubsubNode()]
@ -110,13 +109,17 @@ get_nodes(_Key) ->
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% From = mod_pubsub:jid() %% From = mod_pubsub:jid()
%% @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) ->
[]. [].
%% @spec (Host, Index) -> [pubsubNode()] %% @spec (Host, Index) -> [pubsubNode()]
%% Host = mod_pubsub:host() %% Host = mod_pubsub:host()
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% @doc <p>Virtual node tree does not handle 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).
get_subnodes_tree(_Host, _Node) -> get_subnodes_tree(_Host, _Node) ->
[]. [].
@ -129,11 +132,11 @@ get_subnodes_tree(_Host, _Node) ->
%% @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>
%% <p>default allowed nodes: /home/host/user/any/node/name</p> %% <p>default allowed nodes: /home/host/user/any/node/name</p>
create_node(_Host, Node, _Type, Owner, _Options) -> create_node(Host, Node, _Type, Owner, _Options) ->
UserName = exmpp_jid:lnode_as_list(Owner), UserName = exmpp_jid:lnode_as_list(Owner),
UserHost = exmpp_jid:ldomain_as_list(Owner), UserHost = exmpp_jid:ldomain_as_list(Owner),
case Node of case Node of
["home", UserHost, UserName | _] -> {error, 'conflict'}; ["home", UserHost, UserName | _] -> {error, {virtual, {Host, Node}}};
_ -> {error, 'not-allowed'} _ -> {error, 'not-allowed'}
end. end.
@ -142,5 +145,5 @@ create_node(_Host, Node, _Type, Owner, _Options) ->
%% Node = mod_pubsub:pubsubNode() %% Node = mod_pubsub:pubsubNode()
%% @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) ->
[Node]. [get_node(Host, Node)].

View File

@ -77,24 +77,28 @@
%%% @type affiliation() = none | owner | publisher | outcast. %%% @type affiliation() = none | owner | publisher | outcast.
%%% @type subscription() = none | pending | unconfigured | subscribed. %%% @type subscription() = none | pending | unconfigured | subscribed.
%%% internal pubsub index table
-record(pubsub_index, {index, last, free}).
%%% @type pubsubNode() = #pubsub_node{ %%% @type pubsubNode() = #pubsub_node{
%%% nodeid = {Host::host(), Node::pubsubNode()}, %%% nodeid = {Host::host(), Node::pubsubNode()},
%%% parentid = {Host::host(), Node::pubsubNode()}, %%% parentid = {Host::host(), Node::pubsubNode()},
%%% nodeidx = int().
%%% 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>parentid</tt> and <tt>type</tt> fields are indexed.</p>
-record(pubsub_node, {nodeid, -record(pubsub_node, {nodeid,
parentid = {}, id,
type = "", parent,
type = "default",
owners = [], owners = [],
options = [] options = []
}). }).
%%% @type pubsubState() = #pubsub_state{ %%% @type pubsubState() = #pubsub_state{
%%% stateid = {ljid(), {Host::host(), Node::pubsubNode()}}, %%% stateid = {ljid(), pubsubNodeId()}},
%%% items = [ItemId::string()], %%% items = [ItemId::string()],
%%% affiliation = affiliation(), %%% affiliation = affiliation(),
%%% subscription = subscription()}. %%% subscription = subscription()}.
@ -106,11 +110,11 @@
subscription = none subscription = none
}). }).
%% @type pubsubItem() = #pubsub_item{ %%% @type pubsubItem() = #pubsub_item{
%% itemid = {ItemId::string(), {Host::host(),Node::pubsubNode()}}, %%% itemid = {ItemId::string(), pubsubNodeId()}},
%% creation = {ljid(), now()}, %%% creation = {ljid(), now()},
%% modification = {ljid(), now()}, %%% modification = {ljid(), now()},
%% 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, {itemid,

View File

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