/**********************************************************************
 
	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	"memory_debug.h"
#include	"xl.h"
#include	"xlerror.h"
#include	"utils.h"
#include	"pri_level.h"

XL_SEXP * gb_MPRouting();

typedef struct routing_t {
	Q_HEADER	h;
	XL_SEXP *	s;
	D_SEXP *	d;
	XL_FILE *	file;
	int		line;
} ROUTING_T;

SYS_QUEUE routing_que;

void gc_rque();
void gc_get_rque();
void gc_gb_sexp();
void gc_d_sexp();
void gc_gb_file();
void routing_task();

void
init_gb_MPRouting(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"MPRouting"),
		get_func_prim(gb_MPRouting,FO_APPLICATIVE,0,3,3));
	memset(&routing_que,0,sizeof(SYS_QUEUE));
	routing_que.flags = QF_FIFO|QF_HIGH;
	routing_que.gc_func = gc_rque;
	routing_que.gc_get = gc_get_rque;
	routing_que.key_func = 0;
	routing_que.pri = PRI_XL_RELAY;
	setup_queue(&routing_que);

	create_task(routing_task,0,PRI_XL_RELAY);
}


void
gc_rque(ROUTING_T * n)
{
	gc_gb_sexp(n->s);
	gc_d_sexp(n->d);
	gc_gb_file(n->file);
}

void
gc_get_rque(ROUTING_T * n)
{
	lock_mem();
	gc_set_nl(n->s,gc_gb_sexp);
	gc_set_nl(n->d,gc_d_sexp);
	gc_set_nl(n->file,gc_gb_file);
	unlock_mem();
}


int
routing_t_cond(SYS_QUEUE * q,ROUTING_T * n)
{
	if ( check_delay(n->s,(int)q) == CDT_WAIT )
		return -1;
	return 0;
}

void
routing_task()
{
XL_INTERPRETER * xli;
ROUTING_T * r;
XL_SEXP * ret;

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

		gc_push(0,0,"routing_task");

		r = delete_queue(&routing_que,routing_t_cond,0,1);
		ret = r->s;
		if ( get_type(ret) == XLT_ERROR ) {
			if ( ret->err.code == XLE_PROTO_ACCESS_STREAM ) {
				ret = get_error(
					r->file,
					r->line,
					XLE_SYSTEM_INTERNAL,
					l_string(std_cm,"MProuting"),
					n_get_string("server is down"));
			}
		}

		set_d_sexp(r->d,ret);

		d_f_ree(r);

		gc_pop(0,0);
	}
}

XL_SEXP *
gb_MPRouting(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf)
{
URL u;
XL_SEXP * ret;
ROUTING_T * n;
static ses = -1;

	get_url2(&u,l_string(std_cm,"xlp://localhost:9100/"));
	u.port = get_mp_port();

	if ( ses < 0 )
		ses = open_session(SEST_OPTIMIZE);
	ret = remote_session(
		gblisp_top_env0,
		ses,
		&u,
		l_string(std_cm,"gbmp"),
		l_string(std_cm,"user"),
		l_string(std_cm,"Get"),
		List(s,-1),
		0,0,0);

	n = new_queue_node(sizeof(*n));
	n->h.key = 0;
	n->s = ret;
	ret = new_d_sexp(&n->d);
	n->file = s->h.file;
	n->line = s->h.line;
	insert_queue(&routing_que,n,1);
	free_url(&u);
	return ret;
}


