/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

**********************************************************************/


#include	<fcntl.h>
#include	<stdlib.h>
#include	"init.h"
#include	"long_char.h"
#include	"memory_routine.h"
#include	"xl.h"
#include	"netutils.h"
#include	"utils.h"
#include	"xllock.h"
#include	"pri_level.h"


#define LIFETIME		(3*24*3600+3)
#define LIMIT_TOLL		(12*3600)

#define CONNECTION_TIMEOUT_MAX		(5*60)
#define CONNECTION_TIMEOUT_MIN		5
#define CONNECTION_TIMEOUT_AVG		30

int lock_sync();
void init_xl_lock();
void init_lock_function(XLISP_ENV * env0,XLISP_ENV * env1);

void
destroy_routine()
{
int nos;
int fd_max;
int half;
XL_INTERPRETER info;
int iid,_iid;
int cnt;
int con_timeout,con_timeout_2;
int a;
int wait_min;
	s_check_resource2(&fd_max);

	half = fd_max/2;
	con_timeout = CONNECTION_TIMEOUT_MAX;
	for ( ; ; ) {
		nos = get_launch_interpreter_nos();

		if ( nos < half ) {
			sleep_sec((half - nos)*10/half + 1);
			con_timeout ++;
			if ( con_timeout > CONNECTION_TIMEOUT_MAX )
				con_timeout = CONNECTION_TIMEOUT_MAX;
			continue;
		}
		cnt = nos - half;
		iid = 0;

		for ( ; cnt >= 0 ; ) {
			for ( ; ; ) {

				if ( get_xli_info(&info,iid) < 0 )
					goto skip;
				if ( info.a_type != XLA_CONNECT )
					goto skip;
				if ( info.mode != XIM_RUN )
					goto skip;
				if ( con_timeout < CONNECTION_TIMEOUT_AVG )
					con_timeout_2 = CONNECTION_TIMEOUT_AVG;
				else	con_timeout_2 = con_timeout;
				if ( info.connection_cnt < con_timeout_2 )
					goto skip2;
				if ( info.silent_cnt < 0 )
					goto skip2;
				if ( info.silent_cnt < con_timeout )
					goto skip2;
				if ( exist_lock_info(iid) == 0 ) {

					goto skip;
				}

				_iid = get_next_iid(iid);
				close_interpreter(iid);
				iid = _iid;
				cnt --;
				if ( cnt < 0 ) {
					con_timeout ++;
					break;
				}
				continue;
			skip2:
				a = con_timeout - info.connection_cnt + 1;
				if ( wait_min > a )
					wait_min = a;
				if ( info.silent_cnt >= 0 ) {
					a = con_timeout - info.silent_cnt
						+1;
					if ( wait_min > a )
						wait_min = a;
				}
			skip:





				iid = get_next_iid(iid);
				if ( iid == 0 )
					break;
			}

			if ( cnt < 0 )
				break;
			con_timeout /= 2;
			if ( con_timeout < CONNECTION_TIMEOUT_MIN ) {
				con_timeout = CONNECTION_TIMEOUT_MIN;
				sleep_sec(1);
			}
		}
		sleep_sec(1);
	}
}

int
_main(int argc,char ** argv)
{

	init_xl(INI_DONTWAITCHI);
	init_xl_lock();

	timeout_exit(
		LIFETIME,
		LIFETIME + LIMIT_TOLL,
		lock_sync);
	create_task(destroy_routine,0,PRI_TICK);


	init_function(gblisp_top_env0,gblisp_top_env1,argc,argv);
	init_lock_function(gblisp_top_env0,gblisp_top_env1);
	init_gv_cpu(gblisp_top_env0);

	xl_setup_file(argc,argv);

	exit_stabilizer('e');
	return 0;
}
