aboutsummaryrefslogtreecommitdiff
path: root/src/nodetree_tree.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/nodetree_tree.erl')
-rw-r--r--src/nodetree_tree.erl117
1 files changed, 75 insertions, 42 deletions
diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl
index 69b50ff9f..c94ba197b 100644
--- a/src/nodetree_tree.erl
+++ b/src/nodetree_tree.erl
@@ -5,7 +5,7 @@
%%% Created : 1 Dec 2007 by Christophe Romain <christophe.romain@process-one.net>
%%%
%%%
-%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2019 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -30,7 +30,7 @@
%%% <p>PubSub node tree plugins are using the {@link gen_nodetree} behaviour.</p>
%%% <p><strong>The API isn't stabilized yet</strong>. The pubsub plugin
%%% development is still a work in progress. However, the system is already
-%%% useable and useful as is. Please, send us comments, feedback and
+%%% usable and useful as is. Please, send us comments, feedback and
%%% improvements.</p>
-module(nodetree_tree).
@@ -38,9 +38,11 @@
-author('christophe.romain@process-one.net').
-include_lib("stdlib/include/qlc.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
-include("pubsub.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
+-include("translate.hrl").
-export([init/3, terminate/2, options/0, set_node/1,
get_node/3, get_node/2, get_node/1, get_nodes/2,
@@ -49,15 +51,10 @@
delete_node/2]).
init(_Host, _ServerHost, _Options) ->
- mnesia:create_table(pubsub_node,
+ ejabberd_mnesia:create(?MODULE, pubsub_node,
[{disc_copies, [node()]},
- {attributes, record_info(fields, pubsub_node)}]),
- mnesia:add_table_index(pubsub_node, id),
- NodesFields = record_info(fields, pubsub_node),
- case mnesia:table_info(pubsub_node, attributes) of
- NodesFields -> ok;
- _ -> ok
- end,
+ {attributes, record_info(fields, pubsub_node)},
+ {index, [id]}]),
%% mnesia:transform_table(pubsub_state, ignore, StatesFields)
ok.
@@ -76,51 +73,87 @@ get_node(Host, Node, _From) ->
get_node(Host, Node) ->
case mnesia:read({pubsub_node, {Host, Node}}) of
[Record] when is_record(Record, pubsub_node) -> Record;
- _ -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}
+ _ -> {error, xmpp:err_item_not_found(?T("Node not found"), ejabberd_option:language())}
end.
get_node(Nidx) ->
case mnesia:index_read(pubsub_node, Nidx, #pubsub_node.id) of
[Record] when is_record(Record, pubsub_node) -> Record;
- _ -> {error, ?ERRT_ITEM_NOT_FOUND(?MYLANG, <<"Node not found">>)}
+ _ -> {error, xmpp:err_item_not_found(?T("Node not found"), ejabberd_option:language())}
end.
-get_nodes(Host, _From) ->
- get_nodes(Host).
-
get_nodes(Host) ->
- mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}).
+ get_nodes(Host, infinity).
+
+get_nodes(Host, infinity) ->
+ mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'});
+get_nodes(Host, Limit) ->
+ case mnesia:select(
+ pubsub_node,
+ ets:fun2ms(
+ fun(#pubsub_node{nodeid = {H, _}} = Node) when H == Host ->
+ Node
+ end), Limit, read) of
+ '$end_of_table' -> [];
+ {Nodes, _} -> Nodes
+ end.
-get_parentnodes(_Host, _Node, _From) ->
- [].
+get_parentnodes(Host, Node, _From) ->
+ case catch mnesia:read({pubsub_node, {Host, Node}}) of
+ [Record] when is_record(Record, pubsub_node) ->
+ Record#pubsub_node.parents;
+ _ ->
+ []
+ end.
-%% @doc <p>Default node tree does not handle parents, return a list
-%% containing just this node.</p>
get_parentnodes_tree(Host, Node, _From) ->
+ get_parentnodes_tree(Host, Node, 0, []).
+get_parentnodes_tree(Host, Node, Level, Acc) ->
case catch mnesia:read({pubsub_node, {Host, Node}}) of
- [Record] when is_record(Record, pubsub_node) -> [{0, [Record]}];
- _ -> []
+ [Record] when is_record(Record, pubsub_node) ->
+ Tree = [{Level, [Record]}|Acc],
+ case Record#pubsub_node.parents of
+ [Parent] -> get_parentnodes_tree(Host, Parent, Level+1, Tree);
+ _ -> Tree
+ end;
+ _ ->
+ Acc
end.
-get_subnodes(Host, Node, _From) ->
- get_subnodes(Host, Node).
-
-get_subnodes(Host, <<>>) ->
- Q = qlc:q([N
- || #pubsub_node{nodeid = {NHost, _},
- parents = Parents} =
- N
- <- mnesia:table(pubsub_node),
- Host == NHost, Parents == []]),
- qlc:e(Q);
-get_subnodes(Host, Node) ->
+get_subnodes(Host, <<>>, infinity) ->
+ mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, parents = [], _ = '_'});
+get_subnodes(Host, <<>>, Limit) ->
+ case mnesia:select(
+ pubsub_node,
+ ets:fun2ms(
+ fun(#pubsub_node{nodeid = {H, _}, parents = []} = Node) when H == Host ->
+ Node
+ end), Limit, read) of
+ '$end_of_table' -> [];
+ {Nodes, _} -> Nodes
+ end;
+get_subnodes(Host, Node, infinity) ->
Q = qlc:q([N
|| #pubsub_node{nodeid = {NHost, _},
parents = Parents} =
N
<- mnesia:table(pubsub_node),
Host == NHost, lists:member(Node, Parents)]),
- qlc:e(Q).
+ qlc:e(Q);
+get_subnodes(Host, Node, Limit) ->
+ case mnesia:select(
+ pubsub_node,
+ ets:fun2ms(
+ fun(#pubsub_node{nodeid = {H, _}, parents = Ps} = N)
+ when H == Host andalso Ps /= [] -> N
+ end), Limit, read) of
+ '$end_of_table' -> [];
+ {Nodes, _} ->
+ lists:filter(
+ fun(#pubsub_node{parents = Parents}) ->
+ lists:member(Node, Parents)
+ end, Nodes)
+ end.
get_subnodes_tree(Host, Node, _From) ->
get_subnodes_tree(Host, Node).
@@ -130,13 +163,13 @@ get_subnodes_tree(Host, Node) ->
{error, _} ->
[];
Rec ->
- BasePlugin = jlib:binary_to_atom(<<"node_",
+ BasePlugin = misc:binary_to_atom(<<"node_",
(Rec#pubsub_node.type)/binary>>),
- BasePath = BasePlugin:node_to_path(Node),
+ {result, BasePath} = BasePlugin:node_to_path(Node),
mnesia:foldl(fun (#pubsub_node{nodeid = {H, N}} = R, Acc) ->
- Plugin = jlib:binary_to_atom(<<"node_",
+ Plugin = misc:binary_to_atom(<<"node_",
(R#pubsub_node.type)/binary>>),
- Path = Plugin:node_to_path(N),
+ {result, Path} = Plugin:node_to_path(N),
case lists:prefix(BasePath, Path) and (H == Host) of
true -> [R | Acc];
false -> Acc
@@ -180,10 +213,10 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
options = Options}),
{ok, Nidx};
false ->
- {error, ?ERR_FORBIDDEN}
+ {error, xmpp:err_forbidden()}
end;
_ ->
- {error, ?ERRT_CONFLICT(?MYLANG, <<"Node already exists">>)}
+ {error, xmpp:err_conflict(?T("Node already exists"), ejabberd_option:language())}
end.
delete_node(Host, Node) ->