aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMickaël Rémond <mickael.remond@process-one.net>2007-08-07 16:43:02 +0000
committerMickaël Rémond <mickael.remond@process-one.net>2007-08-07 16:43:02 +0000
commit9d03ea3f987d8eeee1372baa10f235e6b407759f (patch)
tree65dce784cd87223d9847e004a352763f7d2364cc
parent* src/mod_announce.erl: Added support to all the announce features described ... (diff)
* src/mod_offline.erl: Started implementation of mod_offline
quota. For now, it require change in code. Will be turn into a config file parameter soon. (EJAB-314). * src/p1_mnesia.erl: Added memory efficient record count in Mnesia. SVN Revision: 859
-rw-r--r--ChangeLog8
-rw-r--r--src/mod_offline.erl46
-rw-r--r--src/p1_mnesia.erl45
3 files changed, 82 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index cfba33ef8..fe15038c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-08-07 Mickael Remond <mickael.remond@process-one.net>
+
+ * src/mod_offline.erl: Started implementation of mod_offline
+ quota. For now, it require change in code. Will be turn into a
+ config file parameter soon. (EJAB-314).
+ * src/p1_mnesia.erl: Added memory efficient record count in
+ Mnesia.
+
2007-08-03 Mickael Remond <mickael.remond@process-one.net>
* src/mod_announce.erl: Added support to all the announce features
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index b9fde8833..96d963fa3 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -1,13 +1,13 @@
%%%----------------------------------------------------------------------
%%% File : mod_offline.erl
-%%% Author : Alexey Shchepin <alexey@sevcom.net>
-%%% Purpose :
-%%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%% Author : Alexey Shchepin <alexey@process-one.net>
+%%% Purpose : Store and manage offline messages in Mnesia database.
+%%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(mod_offline).
--author('alexey@sevcom.net').
+-author('alexey@process-one.net').
-behaviour(gen_mod).
@@ -29,6 +29,10 @@
-define(PROCNAME, ejabberd_offline).
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
+%% TODO: Move this part as a module config file parameter:
+%% Can be an integer > 0 or infinity:
+-define(MAX_OFFLINE_MSGS, infinity).
+
start(Host, _Opts) ->
mnesia:create_table(offline_msg,
[{disc_only_copies, [node()]},
@@ -51,19 +55,28 @@ init() ->
loop() ->
receive
- #offline_msg{} = Msg ->
- Msgs = receive_all([Msg]),
+ #offline_msg{us=US} = Msg ->
+ Msgs = receive_all(US, [Msg]),
Len = length(Msgs),
F = fun() ->
+ Count = Len + p1_mnesia:count_records(
+ offline_msg,
+ #offline_msg{us=US, _='_'}),
if
- Len >= ?OFFLINE_TABLE_LOCK_THRESHOLD ->
- mnesia:write_lock_table(offline_msg);
+ Count > ?MAX_OFFLINE_MSGS ->
+ %% TODO: Warn that messages have been discarded
+ ok;
true ->
- ok
- end,
- lists:foreach(fun(M) ->
- mnesia:write(M)
- end, Msgs)
+ if
+ Len >= ?OFFLINE_TABLE_LOCK_THRESHOLD ->
+ mnesia:write_lock_table(offline_msg);
+ true ->
+ ok
+ end,
+ lists:foreach(fun(M) ->
+ mnesia:write(M)
+ end, Msgs)
+ end
end,
mnesia:transaction(F),
loop();
@@ -71,10 +84,10 @@ loop() ->
loop()
end.
-receive_all(Msgs) ->
+receive_all(US, Msgs) ->
receive
- #offline_msg{} = Msg ->
- receive_all([Msg | Msgs])
+ #offline_msg{us=US} = Msg ->
+ receive_all(US, [Msg | Msgs])
after 0 ->
Msgs
end.
@@ -387,4 +400,3 @@ update_table() ->
?INFO_MSG("Recreating offline_msg table", []),
mnesia:transform_table(offline_msg, ignore, Fields)
end.
-
diff --git a/src/p1_mnesia.erl b/src/p1_mnesia.erl
new file mode 100644
index 000000000..2483a1b3f
--- /dev/null
+++ b/src/p1_mnesia.erl
@@ -0,0 +1,45 @@
+%% ``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 Process-one.
+%% Portions created by Process-one are Copyright 2007, Process-one
+%% All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(p1_mnesia).
+-author('mickael.remond@process-one.net').
+
+-export([count_records/2]).
+
+%% Return the number of records matching a given match expression.
+%% This function is intended to be used inside a Mnesia transaction.
+%% The count has been written to use the fewest possible memory by
+%% getting the record by small increment and by using continuation.
+-define(BATCHSIZE, 100).
+count_records(Tab, MatchExpression) ->
+ %% the result contains the atom a for each match: We do not need
+ %% actual values as we only count the data.
+ case mnesia:select(Tab, [{MatchExpression, [], [a]}], ?BATCHSIZE, read) of
+ {Result,Cont} ->
+ Count = length(Result),
+ count_records_cont(Cont, Count);
+ '$end_of_table' ->
+ 0
+ end.
+count_records_cont(Cont, Count) ->
+ case mnesia:select(Cont) of
+ {Result,Cont} ->
+ NewCount = Count + length(Result),
+ count_records_cont(Cont, NewCount);
+ '$end_of_table' ->
+ Count
+ end.