src/stats.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. loadStats
  2. saveStats
  3. statsUpdateMaster
  4. print_stats
  5. PrintStats

/* $Id: stats.c,v 1.2 1998/08/02 20:35:04 proff Exp $
 * $Copyright$
 */

#include "nglobal.h"
#include "article.h"

#include "stats.h"
#include "http.h"

#define bf bigToStr

EXPORT struct stats *Stats = NULL;

EXPORT void loadStats (char *f)
/* [<][>][^][v][top][bottom][index][help] */
{
        int fd;
        struct stats st;
        Stats = XMmalloc (sizeof(*Stats));
        fd = open (f, O_RDONLY);
        if (fd >= 0)
        {
                if (read (fd, &st, sizeof st) != sizeof st)
                {
                        loge (("statistics file '%s' corrupted...unlinking", f));
                        close (fd);
                        unlink (f);
                }  else
                if (st.version != STATS_VERSION)
                {
                        char buf[MAX_PATH];
                        sprintf (buf, "%s.%d", f, st.version);
                        loge (("statistics file '%s' version %d, require version %d...renaming old file to '%s'", f, st.version, STATS_VERSION, buf));
                        link(f, buf);
                        unlink(f);
                } else
                {
                        memcpy (Stats, &st, sizeof st);
                        close (fd);
                        goto good;
                }
                close (fd);
        }
        memset (Stats, 0, sizeof(*Stats));
        Stats->statsStarted = time (NULL);
        Stats->version = STATS_VERSION;
good:
        Stats->invocations++;
        Stats->clientsActive = 0;
        Stats->task_high = 0;
        Stats->masterStarted = time (NULL);
        CS = &Stats->cache_stats[c_none];
}

EXPORT bool saveStats (char *f)
/* [<][>][^][v][top][bottom][index][help] */
{
        int fd;
        statsUpdateMaster ();
        fd = open (f, O_WRONLY | O_CREAT, 0664);
        if (write (fd, Stats, sizeof *Stats) != sizeof *Stats)
        {
                loge (("error during write of '%s'", f));
                close (fd);
                unlink (f);
                return FALSE;
        }
        close (fd);
        return TRUE;
}

EXPORT void statsUpdateMaster ()
/* [<][>][^][v][top][bottom][index][help] */
{
        static unsigned long U, S;
        static time_t T;
        unsigned long u, s;
        time_t t;
        assert(Task);
        if (Task->ti_state != nc_master)
            return;
        time(&t);
        if (T != t)
            {
                struct tms tms;
                times(&tms);
                u = tms.tms_utime;
                Stats->task_stats[Task->ti_state].cpu_user += u-U;
                U = u;
                s = tms.tms_stime;
                Stats->task_stats[Task->ti_state].cpu_system += s-S;
                S = s;
            }
        if (T == 0)
            {
                T = t;
            }
        else
            {
                if (t>T)
                    {
                        Stats->task_stats[Task->ti_state].elapsed += t-T;
                        T = t;
                    }
            }
}

/* parameters to fprintf(clientout, ) are passed on the stack altogether, which means functions returning pointers to static variables don't work. */
#define c convMalloc
#define b c

