aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBadlop <badlop@process-one.net>2008-12-23 01:34:52 +0000
committerBadlop <badlop@process-one.net>2008-12-23 01:34:52 +0000
commit42036d8f68beb13f97f8bb06f93eb05ee09d80b3 (patch)
treea91e87c593254d2ca36a6beeb638da2fac4065ba
parent* src/cyrsasl_digest.erl: Check digest-uri in SASL digest (diff)
* src/mod_last.erl: Implement workaround for uptime statistic in
32 bit machines, so it can show uptime greater than 50 days (EJAB-610) * src/mod_last_odbc.erl: Likewise * src/ejabberd_config.erl: Store start time in local_config table SVN Revision: 1744
-rw-r--r--ChangeLog6
-rw-r--r--src/ejabberd_config.erl7
-rw-r--r--src/mod_last.erl35
-rw-r--r--src/mod_last_odbc.erl33
4 files changed, 66 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 8574d1808..dc97f4d67 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2008-12-23 Badlop <badlop@process-one.net>
+ * src/mod_last.erl: Implement workaround for uptime statistic in
+ 32 bit machines, so it can show uptime greater than 50
+ days (EJAB-610)
+ * src/mod_last_odbc.erl: Likewise
+ * src/ejabberd_config.erl: Store start time in local_config table
+
* src/cyrsasl_digest.erl: Check digest-uri in SASL digest
authentication (thanks to Paul Guyot)(EJAB-569)
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index 182b4a216..6ee0fa528 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -55,7 +55,10 @@ start() ->
{attributes, record_info(fields, local_config)}]),
mnesia:add_table_copy(local_config, node(), ram_copies),
Config = get_ejabberd_config_path(),
- load_file(Config).
+ load_file(Config),
+ %% This start time is used by mod_last:
+ add_local_option(node_start, now()),
+ ok.
%% @doc Get the filename of the ejabberd configuration file.
%% The filename can be specified with: erl -config "/path/to/ejabberd.cfg".
@@ -76,7 +79,7 @@ get_ejabberd_config_path() ->
%% @doc Load the ejabberd configuration file.
%% It also includes additional configuration files and replaces macros.
-%% @spec (File::string()) -> [term()]
+%% @spec (File::string()) -> ok
load_file(File) ->
Terms = get_plain_terms_file(File),
State = lists:foldl(fun search_hosts/2, #state{}, Terms),
diff --git a/src/mod_last.erl b/src/mod_last.erl
index a6eb9d5ad..aac37ec59 100644
--- a/src/mod_last.erl
+++ b/src/mod_last.erl
@@ -68,12 +68,16 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST).
+%%%
+%%% Uptime of ejabberd node
+%%%
+
process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
case Type of
set ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
get ->
- Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
+ Sec = get_node_uptime(),
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
[{"xmlns", ?NS_LAST},
@@ -81,6 +85,24 @@ process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
[]}]}
end.
+%% @spec () -> integer()
+%% @doc Get the uptime of the ejabberd node, expressed in seconds.
+%% When ejabberd is starting, ejabberd_config:start/0 stores the datetime.
+get_node_uptime() ->
+ case ejabberd_config:get_local_option(node_start) of
+ {_, _, _} = StartNow ->
+ now_to_seconds(now()) - now_to_seconds(StartNow);
+ _undefined ->
+ trunc(element(1, erlang:statistics(wall_clock))/1000)
+ end.
+
+now_to_seconds({MegaSecs, Secs, _MicroSecs}) ->
+ MegaSecs * 1000000 + Secs.
+
+
+%%%
+%%% Serve queries about user last online
+%%%
process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
case Type of
@@ -126,8 +148,7 @@ get_last(IQ, SubEl, LUser, LServer) ->
[] ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
[#last_activity{timestamp = TimeStamp, status = Status}] ->
- {MegaSecs, Secs, _MicroSecs} = now(),
- TimeStamp2 = MegaSecs * 1000000 + Secs,
+ TimeStamp2 = now_to_seconds(now()),
Sec = TimeStamp2 - TimeStamp,
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
@@ -139,8 +160,7 @@ get_last(IQ, SubEl, LUser, LServer) ->
on_presence_update(User, Server, _Resource, Status) ->
- {MegaSecs, Secs, _MicroSecs} = now(),
- TimeStamp = MegaSecs * 1000000 + Secs,
+ TimeStamp = now_to_seconds(now()),
store_last_info(User, Server, TimeStamp, Status).
store_last_info(User, Server, TimeStamp, Status) ->
@@ -153,8 +173,9 @@ store_last_info(User, Server, TimeStamp, Status) ->
status = Status})
end,
mnesia:transaction(F).
-
-%% Returns: {ok, Timestamp, Status} | not_found
+
+%% @spec (LUser::string(), LServer::string() ->
+%% {ok, Timestamp::integer(), Status::string()} | not_found
get_last_info(LUser, LServer) ->
case catch mnesia:dirty_read(last_activity, {LUser, LServer}) of
{'EXIT', _Reason} ->
diff --git a/src/mod_last_odbc.erl b/src/mod_last_odbc.erl
index 9253c09e1..9fd41da12 100644
--- a/src/mod_last_odbc.erl
+++ b/src/mod_last_odbc.erl
@@ -61,12 +61,16 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_LAST),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_LAST).
+%%%
+%%% Uptime of ejabberd node
+%%%
+
process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
case Type of
set ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
get ->
- Sec = trunc(element(1, erlang:statistics(wall_clock))/1000),
+ Sec = get_node_uptime(),
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
[{"xmlns", ?NS_LAST},
@@ -74,6 +78,24 @@ process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
[]}]}
end.
+%% @spec () -> integer()
+%% @doc Get the uptime of the ejabberd node, expressed in seconds.
+%% When ejabberd is starting, ejabberd_config:start/0 stores the datetime.
+get_node_uptime() ->
+ case ejabberd_config:get_local_option(node_start) of
+ {_, _, _} = StartNow ->
+ now_to_seconds(now()) - now_to_seconds(StartNow);
+ _undefined ->
+ trunc(element(1, erlang:statistics(wall_clock))/1000)
+ end.
+
+now_to_seconds({MegaSecs, Secs, _MicroSecs}) ->
+ MegaSecs * 1000000 + Secs.
+
+
+%%%
+%%% Serve queries about user last online
+%%%
process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
case Type of
set ->
@@ -119,8 +141,7 @@ get_last(IQ, SubEl, LUser, LServer) ->
{selected, ["seconds","state"], [{STimeStamp, Status}]} ->
case catch list_to_integer(STimeStamp) of
TimeStamp when is_integer(TimeStamp) ->
- {MegaSecs, Secs, _MicroSecs} = now(),
- TimeStamp2 = MegaSecs * 1000000 + Secs,
+ TimeStamp2 = now_to_seconds(now()),
Sec = TimeStamp2 - TimeStamp,
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
@@ -136,8 +157,7 @@ get_last(IQ, SubEl, LUser, LServer) ->
end.
on_presence_update(User, Server, _Resource, Status) ->
- {MegaSecs, Secs, _MicroSecs} = now(),
- TimeStamp = MegaSecs * 1000000 + Secs,
+ TimeStamp = now_to_seconds(now()),
store_last_info(User, Server, TimeStamp, Status).
store_last_info(User, Server, TimeStamp, Status) ->
@@ -148,7 +168,8 @@ store_last_info(User, Server, TimeStamp, Status) ->
State = ejabberd_odbc:escape(Status),
odbc_queries:set_last_t(LServer, Username, Seconds, State).
-%% Returns: {ok, Timestamp, Status} | not_found
+%% @spec (LUser::string(), LServer::string() ->
+%% {ok, Timestamp::integer(), Status::string()} | not_found
get_last_info(LUser, LServer) ->
Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_last(LServer, Username) of