/*
    mudstat.c

  Keep hundreth of a second statistics 

 */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <stdio.h>

#include "config.h"
#include "lint.h"

#ifdef sun
time_t time (time_t *);
#endif


#define MUDSTAT
#include "mudstat.h"

#ifdef RUSAGE			/* Defined in config.h */
#ifdef SOLARIS
#include <sys/times.h>
#include <limits.h>
#else
#include <sys/resource.h>
extern int getrusage (int, struct rusage *);
#ifdef sun
extern int getpagesize();
#endif
#ifndef RUSAGE_SELF
#define RUSAGE_SELF	0
#endif
#endif /* SOLARIS */
#endif

    long mch_t1;
    static struct tms tms1;
    static int num_pr = 0;

    static	int	ms_eval_lim,    /* Low limit for logging eval cost */
    			ms_time_lim,    /* Low limit for logging eval time */
			ms_active = 0;  /* True if logging active */
extern int s_flag;
			
/*
 * Set active / inactive and parameters
 */
void
mudstatus_set(int active, int eval_lim, int time_lim)
{
    float tifl = time_lim / 100.0;
    FILE *mstat;

    ms_active = active;

    if (active)
    {
	s_flag = 1;
	if ((mstat = fopen(MUDSTAT_FILE, "a")) != NULL)
	{
	    fprintf(mstat,"\n%-30s (%5.2f) %8d\n",
		    "------ ON, Limits:", tifl, eval_lim);
	    fclose(mstat);
	}
    }
    else
    {
	if (s_flag && ((mstat = fopen(MUDSTAT_FILE,"a")) != NULL))
	{
	    fprintf(mstat,"\n%-30s\n", "------ OFF");
	    fclose(mstat);
	}
	s_flag = 0;
    }
    ms_eval_lim = ((eval_lim >= 0) ? eval_lim : MUDSTAT_LOGEVAL);
    ms_time_lim = ((time_lim >= 0) ? time_lim : MUDSTAT_LOGTIME);
}

/*
 * Mark current millitime
 */ 
static void 
mark_millitime()
{
#ifdef RUSAGE
#ifdef SOLARIS
    struct tms buffer;
    
    if (times(&buffer) != -1)
	mch_t1 = buffer.tms_utime + buffer.tms_stime;
#else
    static struct rusage rus;
    if (getrusage(RUSAGE_SELF, &rus) >= 0) 
    {                      
	/* Time in millisecs
	 */
	mch_t1 = rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000 +
	    rus.ru_stime.tv_sec * 1000 + rus.ru_stime.tv_usec / 1000; 
    }
#endif
#endif

    times(&tms1);
}

/*
 * Get millitime passed (actual real time)
 */
int 
get_millitime()
{
    float mtime;
    static struct tms tms2;

    times(&tms2);
    mtime =  (tms2.tms_utime - tms1.tms_utime +
	      tms2.tms_stime - tms1.tms_stime) / 60.0;

    return (int)(mtime * 100.0);
}

#ifdef RUSAGE
/*
 * Get millitime passed (process time)
 */
int 
get_processtime()
{
#ifdef SOLARIS
    struct tms buffer;
    long mch_t2;
    
    if (times(&buffer) != -1)
	mch_t2 = buffer.tms_utime + buffer.tms_stime;
#else
    static struct rusage rus;
    long mch_t2;

    if (getrusage(RUSAGE_SELF, &rus) >= 0) 
    {                      
	/* Time in millisecs
	 */
	mch_t2 = rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000 +
	    rus.ru_stime.tv_sec * 1000 + rus.ru_stime.tv_usec / 1000; 
    }
#endif /* SOLARIS */
    return mch_t2 - mch_t1;
}
#else
int get_processtime() { return 0; }
#endif

void 
reset_mudstatus()
{
    mark_millitime();
    num_move = 0;
    num_mcall = 0;
    num_fileread = 0;
    num_filewrite = 0;
    num_compile = 0;
}

void 
print_mudstatus(char *activity, int eval, int timem, int tiproc)
{
    FILE *mstat;
    float tifl, tifl2;

    if (!ms_active)
	return;

    if (timem < ms_time_lim && eval < ms_eval_lim)
	return;

    tifl = timem / 100.0;
    tifl2 = tiproc / 1000.0;

    if ((mstat = fopen(MUDSTAT_FILE,"a")) != NULL)
    {
	if (!num_pr)
	    fprintf(mstat,"\n%-30s (%11s) %8s %3s %3s %3s %3s %3s\n",
		    "Activity", "time:cpu", "evalcost", "cp", "mc",
		    "rd", "wr", "mv");
	num_pr = (num_pr + 1) % 10;
	if (strlen(activity) < 30)
	    fprintf(mstat,"%-30s (%5.2f:%5.2f) %8d %3d %3d %3d %3d %3d\n",
		    activity, tifl, tifl2, eval, num_compile, num_mcall, 
		    num_fileread, num_filewrite, num_move);
	else
	    fprintf(mstat,"%s\n%-30s (%5.2f:%5.2f) %8d %3d %3d %3d %3d %3d\n",
		    activity, "", tifl, tifl2, eval, num_compile, num_mcall, 
		    num_fileread, num_filewrite, num_move);
	    
	fclose(mstat);
    }
}