
/*
    LinuxWare daemon - Netware like server for Linux

    Copyright (C) 1994, 1995  Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include "config.h"
#include "logging.h"
#include "bindery.h"
#include "sap2bind.h"
#include "wdog.h"
#include "bcast.h"
#include "timer.h"

static int age_bindery_object(bind_list* bl,void* data)
{
	if (bl->obj.flag & BFLAG_DYNAMIC)
	{
		if ((bl->obj.timer+=TIMER_RATE)>SAP_TIMEOUT)
		{
			LPRINTF(LL_INFO,("Removing %s from bindery (timed out)\n",bl->obj.name.name));
			if (!bind_remove(bl))
			{
				LPRINTF(LL_ERROR,("Remove not successfull\n"));
			}
		}
	}
	return 0;
}

static void age_bindery()
{
	bind_first_that(age_bindery_object,NULL);
}

volatile int timer_request=0;

static void timer_handler()
{
	signal(SIGALRM,timer_handler);
	timer_request=1;
}

static void age_conn()
{
	int cid;
	
	for(cid=1;cid<MAX_CONNECT;cid++)
	{
		connection* c=get_conn(cid);
		if (c->alloc)
		{
			if ((c->timer+=TIMER_RATE)>=CONN_TIMEOUT)
			{
				LPRINTF(LL_INFO,("timed out: connection %i",cid));
				if (c->logged_obj!=NULL) 
				{
					LPRINTF(LL_INFO,(", object name: %s \n",c->logged_obj->name.name));
				}
				else
				{
					LPRINTF(LL_INFO,("\n"));
				}
				free_conn(c);
				continue;
			}
			if ((c->wdog_timer+=TIMER_RATE)>=CONN_QUERY)
			{
				LPRINTF(LL_FULL,("poll connection %i\n",cid));
				wdog_send(c,IPX_WDOG_POOL_INACTIVE);
				c->wdog_timer-=CONN_QUERY;
			}
			if (c->msg_hold && (c->msg_timer+=TIMER_RATE)>=MSG_NOTIFY)
			{
				LPRINTF(LL_FULL,("message notify connection %i\n",cid));
				bcast_send(c,IPX_BCAST_MSG_NOTIFY);
				c->msg_timer=0;
			}
		}
	}
}

static int sap_query_timer=0;
static int sap_notify_timer=0;

void handle_timer()
{
	LPRINTF(LL_FULL,("Timer request\n"));
	if ((sap_query_timer+=TIMER_RATE)>=SAP_QUERY)
	{
		sap_query();
		sap_query_timer-=SAP_QUERY;
	}
	if ((sap_notify_timer+=TIMER_RATE)>=SAP_NOTIFY)
	{
		sap_notify();
		sap_notify_timer-=SAP_NOTIFY;
	}
	LPRINTF(LL_FULL,("Aging bindery\n"));
	age_bindery();
	LPRINTF(LL_FULL,("Aging connections\n"));
	age_conn();
}

void init_timer()
{
	struct itimerval itval;

	itval.it_interval.tv_sec = TIMER_RATE;
	itval.it_value.tv_sec = TIMER_RATE;
	itval.it_interval.tv_usec = 0;
	itval.it_value.tv_usec = 0;
	if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
	{
		LPRINTF(LL_FATAL,("Can't set interval timer: %s\n",strerror(errno)));
		exit(1);
	}
	
	signal(SIGALRM,timer_handler);
	LPRINTF(LL_INFO,("timer initialized\n"));
}

void done_timer()
{
	signal(SIGALRM,SIG_DFL);
	LPRINTF(LL_INFO,("timer shutdown\n"));
}
