/**********************************************************************
 
	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	<stdlib.h>
#include	"memory_routine.h"
#include	"memory_debug.h"
#include	"xl.h"
#include	"gbacrp.h"
#include	"task.h"
#include	"pri_level.h"
#include	"lock_level.h"
#include	"mp.h"
#include	"machine/mp.h"
#include	"gbmp.h"
#include        "xldir.h"
#include	"queue.h"

#define THRESH_HOLD	30

extern struct path_pair * start;
DIR_LIST * marge_dir_list(DIR_LIST * d1,DIR_LIST * d2);

void mp_interval();
void hangup_watchdog();

extern SEM	tick_que_lock;
extern SEM	tick_que_lock_2;
unsigned int startup_time;
extern int stab_status;
/*
int * task_flag;
*/
int * task_timer;
TICK_QUE ** task_target;
int * thread_id;
int cpu_nos;
extern int regist_time;
int regist_zero;
SYS_QUEUE mp_task_que;
SYS_QUEUE mp_task_que_2[GRUE_2_NOS];
AVT_NODE * mp_task_que_index;
unsigned int tqt_tat[TQT_MAX];

void set_idle_interval(float);
void idle_check_task();
int idle_cnt,idle_reset_time;
void mp_task_que_grue();
void mp_task_que_2_grue();

int smap_time_all;
int all_count;
int insert_smap_count;
int smap_start_time,smap_end_time;
int smap_waiting_time;
void gc_mp_task_t(MP_TASK_T * t);
void gc_get_mp_task_t(MP_TASK_T * t);


void
smap_count_up(int time_all);

void
_smap_count_up(int time_all)
{
	smap_time_all += time_all;
	all_count ++;
}

void
smap_count_up(int time_all)
{
	lock_task(tick_que_lock_2);
	_smap_count_up(time_all);
	unlock_task(tick_que_lock_2,"smap_count_up");
}

void
smap_insert_waiting_time(int tim);

void
smap_insert_waiting_time(int tim)
{
	lock_task(tick_que_lock_2);
	smap_waiting_time += tim;
	unlock_task(tick_que_lock_2,"smap_count_up");
}


void
tick_report()
{
	log_printf(LOG_SYSTEM,LOG_LAYER_XL,0,"FILE DESCRIPTOR %i %i",
		s_check_resource2(0),
		s_check_resource3());
	
}


void
start_task()
{
int cpu;
int interval;
int i;

	new_tick(tick_report,3600,0);

	memset(&mp_task_que,0,sizeof(SYS_QUEUE));
	mp_task_que.flags = QF_STACK;
	mp_task_que.key_func = mp_task_que_grue;
	mp_task_que.gc_func = gc_mp_task_t;
	mp_task_que.gc_get = gc_get_mp_task_t;
	mp_task_que.pri = PRI_FETCH;
	mp_task_que.key_limit = 50;
	setup_queue(&mp_task_que);

	for ( i = 0 ; i < GRUE_2_NOS ; i ++ ) {
		memset(&mp_task_que_2[i],0,sizeof(SYS_QUEUE));
		mp_task_que_2[i].flags = QF_FIFO|QF_HIGH;
		mp_task_que_2[i].key_func = mp_task_que_2_grue;
		mp_task_que_2[i].gc_func = gc_mp_task_t;
		mp_task_que_2[i].gc_get = gc_get_mp_task_t;
		mp_task_que_2[i].pri = PRI_FETCH;
		setup_queue(&mp_task_que_2[i]);
	}

	mp_task_que_2[GRUE_2_ACRP_2].total_limit = 1;

	default_silent_timeout_table[XLA_CONNECT]
		= MP_TASK_HANGUP_LIMIT/3; 
 
	interval = mp_counter();
	set_idle_interval(0);

	cpu_nos = cpu = 2*sys_param.cpu;

	log_printf(LOG_SYSTEM,LOG_LAYER_GB,0,"management process (MP) is comming up : status = %c",
			stab_status);

/*
	task_flag = d_alloc((cpu+1)*sizeof(int));
*/
	task_timer = d_alloc((cpu+1)*sizeof(int));
	task_target = d_alloc((cpu+1)*sizeof(TICK_QUE*));
	thread_id = d_alloc((cpu+1)*sizeof(int));

	for ( cpu = 0 ; cpu < cpu_nos ; cpu ++ )
		create_task(mp_interval,cpu,PRI_FETCH);

/*
	create_task(hangup_watchdog,cpu,PRI_FETCH);
*/
	create_task(idle_check_task,0,PRI_FETCH);

	trace_mapping();
	trace_crd_routing(0);
	insert_tick_que(interval*4,0,TQT_MPC,TQL_NORMAL);
	startup_time = get_xltime();

	insert_tick_que(20,0,TQT_LGC,TQL_NORMAL);
}

