24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-07-02 23:06:21 +02:00

added pubsub helper modules

This commit is contained in:
Christophe Romain 2010-09-16 14:31:08 +02:00
parent 652774a83c
commit 2624f3ba51
2 changed files with 153 additions and 0 deletions

View 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).

View 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.