static void print_stats (struct stats *s)
/* [<][>][^][v][top][bottom][index][help] */
{
#if 0
        time_t ti=time(NULL);
        int dif=ti-s->time_statistics_started;
        /* keep initial \r\n -- used for head/body sep */
        emitf("\r\nNNTPCACHE %s statistics on %s, %s\r\n", VERSION, Host, con->bindAddr);
        emitf("\r\nOVERALL:\r\n\r\n");
        emitf("\tStatistics gathering commenced:         %24s\r\n", NewsDate(s->time_statistics_started));
        emitf("\tCurrent nntpcached started:             %24s\r\n", NewsDate(s->time_server_started));
        emitf("\tServers run during statistical period:  %24d\r\n", s->servers_run);
        emitf("\tClients active:                         %24d\r\n", s->clients_active);
        emitf("\tClient connects:                        %24s\r\n", c(s->client_connects));
        emitf("\tOutgoing server connections:            %24s\r\n", c(s->server_connects));
        emitf("\tOutgoing server connections (failed):   %24s\r\n", c(s->server_connects_failed));
        emitf("\tTotal data from remote servers (bytes): %24s\r\n", c(s->server_read_bytes));
        emitf("\tTotal data to remote servers (bytes):   %24s\r\n", c(s->server_write_bytes));
        emitf("\tTotal data from clients (bytes):        %24s\r\n", c(s->client_read_bytes));
        emitf("\tTotal data to clients (bytes):          %24s\r\n", c(s->client_write_bytes));
        emitf("\tTotal cache cache efficiency:           %23.2f%%\r\n", (1.0-((float)(s->server_read_bytes+s->server_write_bytes+1)/(float)(s->client_write_bytes+s->client_read_bytes+1)))*100.0);
        emitf("\tIPC messages to children:               %24s\r\n", b(s->ipc_messages_out));
        emitf("\tIPC messages to children (bytes):       %24s\r\n", c(s->ipc_messages_out_bytes));
        emitf("\tIPC messages from children:             %24s\r\n", b(s->ipc_messages_in));
        emitf("\tIPC messages from children (bytes):     %24s\r\n", c(s->ipc_messages_in_bytes));
        emitf("\tCPU Usage (User) in server:             %23.2fs\r\n", ((double) s->server_user_cpu/(double) CLK_TCK));
        emitf("\tCPU Usage (System) in server:           %23.2fs\r\n", ((double) s->server_syst_cpu/(double) CLK_TCK));
        emitf("\tCPU Usage (User) in update daemon:      %23.2fs\r\n", ((double) s->update_user_cpu/(double) CLK_TCK));
        emitf("\tCPU Usage (System) in update daemon:    %23.2fs\r\n", ((double) s->update_syst_cpu/(double) CLK_TCK));
        emitf("\tCPU Usage (User) in children:           %23.2fs\r\n", ((double) s->client_user_cpu/(double) CLK_TCK));
        emitf("\tCPU Usage (System) in children:         %23.2fs\r\n", ((double) s->client_syst_cpu/(double) CLK_TCK));
        emitf("\tTotal time elapsed in children:         %24s\r\n", nnitod(s->client_elapsed));
        emitf("\tDatabase stores:                        %24s\r\n", b(s->dbz_stores));
        emitf("\tDatabase fetches:                       %24s\r\n", b(s->dbz_fetches));
        emitf("\tDatabase size:                          %24s\r\n", c(s->dbz_len));
        emitf("\tGROUP commands:                         %24s\r\n", b(s->group));
        emitf("\tLISTGROUP commands:                     %24s\r\n", b(s->listgroup));
        emitf("\tGroups cached with > 0 articles:        %24d\r\n", s->groups_cached);
        emitf("\tGroups expired:                         %24d\r\n", s->expire_groups);
        emitf("\tArticles expired:                       %24s\r\n", b(s->expire_articles));
        emitf("\tPosts:                                  %24s\r\n", b(s->posts));
        emitf("\tPosts (crossposted):                    %24s\r\n", b(s->posts_cross));
        emitf("\tPosts (failed):                         %24s\r\n", b(s->posts_failed));
        emitf("\tPosts (bytes):                          %24s\r\n", c(s->posts_bytes));
        emitf("\tIncoming crossposts:                    %24s\r\n", b(s->crossposts));
        emitf("\tIncoming crossposts (bytes):            %24s\r\n", c(s->crossposts_bytes));
#if 0
emitf("\
\r\n\
LISTS:\r\n\
\r\n\
List-name---- --out-of-cache -----into-cache hits --xfer-per-hour lines -length\r\n");
emitf("\
active       %7d %7s %7d %7s %3.0f%% %7.2f %7s %5d %7s\r\n", s->list_active_cache, c(s->list_active_cache_bytes), s->list_active_cached, c(s->list_active_cached_bytes),  100.0*(s->list_active_cache_bytes+1)/(float)(s->list_active_cache_bytes+s->list_active_cached_bytes+1), (s->list_active_cache+s->list_active_cached)/(dif/3600.0), c(((s->list_active_cache_bytes+s->list_active_cached_bytes)*3600.0)/dif), s->active_entries, c(s->active_len));
emitf("\
active.times %7d %7s %7d %7s %3.0f%% %7.2f %7s %5d %7s\r\n", s->list_active_times_cache, c(s->list_active_times_cache_bytes), s->list_active_times_cached, c(s->list_active_times_cached_bytes),  100*(s->list_active_times_cache_bytes+1)/(float)(s->list_active_times_cache_bytes+s->list_active_times_cached_bytes+1), (s->list_active_times_cache+s->list_active_times_cached)/(dif/3600.0), c((s->list_active_times_cache_bytes+s->list_active_times_cached_bytes)/(dif/3600.0)), s->active_times_entries, c(s->active_times_len));
emitf("\
newsgroups   %7d %7s %7d %7s %3.0f%% %7.2f %7s %5d %7s\r\n", s->list_newsgroups_cache, c(s->list_newsgroups_cache_bytes), s->list_newsgroups_cached, c(s->list_newsgroups_cached_bytes),  100.0*(s->list_newsgroups_cache_bytes+1)/(float)(s->list_newsgroups_cache_bytes+s->list_newsgroups_cached_bytes+1), (s->list_newsgroups_cache+s->list_newsgroups_cached)/(dif/3600.0), c((s->list_newsgroups_cache_bytes+s->list_newsgroups_cached_bytes)/(dif/3600.0)), s->newsgroups_entries, c(s->newsgroups_len));
emitf("\
overview_fmt %7d %7s %7d %7s %3.0f%% %7.2f %7s %5d %7s\r\n", s->list_overview_fmt_cache, c(s->list_overview_fmt_cache_bytes), s->list_overview_fmt_cached, c(s->list_overview_fmt_cached_bytes),  100.0*(s->list_overview_fmt_cache_bytes+1)/(float)(s->list_overview_fmt_cache_bytes+s->list_overview_fmt_cached_bytes+1), (s->list_overview_fmt_cache+s->list_overview_fmt_cached)/(dif/3600.0), c((s->list_overview_fmt_cache_bytes+s->list_overview_fmt_cached_bytes)/(dif/3600.0)), s->overview_fmt_entries, c(s->overview_fmt_len));
emitf("\r\n\
MESSAGES:\r\n\
\r\n\
Data-type---- --out-of-cache -----into-cache hits ----------proxy xfer-per-hour\r\n");
emitf("\
article      %7d %7s %7d %7s %3.0f%% %7d %7s %5.0f %7s\r\n", s->article_cache, c(s->article_cache_bytes), s->article_cached, c(s->article_cached_bytes),  100.0*(s->article_cache_bytes+1)/(float)(s->article_cache_bytes+s->article_cached_bytes+1), s->article_proxy, c(s->article_proxy_bytes), (s->article_cache+s->article_cached)/(dif/3600.0), c(((s->article_cache_bytes+s->article_cached_bytes)*3600.0)/dif));
emitf("\
head         %7d %7s %7d %7s %3.0f%% %7d %7s %5.0f %7s\r\n", s->head_cache, c(s->head_cache_bytes), s->head_cached, c(s->head_cached_bytes),  100.0*(s->head_cache_bytes+1)/(float)(s->head_cache_bytes+s->head_cached_bytes+1), s->head_proxy, c(s->head_proxy_bytes), ((s->head_cache+s->head_cached)*3600.0)/dif, c(((s->head_cache_bytes+s->head_cached_bytes)*3600.0)/dif));
emitf("\
body         %7d %7s %7d %7s %3.0f%% %7d %7s %5.0f %7s\r\n", s->body_cache, c(s->body_cache_bytes), s->body_cached, c(s->body_cached_bytes),  100.0*(s->body_cache_bytes+1)/(float)(s->body_cache_bytes+s->body_cached_bytes+1), s->body_proxy, c(s->body_proxy_bytes), ((s->body_cache+s->body_cached)*3600.0)/dif, c(((s->body_cache_bytes+s->body_cached_bytes)*3600)/dif));
emitf("\
xover        %7d %7s %7d %7s %3.0f%% %7d %7s %5.0f %7s\r\n", s->xover_cache, c(s->xover_cache_bytes), s->xover_cached, c(s->xover_cached_bytes),  100.0*(s->xover_cache_bytes+1)/(float)(s->xover_cache_bytes+s->xover_cached_bytes+1), s->xover_proxy, c(s->xover_proxy_bytes), ((s->xover_cache+s->xover_cached+s->xover_proxy)*3600.0)/dif, c(((s->xover_cache_bytes+s->xover_cached_bytes+s->xover_proxy_bytes)*3600.0)/dif));
emitf("\
xhdr         %7d %7s %7d %7s %3.0f%% %7d %7s %5.0f %7s\r\n", s->xhdr_cache, c(s->xhdr_cache_bytes), s->xhdr_cached, c(s->xhdr_cached_bytes),  100.0*(s->xhdr_cache_bytes+1)/(float)(s->xhdr_cache_bytes+s->xhdr_cached_bytes+1), s->xhdr_proxy, c(s->xhdr_proxy_bytes), ((s->xhdr_cache+s->xhdr_cached+s->xhdr_proxy)*3600.0)/dif, c(((s->xhdr_cache_bytes+s->xhdr_cached_bytes+s->xhdr_proxy_bytes)*3600.0)/dif));
emitf("\
msgid        %7d %7s %7d %7s %3.0f%%                 %5.0f %7s\r\n", s->msgid_cache, c(s->msgid_cache_bytes), s->msgid_cached, c(s->msgid_cached_bytes),  100.0*(s->msgid_cache_bytes+1)/(float)(s->msgid_cache_bytes+s->msgid_cached_bytes+1), ((s->msgid_cache+s->msgid_cached)*3600.0)/dif, c(((s->msgid_cache_bytes+s->msgid_cached_bytes)*3600.0)/dif));
#endif
        convFree();
        return;
#endif
}

EXPORT bool PrintStats()
/* [<][>][^][v][top][bottom][index][help] */
{
        print_stats(Stats);
        return TRUE;
}

/* [<][>][^][v][top][bottom][index][help] */