MP_TASK_T *
new_mp_task_t()
{
MP_TASK_T * ret;
	ret = new_queue_node(sizeof(*ret));
	memset(ret,0,sizeof(*ret));
	return ret;
}


void
gc_mp_task_t(MP_TASK_T * t)
{
	gc_gb_sexp(t->sexp);
}

void
gc_get_mp_task_t(MP_TASK_T * t)
{
	lock_mem();
	gc_set_nl(t->sexp,gc_gb_sexp);
	unlock_mem();
}

int
mp_task_index_cmp(MP_TASK_T * t1,MP_TASK_T * t2)
{
	if ( t1->tq->type < t2->tq->type )
		return -1;
	if ( t1->tq->type > t2->tq->type )
		return 1;
	return l_strcmp(t1->tq->filename,t2->tq->filename);
}

int
print_index(AVT_NODE * a)
{
MP_TASK_T * tt;
	tt = a->data;
	if ( tt->tq ) {
		if ( tt->tq->filename ) {
			ss_printf("\ttype:%i %ls\n",
				tt->tq->type,
				tt->tq->filename);
		}
		else {
			ss_printf("\ttype:%i\n",tt->tq->type);
		}
	}
	else {
		ss_printf("\tUnknown\n");
	}
	return 0;
}


void
_free_mp_task_t(MP_TASK_T * tt,int avt_flag)
{
unsigned int tat;
AVT_NODE * a1;

	if ( tt->tq && tt->tq->filename && avt_flag ) {
		a1 = avt_delete(&mp_task_que_index,tt,mp_task_index_cmp);
		if ( a1 )
			d_f_ree(a1);
	}


	if ( tt->tq && tt->tq->type == TQT_SMAP ) {
		_smap_count_up(get_xltime() - tt->ins_time);
		if ( insert_smap_count == all_count ) {
		int n;
			n = get_xltime();
			ss_printf(
			"SMAP COMPLETE %i %i %i %i (%f %f %f)\n",
				n - smap_start_time,
				smap_time_all,
				smap_waiting_time,
				all_count,
				((double)(n - smap_start_time))/all_count,
				((double)smap_time_all)/all_count,
				((double)(smap_time_all - 
					smap_waiting_time))/all_count);
			log_printf(LOG_TEST,LOG_LAYER_GB,0,
				"SMAP-COMPLETE %i %i %i %i %f %f %f\n",
				n - smap_start_time,
				smap_time_all,
				smap_waiting_time,
				all_count,
				((double)(n - smap_start_time))/all_count,
				((double)smap_time_all)/all_count,
				((double)(smap_time_all - 
					smap_waiting_time))/all_count);
		}
	}

	if ( tt->tq ) {
		tat = get_xltime() - tt->ins_time;
		if ( tqt_tat[tt->tq->type] == 0 )
			tqt_tat[tt->tq->type] = tat;
		if ( tqt_tat[tt->tq->type] < tat )
			tqt_tat[tt->tq->type] =
				0.9*tqt_tat[tt->tq->type] + 0.1*tat;
		else	
			tqt_tat[tt->tq->type] =
				0.999*tqt_tat[tt->tq->type] + 0.001*tat;
	}
	if ( tt->h.key )
		d_f_ree(tt->h.key);
	if ( tt->tq )
		free_tick_que(tt->tq);
	if ( tt->free_t )
		(*tt->free_t)(tt);
	memset(tt,0,sizeof(*tt));
	d_f_ree(tt);


//	print_key_list(&mp_task_que);

}

