#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/server/update.c,v 2.6 1995/10/01 21:57:37 empire Exp $";
#endif

/*
 * update.c
 *
 * Update scheduler
 *
 * Dave Pare, 1994
 */

#include "misc.h"
#include "player.h"
#include "keyword.h"
#include "lwp.h"

struct lwpSem	*update_sem;

int	update_pending;

extern	void update_main();
extern	void update_wait();

/*ARGSUSED*/
void
update_sched(argc, argv)
	int	argc;
	s_char	**argv;
{
	extern	int s_p_etu;
	extern	int etu_per_update;
	extern	int adj_update;
	s_char	*kw;
	int	hour[2];
	int	secs_per_update;
	time_t	now, next, delta;

	update_sem = lwpCreateSem("Update", 0);
	update_pending = 0;
	lwpCreate(PP_SCHED, update_wait, 8192, LwpCurrent->flags, "updateWait",
		"Waits until players idle", 0, 0, 0);
	time(&now);
	(void) gamehours(now, hour);
	if (kw = kw_find("s_p_etu"))
		kw_parse(CF_VALUE, kw, &s_p_etu);
	if (kw = kw_find("etu_per_update"))
		kw_parse(CF_VALUE, kw, &etu_per_update);
	if (kw = kw_find("adj_update"))
		kw_parse(CF_VALUE, kw, &adj_update);
	if (s_p_etu <= 0) {
		logerror("bad value for s_p_etu (%d)", s_p_etu);
		s_p_etu = 2 * 60;
		logerror("setting s_p_etu to %d", s_p_etu);
	}
	while (1) {
		time(&now);
		next_update_time(&now, &next, &delta);
		logerror("Next update at %s", ctime(&next));
		logerror("Next update in %d seconds", delta);
		/* sleep until update is scheduled to go off */
		lwpSleepUntil(next);
		time(&now);
		now += adj_update;
		if (!gamehours(now, hour)) {
			logerror("No update permitted (hours restriction)");
			continue;
		}
		if (!updatetime(&now)) {
			logerror("No update wanted");
			continue;
		}
		if (updates_disabled()) {
			logerror("Updates disabled...skipping update");
			continue;
		}
		lwpSignal(update_sem);
	}
	/*NOTREACHED*/
}

/*ARGSUSED*/
void
update_wait(argc, argv)
	int	argc;
	s_char	**argv;
{
	struct	player *p;
	int	running;
	time_t	now;
	int	stacksize;
	struct	player *dp;

	while (1) {
		lwpWait(update_sem);
		running = 0;
		update_pending++;
		for (p = player_next(0); p != 0; p = player_next(p)) {
			if (p->state != PS_PLAYING)
				continue;
			if (p->command) {
				pr_flash(p, "Update aborting command\n");
				p->aborted = 1;
				lwpWakeupFd(p->proc);
				running++;
			}
		}
		time(&now);
		if (running) {
			/* sleep a few, wait for aborts to take effect */
			lwpSleepUntil(now + 2);
		}
		/* 
		 * we rely on the fact that update's priority is the highest
		 * in the land so it can finish before it yields.
		 */
		dp = player_new(0, 0);
		stacksize= 100000 +
/* finish_sects */	   WORLD_X*WORLD_Y*(2*sizeof(double)+sizeof(s_char *));
			
		lwpCreate(PP_UPDATE, update_main, stacksize, LwpCurrent->flags,
			"Update", "Updates the world", 0, 0, dp);
		update_pending = 0;
	}
	/*NOTREACHED*/
}
