mirror of
https://github.com/processone/ejabberd.git
synced 2024-10-05 14:51:05 +02:00
added pubsub helper modules
This commit is contained in:
parent
652774a83c
commit
2624f3ba51
41
src/mod_pubsub/pubsub_clean.erl
Normal file
41
src/mod_pubsub/pubsub_clean.erl
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
-module(pubsub_clean).
|
||||||
|
|
||||||
|
-define(TIMEOUT, 1000*600). % 1 minute
|
||||||
|
|
||||||
|
-export([start/0, loop/0, subscribed/1, offline/1]).
|
||||||
|
|
||||||
|
start() ->
|
||||||
|
Pid = spawn(?MODULE, loop, []),
|
||||||
|
register(pubsub_clean, Pid),
|
||||||
|
Pid.
|
||||||
|
|
||||||
|
loop() ->
|
||||||
|
receive
|
||||||
|
purge -> purge()
|
||||||
|
after ?TIMEOUT -> purge()
|
||||||
|
end,
|
||||||
|
loop().
|
||||||
|
|
||||||
|
purge() ->
|
||||||
|
{Sessions, Subscriptions} = {mnesia:table_info(session,size),mnesia:table_info(pubsub_state,size)},
|
||||||
|
if Subscriptions > Sessions + 500 ->
|
||||||
|
lists:foreach(fun(K) ->
|
||||||
|
[N]=mnesia:dirty_read({pubsub_node, K}),
|
||||||
|
I=element(3,N),
|
||||||
|
lists:foreach(fun(JID) ->
|
||||||
|
mnesia:dirty_delete({pubsub_state, {JID, I}})
|
||||||
|
end, offline(subscribed(I)))
|
||||||
|
end, mnesia:dirty_all_keys(pubsub_node));
|
||||||
|
true ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
subscribed(NodeId) ->
|
||||||
|
lists:map(fun(S) ->
|
||||||
|
element(1,element(2,S))
|
||||||
|
end, mnesia:dirty_match_object({pubsub_state, {'_',NodeId},'_',none,subscribed})).
|
||||||
|
|
||||||
|
offline(Jids) ->
|
||||||
|
lists:filter(fun({U,S,""}) -> ejabberd_sm:get_user_resources(U,S) == [];
|
||||||
|
({U,S,R}) -> not lists:member(R,ejabberd_sm:get_user_resources(U,S))
|
||||||
|
end, Jids).
|
112
src/mod_pubsub/pubsub_debug.erl
Normal file
112
src/mod_pubsub/pubsub_debug.erl
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
-module(pubsub_debug).
|
||||||
|
-author('christophe.romain@process-one.net').
|
||||||
|
|
||||||
|
-include("pubsub.hrl").
|
||||||
|
|
||||||
|
-compile(export_all).
|
||||||
|
|
||||||
|
nodeid(Host, Node) ->
|
||||||
|
case mnesia:dirty_read({pubsub_node, {Host, Node}}) of
|
||||||
|
[N] -> nodeid(N);
|
||||||
|
_ -> 0
|
||||||
|
end.
|
||||||
|
nodeid(N) -> N#pubsub_node.id.
|
||||||
|
nodeids() -> [nodeid(Host, Node) || {Host, Node} <- mnesia:dirty_all_keys(pubsub_node)].
|
||||||
|
nodeids_by_type(Type) -> [nodeid(N) || N <- mnesia:dirty_match_object(#pubsub_node{type=Type, _='_'})].
|
||||||
|
nodeids_by_option(Key, Value) -> [nodeid(N) || N <- mnesia:dirty_match_object(#pubsub_node{_='_'}), lists:member({Key, Value}, N#pubsub_node.options)].
|
||||||
|
nodeids_by_owner(JID) -> [nodeid(N) || N <- mnesia:dirty_match_object(#pubsub_node{_='_'}), lists:member(JID, N#pubsub_node.owners)].
|
||||||
|
nodes_by_id(I) -> mnesia:dirty_match_object(#pubsub_node{id=I, _='_'}).
|
||||||
|
|
||||||
|
state(JID, NodeId) ->
|
||||||
|
case mnesia:dirty_read({pubsub_state, {JID, NodeId}}) of
|
||||||
|
[S] -> S;
|
||||||
|
_ -> undefined
|
||||||
|
end.
|
||||||
|
states(NodeId) -> mnesia:dirty_match_object(#pubsub_state{stateid={'_', NodeId}, _='_'}).
|
||||||
|
stateid(S) -> element(1, S#pubsub_state.stateid).
|
||||||
|
stateids(NodeId) -> [stateid(S) || S <- states(NodeId)].
|
||||||
|
states_by_jid(JID) -> mnesia:dirty_match_object(#pubsub_state{stateid={JID, '_'}, _='_'}).
|
||||||
|
|
||||||
|
item(ItemId, NodeId) ->
|
||||||
|
case mnesia:dirty_read({pubsub_item, {ItemId, NodeId}}) of
|
||||||
|
[I] -> I;
|
||||||
|
_ -> undefined
|
||||||
|
end.
|
||||||
|
items(NodeId) -> mnesia:dirty_match_object(#pubsub_item{itemid={'_', NodeId}, _='_'}).
|
||||||
|
itemid(I) -> element(1, I#pubsub_item.itemid).
|
||||||
|
itemids(NodeId) -> [itemid(I) || I <- items(NodeId)].
|
||||||
|
items_by_id(ItemId) -> mnesia:dirty_match_object(#pubsub_item{itemid={ItemId, '_'}, _='_'}).
|
||||||
|
|
||||||
|
affiliated(NodeId) -> [stateid(S) || S <- states(NodeId), S#pubsub_state.affiliation=/=none].
|
||||||
|
subscribed(NodeId) -> [stateid(S) || S <- states(NodeId), S#pubsub_state.subscriptions=/=[]].
|
||||||
|
%subscribed(NodeId) -> [stateid(S) || S <- states(NodeId), S#pubsub_state.subscription=/=none]. %% old record
|
||||||
|
owners(NodeId) -> [stateid(S) || S <- mnesia:dirty_match_object(#pubsub_state{stateid={'_', NodeId}, affiliation=owner, _='_'})].
|
||||||
|
|
||||||
|
orphan_items(NodeId) ->
|
||||||
|
itemids(NodeId) -- lists:foldl(fun(S, A) -> A++S#pubsub_state.items end, [], mnesia:dirty_match_object(#pubsub_state{stateid={'_', NodeId}, _='_'})).
|
||||||
|
newer_items(NodeId, Seconds) ->
|
||||||
|
Now = calendar:universal_time(),
|
||||||
|
Oldest = calendar:seconds_to_daystime(Seconds),
|
||||||
|
[itemid(I) || I <- items(NodeId), calendar:time_difference(calendar:now_to_universal_time(element(1, I#pubsub_item.modification)), Now) < Oldest].
|
||||||
|
older_items(NodeId, Seconds) ->
|
||||||
|
Now = calendar:universal_time(),
|
||||||
|
Oldest = calendar:seconds_to_daystime(Seconds),
|
||||||
|
[itemid(I) || I <- items(NodeId), calendar:time_difference(calendar:now_to_universal_time(element(1, I#pubsub_item.modification)), Now) > Oldest].
|
||||||
|
|
||||||
|
orphan_nodes() -> [I || I <- nodeids(), owners(I)==[]].
|
||||||
|
duplicated_nodes() -> L = nodeids(), lists:usort(L -- lists:seq(1, lists:max(L))).
|
||||||
|
node_options(NodeId) ->
|
||||||
|
[N] = mnesia:dirty_match_object(#pubsub_node{id=NodeId, _='_'}),
|
||||||
|
N#pubsub_node.options.
|
||||||
|
update_node_options(Key, Value, NodeId) ->
|
||||||
|
[N] = mnesia:dirty_match_object(#pubsub_node{id=NodeId, _='_'}),
|
||||||
|
NewOptions = lists:keyreplace(Key, 1, N#pubsub_node.options, {Key, Value}),
|
||||||
|
mnesia:dirty_write(N#pubsub_node{options = NewOptions}).
|
||||||
|
|
||||||
|
check() ->
|
||||||
|
mnesia:transaction(fun() ->
|
||||||
|
case mnesia:read({pubsub_index, node}) of
|
||||||
|
[Idx] ->
|
||||||
|
Free = Idx#pubsub_index.free,
|
||||||
|
Last = Idx#pubsub_index.last,
|
||||||
|
Allocated = lists:seq(1, Last) -- Free,
|
||||||
|
NodeIds = mnesia:foldl(fun(N,A) -> [nodeid(N)|A] end, [], pubsub_node),
|
||||||
|
StateIds = lists:usort(mnesia:foldl(fun(S,A) -> [element(2, S#pubsub_state.stateid)|A] end, [], pubsub_state)),
|
||||||
|
ItemIds = lists:usort(mnesia:foldl(fun(I,A) -> [element(2, I#pubsub_item.itemid)|A] end, [], pubsub_item)),
|
||||||
|
BadNodeIds = NodeIds -- Allocated,
|
||||||
|
BadStateIds = StateIds -- NodeIds,
|
||||||
|
BadItemIds = ItemIds -- NodeIds,
|
||||||
|
Lost = Allocated -- NodeIds,
|
||||||
|
[{bad_nodes, [N#pubsub_node.nodeid || N <- lists:flatten([mnesia:match_object(#pubsub_node{id=I, _='_'}) || I <- BadNodeIds])]},
|
||||||
|
{bad_states, lists:foldl(fun(N,A) -> A++[{I,N} || I <- stateids(N)] end, [], BadStateIds)},
|
||||||
|
{bad_items, lists:foldl(fun(N,A) -> A++[{I,N} || I <- itemids(N)] end, [], BadItemIds)},
|
||||||
|
{lost_idx, Lost},
|
||||||
|
{orphaned, [I || I <- NodeIds, owners(I)==[]]},
|
||||||
|
{duplicated, lists:usort(NodeIds -- lists:seq(1, lists:max(NodeIds)))}];
|
||||||
|
_ ->
|
||||||
|
no_index
|
||||||
|
end
|
||||||
|
end).
|
||||||
|
|
||||||
|
rebuild_index() ->
|
||||||
|
mnesia:transaction(fun() ->
|
||||||
|
NodeIds = mnesia:foldl(fun(N,A) -> [nodeid(N)|A] end, [], pubsub_node),
|
||||||
|
Last = lists:max(NodeIds),
|
||||||
|
Free = lists:seq(1, Last) -- NodeIds,
|
||||||
|
mnesia:write(#pubsub_index{index = node, last = Last, free = Free})
|
||||||
|
end).
|
||||||
|
|
||||||
|
pep_subscriptions(LUser, LServer, LResource) ->
|
||||||
|
case ejabberd_sm:get_session_pid({LUser, LServer, LResource}) of
|
||||||
|
C2SPid when is_pid(C2SPid) ->
|
||||||
|
case catch ejabberd_c2s:get_subscribed(C2SPid) of
|
||||||
|
Contacts when is_list(Contacts) ->
|
||||||
|
lists:map(fun({U, S, _}) ->
|
||||||
|
io_lib:format("~s@~s", [U, S])
|
||||||
|
end, Contacts);
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user