void
free_mp_task_t(MP_TASK_T * tt)
{
	lock_task(tick_que_lock_2);
	_free_mp_task_t(tt,1);
	unlock_task(tick_que_lock_2,"free_mp_task_t");
}

void
mp_task_que_grue()
{
MP_TASK_T * tt;
L_CHAR * key;
L_CHAR * key_copy;
XL_INTERPRETER * xli;
MP_TASK_ENV e;


	key = touch_qkey(&mp_task_que);
	if ( key == 0 )
		return;


	key_copy = ll_copy_str(key);

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

	e.ses = open_session(SEST_OPTIMIZE);
	e.count = 0;


	for ( ; ; ) {
		gc_push(0,0,"mp_task_que_grue");
		tt = delete_queue(&mp_task_que,sq_key_cond,key,0);
		if ( tt == 0 ) {
		 	gc_pop(0,0);
			break;
		}
		(*tt->op)(&e,tt);
		gc_pop(0,0);
	}


	close_session(e.ses);

	close_self_interpreter();

	release_qkey(&mp_task_que,key);
	d_f_ree(key);

	d_f_ree(key_copy);
}

int
grue_2_cond(SYS_QUEUE * q,MP_TASK_T * t,L_CHAR * key)
{
int ret;
	if ( l_strcmp(key,t->h.key) )
		return -1;
	if ( t->sexp == 0 )
		return 0;
	ret = check_delay(t->sexp,(int)q);

	if ( ret == CDT_WAIT )
		return -1;
	if ( ret == CDT_WAIT_ERR ) {
		sexp_reconnect(t->sexp);
		return -1;
	}
	return 0;
}

void
mp_task_que_2_grue(TKEY d)
{
MP_TASK_T * tt;
L_CHAR * key;
XL_INTERPRETER * xli;
MP_TASK_ENV e;
SYS_QUEUE * q;

	q = (SYS_QUEUE*)GET_TKEY(d);

	key = touch_qkey(q);
	if ( key == 0 )
		return;

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

	e.ses = open_session(SEST_OPTIMIZE);
	e.count = 0;

	for ( ; ; ) {
		gc_push(0,0,"mp_task_que_grue");
		if ( check_queue(q,sq_key_cond,key) == 0 ) {
			gc_pop(0,0);
			break;
		}
		tt = delete_queue(q,grue_2_cond,key,1);
		if ( tt == 0 ) {
		 	gc_pop(0,0);
			break;
		}
		(*tt->op)(&e,tt);
		gc_pop(0,0);
	}


	close_session(e.ses);

	close_self_interpreter();

	release_qkey(q,key);
	d_f_ree(key);
}

void
insert_mp_task_que(MP_TASK_T * tt)
{
char buf[100];
AVT_NODE *a1,* a2;
int i;
int cnt,_cnt,_i;

	_i = 0;
	_cnt = 0x7fffffff;
	for ( i = 0 ; i < cpu_nos ; i ++ ) {
		if ( tt->tq )
			sprintf(buf,"mpt-%i[%i]-%i",
				(int)tt->op,tt->tq->type,i);
		else	sprintf(buf,"mpt-%i-%i",(int)tt->op,i);
		cnt = get_key_count(&mp_task_que,l_string(std_cm,buf));
		if ( _cnt > cnt ) {
			_i = i;
			_cnt = cnt;
		}
	}
	if ( tt->tq )
		sprintf(buf,"mpt-%i[%i]-%i",
			(int)tt->op,tt->tq->type,_i);
	else	sprintf(buf,"mpt-%i-%i",(int)tt->op,_i);

	tt->h.key = nl_copy_str(std_cm,buf);
	tt->ins_time = get_xltime();

	lock_task(tick_que_lock_2);
	if ( tt->tq && tt->tq->filename ) {
		a1 = d_alloc(sizeof(*a1));
		a1->data = tt;
		a2 = avt_insert(&mp_task_que_index,a1,mp_task_index_cmp);
		if ( a1 == a2 ) {
			unlock_task(tick_que_lock_2,"insert_mp_task_que");
			insert_queue(&mp_task_que,tt,1);
		}
		else {
			d_f_ree(a1);
			_free_mp_task_t(tt,0);
			unlock_task(tick_que_lock_2,"insert_mp_task_que");
		}
	}
	else {
		unlock_task(tick_que_lock_2,"insert_mp_task_que");
		insert_queue(&mp_task_que,tt,1);
	}
}

