* 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
This commit is contained in:
Badlop 2008-12-23 01:34:52 +00:00
parent af2fa5b5f5
commit 42036d8f68
4 changed files with 66 additions and 15 deletions

View File

@ -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)

View File

@ -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),

View File

@ -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} ->

View File

@ -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