/* timer.c */

/* Subroutines for timed events */
#include "copyright.h"

#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>

#ifdef WANT_ANSI
#ifdef __STDC__
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#endif /* __STDC__ */
#endif /* WANT_ANSI */
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#ifdef XENIX
#include <sys/signal.h>
#else
#include <signal.h>
#endif /* xenix */

#include "mudconf.h"
#include "config.h"
#include "db.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
#include "command.h"
#include "rwho_clilib.h"

extern void atr_collect ();
extern void do_second (int nsecs);
extern void fork_and_dump (int key);

static int alarm_triggered = 0;

static
#ifndef VMS
void 
#endif
alarm_handler ()
{
  alarm_triggered = 1;
#ifdef XENIX
  signal (SIGALRM, alarm_handler);
#endif
#ifdef VMS
  signal (SIGALRM, alarm_handler);
  return 1;
#endif
}

void init_timer ()
{
	signal (SIGALRM, alarm_handler);
	signal (SIGHUP, alarm_handler);
	mudstate.dump_counter = (mudconf.dump_offset == 0) ? 
		mudconf.dump_interval : mudconf.dump_offset;
	mudstate.check_counter = (mudconf.check_offset == 0) ?
		mudconf.check_interval : mudconf.check_offset;
	mudstate.idle_counter = mudconf.idle_interval;
	mudstate.rwho_counter = mudconf.rwho_interval;
	mudstate.mstats_counter = 15;
	alarm (1);
}

void dispatch ()
{
char	*cmdsave;
int	now, curr;
struct	rusage	usage;

	cmdsave = mudstate.debug_cmd;
	mudstate.debug_cmd = (char *)"< dispatch >";

	/* this routine can be used to poll from interface.c */

	if (!alarm_triggered) return;
	alarm_triggered = 0;

	do_second(1);

	/* Free list reconstruction */

	if ((mudconf.control_flags & CF_DBCHECK) &&
	    (mudstate.check_counter-- <= 0)) {
		mudstate.check_counter = mudconf.check_interval;
		mudstate.debug_cmd = (char *)"< dbck >";
		tmp_sync();
		cache_reset();

		do_dbck (NOTHING, NOTHING, 0);

		tmp_sync();
		cache_reset();
	}

	/* Database dump routines */

	if ((mudconf.control_flags & CF_CHECKPOINT) &&
	    (mudstate.dump_counter-- <= 0)) {
		mudstate.dump_counter = mudconf.dump_interval;
		mudstate.debug_cmd = (char *)"< dump >";
		tmp_sync();
		cache_reset();
		fork_and_dump(0);
	}

	/* Idle user check */

	if ((mudconf.control_flags & CF_IDLECHECK) &&
	    (mudstate.idle_counter-- <= 0)) {
		mudstate.idle_counter = mudconf.idle_interval;
		mudstate.debug_cmd = (char *)"< idlecheck >";
		tmp_sync();
		cache_reset();
		check_idle();

	}

	/* Memory use stats */

	if (mudstate.mstats_counter-- <= 0) {
		mudstate.mstats_counter = 15;
		now = time(0);
		curr = mudstate.mstat_curr;
		if (now > mudstate.mstat_secs[curr]) {
			curr = 1-curr;
			getrusage(RUSAGE_SELF, &usage);
			mudstate.mstat_ixrss[curr] = usage.ru_ixrss;
			mudstate.mstat_idrss[curr] = usage.ru_idrss;
			mudstate.mstat_isrss[curr] = usage.ru_isrss;
			mudstate.mstat_secs[curr] = now;
			mudstate.mstat_curr = curr;
		}
	}

#ifdef RWHO_IN_USE
	if ((mudconf.control_flags & CF_RWHO_XMIT) &&
	    (mudstate.rwho_counter-- <= 0)) {
		mudstate.rwho_counter = mudconf.rwho_interval;
		mudstate.debug_cmd = (char *)"< rwho update >";
		rwho_update();
	}
#endif

	/* reset alarm */

	alarm (1);
	mudstate.debug_cmd = cmdsave;
}

/* ---------------------------------------------------------------------------
 * do_timewarp: Adjust various internal timers.
 */

void do_timewarp (dbref player, dbref cause, int key, char *arg)
{
int	secs;

	secs = atol(arg);

	if ((key == 0) || (key & TWARP_QUEUE))		/* Sem/Wait queues */
		do_queue(player, cause, QUEUE_WARP, arg);
	if (key & TWARP_DUMP)
		mudstate.dump_counter -= secs;
	if (key & TWARP_CLEAN)
		mudstate.check_counter -= secs;
	if (key & TWARP_IDLE)
		mudstate.idle_counter -= secs;
	if (key & TWARP_RWHO)
		mudstate.rwho_counter -= secs;
}