int
mp_task_que_check(SYS_QUEUE * q,MP_TASK_T * a,void * b)
{
int len;
	if ( a->tq == 0 )
		return -1;
	if ( a->tq->filename == 0 )
		return -1;
	len = l_strlen(a->tq->filename);
	if ( l_strcmp(&a->tq->filename[len-4],
			l_string(std_cm,".map")) == 0 )
		return 0;
	return -1;
}

int
get_map_nos()
{
	return check_queue(&mp_task_que,mp_task_que_check,0);
}


void
idle_check_task()
{
unsigned int t;
float p;
int check_interval;


	idle_reset_time = get_xltime();
	idle_cnt = 0;
	check_interval = 10;
	for ( ; ; ) {
		if ( get_xltime() - idle_reset_time
				>= check_interval ) {
			p = (float)idle_cnt 
				/ (get_xltime() - idle_reset_time);
			set_idle_interval(p);
			idle_reset_time = get_xltime();
			idle_cnt = 0;

			check_interval *= 2;
			if ( check_interval > MAPPING_IDLE_CHECK_INTERVAL )
				check_interval = MAPPING_IDLE_CHECK_INTERVAL;
		}
		t = get_comesoon();
/*
printf("idle %i %i\n",t - get_xltime(),idle_interval);
*/
		if ( (t - get_xltime()) >= MAPPING_PING_INTERVAL_UNIT )
			idle_cnt ++;
		sleep_sec(1);
	}
}


int
mp_live()
{

	if ( startup_time == 0 )
		return 0;
	if ( get_xltime() - startup_time < MP_LIVE_MAX )
		return 0;
	exit_stabilizer('r');
	exit(0);
	return 0;
}

void
hangup_watchdog()
{
int i;
unsigned int t,tt;
XL_INTERPRETER * xli;
TICK_QUE * tq;

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

	for ( ; ; ) {
		t = tt = get_xltime();
		tq = 0;
		for ( i = 1 ; i <= cpu_nos ; i ++ ) 
			if ( task_timer[i] && task_timer[i] < t ) {
				t = task_timer[i];
				tq = task_target[i];
			}
		if ( t <= tt - MP_TASK_HANGUP_LIMIT ) {
			gc_push(0,0,"hangup_watchdog");
			log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"MP hangup!!");
			ss_printf("MP hangup!!");
			if ( tq ) {
				if ( tq->filename )
				  log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
						"n:%s t:%i tid:%i\n",
						n_string(std_cm,tq->filename),
						tq->type,
						get_tid());
				else
					log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
						"n:0 t:%i tid:%i\n",
						tq->type,
						get_tid());
			}
			gc_pop(0,0);

{
char buffer[50];
	sprintf(buffer,"ps -fA | egrep xl > hangup.txt");
	system(buffer);
	sprintf(buffer,"gcore %i\n",(int)getpid());
	system(buffer);
}

			exit_stabilizer('r');
			exit(1);
		}

		sleep_sec(t + MP_TASK_HANGUP_LIMIT - tt);
	}
}


int
_tqt_ex_wait(SYS_QUEUE * q,MP_TASK_T * tt,int * _ret)
{
	if ( tt->tq == 0 )
		return 0;
	if ( tt->tq->type <=  TQT_MCRD_48sec ) {
		*_ret = 1;
		return CQ_END;
	}
	return 0;
}


