]> granicus.if.org Git - ejabberd/commitdiff
* src/mod_last.erl: Implement workaround for uptime statistic in
authorBadlop <badlop@process-one.net>
Tue, 23 Dec 2008 01:34:52 +0000 (01:34 +0000)
committerBadlop <badlop@process-one.net>
Tue, 23 Dec 2008 01:34:52 +0000 (01:34 +0000)
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

ChangeLog
src/ejabberd_config.erl
src/mod_last.erl
src/mod_last_odbc.erl

index 8574d18086c93d84673c6a4d4113eb6738711a94..dc97f4d67940930df4deb233e5353a3a5ae02f59 100644 (file)
--- 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)
 
index 182b4a216c0d2219ed88a36d9a4cbbcc66e6a728..6ee0fa528e443b0ae7bfc80dd23aa5ab0030431b 100644 (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),
index a6eb9d5ad90b294007639634a7614ef423051680..aac37ec59eed2614ab93f75b337d724f65901b61 100644 (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} ->
index 9253c09e1717491280a4ac9dcce601150d65a040..9fd41da1203dd33dfb07b17e7f009f491b7ab5c2 100644 (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