void
tqt_ex_wait(MP_TASK_ENV * e,unsigned int time)
{
unsigned int t;
int _ret;
int lim;
int i;
	for ( ; ; ) {
		lim = 0;
		for ( i = 1 ; i <= TQT_MCRD_48sec ; i ++ )
			lim += tqt_tat[i];
//ss_printf("TQT %i\n",lim);
		lim = (lim/TQT_MCRD_48sec)*MPI_EX_WAIT_LIMIT_RATE;
		if ( lim > MPI_EX_WAIT_LIMIT_MAX )
			lim = MPI_EX_WAIT_LIMIT_MAX;
		if ( lim < MPI_EX_WAIT_LIMIT_MIN )
			lim = MPI_EX_WAIT_LIMIT_MIN;
//ss_printf("TQT LIMIT = %i\n",lim);

		t = get_xltime();
		if ( t - time > lim )
			break;
		if ( e->count && e->count < 1000 )
			break;
		if ( e->count >= 1000 )
			e->count = 0;
		_ret = 0;
		check_queue(&mp_task_que,_tqt_ex_wait,&_ret);
		if ( _ret == 0 )
			break;
		sleep_sec(10);
	}
}

void
tqt_ex_crd_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{


//ss_printf("EX CRD %ls\n",tt->tq->filename);

	tqt_ex_wait(e,tt->ins_time);

//ss_printf("EX CRD %ls EX\n",tt->tq->filename);

	e->count ++;
	insert_tick_que(
			2*MODIFY_CHECK_INTERVAL,
			tt->tq->filename,TQT_CRD,TQL_NORMAL);
//ss_printf("EX CRD %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}


void
tqt_ex_prg_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{

int ret;
//URL u;
L_CHAR * f;

//ss_printf("EX PRG %ls\n",tt->tq->filename);

	tqt_ex_wait(e,tt->ins_time);

//ss_printf("EX PRG %ls EX\n",tt->tq->filename);

	e->count ++;

	if ( memcmp(tt->tq->filename,l_string(std_cm,"/xlp:"),
			5*sizeof(L_CHAR)) == 0 ) {
//ss_printf("EX PRG SHIFT\n");
		ret = mpi_purge(f = &tt->tq->filename[1]);
	}
	else	ret = mpi_purge(f = tt->tq->filename);

/*
	if ( ret == 0 ) {
ss_printf("EX PRG LLT\n");
		get_url2(&u,f);
		d_f_ree(u.resource);
		d_f_ree(u.agent);
		d_f_ree(u.db);
		u.resource = u.agent = u.db = 0;
		f = ll_copy_str(get_url_str2(&u));
		insert_tick_que(0,f,TQT_LLT,TQL_ACRP);
		d_f_ree(f);
	}
*/

ss_printf("EX PRG %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}

void
tqt_llt(MP_TASK_ENV * e,MP_TASK_T * tt)
{
L_CHAR * target;
URL u;
XL_SEXP * s;
XL_SEXP * pri,* cid;
int * _cid;
XL_SEXP * ret;

ss_printf("LLT %ls\n",tt->tq->filename);


	if ( memcmp(tt->tq->filename,l_string(std_cm,"/xlp:"),
			5*sizeof(L_CHAR)) == 0 ) {
ss_printf("LLT SHIFT\n");
		target = &tt->tq->filename[1];
	}
	else	target = tt->tq->filename;

	get_url2(&u,target);

	s = List(
		n_get_symbol("MPgetLoopLockTable"),
		-1);

	ret = remote_session(
		gblisp_top_env0,
		e->ses,
		&u,
		l_string(std_cm,"gbstd"),
		l_string(std_cm,"user"),
		l_string(std_cm,"Get"),
		List(s,-1),
		0,0,0,0);

	if ( get_type(ret) == XLT_ERROR ) {
ss_printf("LLT ERR ");
print_sexp(s_stdout,ret,0);
ss_printf("\n");
	}
	else {
		for ( ; get_type(ret) == XLT_PAIR ; ret = cdr(ret) ) {
			s = car(ret);
			if ( get_type(s) != XLT_PAIR )
{
ss_printf("LLT ? 1\n");
				continue;
}
			pri = get_el(s,0);
			if ( get_type(pri) != XLT_STRING )
{
ss_printf("LLT ? 2\n");
				continue;
}
			cid = get_el(s,1);
			_cid = list2cid(cid);
			if ( _cid == 0 )
{
ss_printf("LLT ? 3\n");
				continue;
}
			search_ipt(_cid,pri->string.data,0,2);
			d_f_ree(_cid);
		}
	}

	sleep_sec(5);

ss_printf("LLT %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}



int
get_crd_tat()
{
int sum;
	sum = tqt_tat[TQT_CRD];
	sum += tqt_tat[TQT_CRD_2sec];
	sum += tqt_tat[TQT_CRD_48sec];
	sum += tqt_tat[TQT_MCRD];
	sum += tqt_tat[TQT_MCRD_2sec];
	sum += tqt_tat[TQT_MCRD_48sec];
	sum = sum/6;

	if ( sum <= 0 )
		return 1;
	if ( sum > 10*60 )
		sum = 10*50;
	return sum;
}


void
tqt_crd_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int tim;

//ss_printf("CRD %ls\n",tt->tq->filename);
	tim = get_xltime();
	if ( check_my_acrp(e->ses,tt->tq->filename,0) < 0 ) {
		insert_tick_que(
			2*get_crd_tat(),
			tt->tq->filename,TQT_CRD_2sec,TQL_ACRP);
	}
	else tick_lump(tt->tq,tim);
//ss_printf("CRD %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}


void
tqt_crd_op_2(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int tim;

//ss_printf("CRD_2 %ls\n",tt->tq->filename);
	tim = get_xltime();
	if ( check_my_acrp(e->ses,tt->tq->filename,0) < 0 ) {
		insert_tick_que(
			4*get_crd_tat(),
			tt->tq->filename,TQT_CRD_48sec,TQL_ACRP);
	}
	else tick_lump(tt->tq,tim);
//ss_printf("CRD_2 %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}

void
tqt_crd_op_48(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int tim;

//ss_printf("CRD_48 %ls\n",tt->tq->filename);
	tim = get_xltime();
	if ( check_my_acrp(e->ses,tt->tq->filename,0) < 0 ) {
		insert_tick_que(
			8*get_crd_tat(),
			tt->tq->filename,TQT_CRD_48sec,TQL_ACRP);
	}
	else tick_lump(tt->tq,tim);
//ss_printf("CRD_48 %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}

void
tqt_mcrd_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int tim;

//ss_printf("M-CRD %ls\n",tt->tq->filename);
	tim = get_xltime();
	check_my_acrp(e->ses,tt->tq->filename,1);
	if ( check_my_acrp(e->ses,tt->tq->filename,0) < 0 ) {
		insert_tick_que(
			2*get_crd_tat(),
			tt->tq->filename,TQT_MCRD_2sec,TQL_ACRP);
	}
	else tick_lump(tt->tq,tim);
//ss_printf("M-CRD %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}

void
tqt_mcrd_op_2(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int tim;

//ss_printf("M-CRD_2 %ls\n",tt->tq->filename);
	tim = get_xltime();
	check_my_acrp(e->ses,tt->tq->filename,1);
	if ( check_my_acrp(e->ses,tt->tq->filename,0) < 0 ) {
		insert_tick_que(
			4*get_crd_tat(),
			tt->tq->filename,TQT_MCRD_48sec,TQL_ACRP);
	}
	else tick_lump(tt->tq,tim);
//ss_printf("M-CRD_2 %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}


void
tqt_mcrd_op_48(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int tim;

//ss_printf("M-CRD_48 %ls\n",tt->tq->filename);
	tim = get_xltime();
	check_my_acrp(e->ses,tt->tq->filename,1);
	if ( check_my_acrp(e->ses,tt->tq->filename,0) < 0 ) {
		insert_tick_que(
			8*get_crd_tat(),
			tt->tq->filename,TQT_MCRD_48sec,TQL_ACRP);
	}
	else tick_lump(tt->tq,tim);
//ss_printf("M-CRD_48 %ls END\n",tt->tq->filename);
	free_mp_task_t(tt);
}


void
tqt_lmp_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
	check_my_lump(e->ses,tt->tq->filename);
	free_mp_task_t(tt);
}

void
tqt_map_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int interval;
/*
ss_printf("MAP %ls %ls\n",tt->h.key,tt->tq->filename);
*/
	interval = ping_mapping(e,tt,0);
	if ( interval < 0 ) {
		if ( interval == -1 )
			free_mp_task_t(tt);
		return;
	}
	insert_tick_que(interval,tt->tq->filename,TQT_MAP,TQL_NORMAL);
/*
ss_printf("MAP %ls %ls END\n",tt->h.key,tt->tq->filename);
*/
	free_mp_task_t(tt);
}


void
tqt_tmp_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int interval;
	interval = ping_mapping(e,tt,1);
	if ( interval < 0 ) {
		if ( interval == -1 )
			free_mp_task_t(tt);
		return;
	}
		insert_tick_que(interval,tt->tq->filename,
			TQT_MAP,TQL_NORMAL);
	free_mp_task_t(tt);
}


void
tqt_smap_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int interval;
/*
ss_printf("SMAP %ls %ls\n",tt->h.key,tt->tq->filename);
*/

	smap_insert_waiting_time(get_xltime() - tt->ins_time);

	interval = ping_mapping(e,tt,2);


	if ( interval < 0 ) {
		if ( interval == -1 )
			free_mp_task_t(tt);
		return;
	}
	insert_tick_que(interval,tt->tq->filename,
		TQT_MAP,TQL_NORMAL);
/*
ss_printf("SMAP %ls %ls END\n",tt->h.key,tt->tq->filename);
*/
	free_mp_task_t(tt);
}

void
tqt_mpc_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int interval;
	interval = mp_counter();
	trace_crd_mapping();
	insert_tick_que(interval,0,TQT_MPC,TQL_NORMAL);
	free_mp_task_t(tt);
}

void
tqt_dmap_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
	if ( ping_mapping(e,tt,3) >= -1 )
		free_mp_task_t(tt);
}


void
tqt_fmap_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int interval;
	interval = ping_mapping(e,tt,1);
	if ( interval < 0 ) {
		if ( interval == -1 )
			free_mp_task_t(tt);
		return;
	}
	insert_tick_que(interval,tt->tq->filename,
		TQT_MAP,TQL_NORMAL);
	free_mp_task_t(tt);
}

void
tqt_lgc_op(MP_TASK_ENV * e,MP_TASK_T * tt)
{
int interval;
	interval = get_idle_interval();
	lump_gc_path(e->ses);
	insert_tick_que(
		interval,
		0,
		TQT_LGC,TQL_NORMAL);
	free_mp_task_t(tt);
}


void
mp_interval(TKEY d)
{
TICK_QUE * t1;
int ses;
XL_INTERPRETER * xli;
int cpu;
int i;
int t,now;
MP_TASK_T * tt;


	cpu = (int)GET_TKEY(d);


	thread_id[cpu] = get_tid();
	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

	ses = open_session(SEST_OPTIMIZE);
	for ( ; ; ) {

		t = get_comesoon();
		now = get_xltime();
		if ( t > 0 ) {
			t = t - now;
			if ( t < -THRESH_HOLD ) {
				if ( now - regist_zero > 5 ) {
					regist_time *= 0.8;
					if ( regist_time == 1 )
						regist_time = 0;
					regist_zero = now;
				}
				if ( regist_time < (-t-THRESH_HOLD)*2 )
					regist_time = (-t-THRESH_HOLD)*2;
			}
			else if ( regist_time > 0 ) {
				if ( now - regist_zero > 5 ) {
					regist_time *= 0.8;
					regist_zero = now;
				}
			}
		}
		else if ( regist_time > 0 ) {
			if ( now - regist_zero > 5 ) {
				regist_time *= 0.8;
				if ( regist_time == 1 )
					regist_time = 0;
				regist_zero = now;
			}
		}



		t1 = 0;

		task_timer[cpu] = 0;
		task_target[cpu] = 0;

		for ( i = 0 ; i < TQL_MAX ; i ++ ) {
			t1 = delete_tick_que(i);
			if ( t1 )
				break;
		}
		if ( t1 == 0 ) {

			if ( mp_live() )
				return;

			sleep_sec(1);


/*
printf("loop\n");
*/
			continue;
		}


		task_timer[cpu] = get_xltime();
		task_target[cpu] = t1;
/*
if ( t1->filename )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,">>> %s %i %i\n",n_string(std_cm,t1->filename),t1->type,get_tid());
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,">>> %i %i\n",t1->type,get_tid());
*/
/*
if ( t1->filename )
ss_printf(">>> %s %i %i\n",n_string(std_cm,t1->filename),t1->type,get_tid());
else
ss_printf(">>> %i %i\n",t1->type,get_tid());
*/
		gc_push(0,0,"acrp_task");
		tt = new_mp_task_t();
		tt->tq = t1;


		switch ( t1->type ) {
		case TQT_CRD:
			tt->op = tqt_crd_op;
			insert_mp_task_que(tt);
			break;
		case TQT_CRD_2sec:
			tt->op = tqt_crd_op_2;
			insert_mp_task_que(tt);
			break;
		case TQT_CRD_48sec:
			tt->op = tqt_crd_op_48;
			insert_mp_task_que(tt);
			break;
		case TQT_MCRD:
			tt->op = tqt_mcrd_op;
			insert_mp_task_que(tt);
			break;
		case TQT_MCRD_2sec:
			tt->op = tqt_mcrd_op_2;
			insert_mp_task_que(tt);
			break;
		case TQT_MCRD_48sec:
			tt->op = tqt_mcrd_op_48;
			insert_mp_task_que(tt);
			break;
		case TQT_LMP:
			tt->op = tqt_lmp_op;
			insert_mp_task_que(tt);
			break;
		case TQT_MAP:
			tt->op = tqt_map_op;
			insert_mp_task_que(tt);
			break;
		case TQT_TMP:
			tt->op = tqt_tmp_op;
			insert_mp_task_que(tt);
			break;
		case TQT_MPC:
			tt->op = tqt_mpc_op;
			insert_mp_task_que(tt);
			break;
		case TQT_DMAP:
			tt->op = tqt_dmap_op;
			insert_mp_task_que(tt);
			break;
		case TQT_FMAP:
			tt->op = tqt_fmap_op;
			insert_mp_task_que(tt);
			break;
		case TQT_SMAP:
			tt->op = tqt_smap_op;

			lock_task(tick_que_lock_2);
			insert_smap_count ++;
			unlock_task(tick_que_lock_2,"tqt_smap");


			insert_mp_task_que(tt);
			break;
		case TQT_LGC:
			tt->op = tqt_lgc_op;
			insert_mp_task_que(tt);
			break;

		case TQT_EX_CRD:
			tt->op = tqt_ex_crd_op;
			insert_mp_task_que(tt);
			break;
		case TQT_EX_PRG:
			tt->op = tqt_ex_prg_op;
			insert_mp_task_que(tt);
			break;

		case TQT_LLT:
			tt->op = tqt_llt;
			insert_mp_task_que(tt);
			break;

		default:
			er_panic("mp_interval");
		}
		gc_pop(0,0);


	}
}

void
insert_all_files()
{
L_CHAR * lpath;
DIR_LIST * d, * d1, * d2;
struct path_pair * wp;
	gc_push(0,0,"insert_all_files");
        d = NULL;
        for(wp=start;wp != NULL;wp=wp->next)
        {
                lpath = get_append_path(wp->docs_path,"/**/*.crd");
                d1 = get_dir(n_string(std_cm,lpath),0,0,0,DLF_FILE);
                d_f_ree(lpath);
                d = marge_dir_list(d,d1);
                lpath = get_append_path(wp->docs_path,"/*.crd");
                d2 = get_dir(n_string(std_cm,lpath),0,0,0,DLF_FILE);
                d_f_ree(lpath);
                d = marge_dir_list(d,d2);
        }
        for ( d1 = d ; d1 ; d1 = d1->next ) {
                lpath = get_url_path(
			l_string(std_cm,d1->name),0);
		if ( lpath == 0 )
			continue;
                insert_tick_que(0,lpath,TQT_CRD,TQL_ACRP);
		d_f_ree(lpath);
        }
        free_dir_list(d2);
	gc_pop(0,0);
}

