/**********************************************************************
 
	Copyright (C) 2005- 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 	"resource.h"
#include	"pri_level.h"
#include	"gbview.h"
#include	"memory_debug.h"
#include	"memory_routine.h"
#include	"resource.h"
#include	"rs_cache.h"
#include	"xlerror.h"
#include	"win_flame.h"
#include	"lock_level.h"


#define QUEUE_LENGTH_2 	5

void gc_tick_notin_tick();

void
gc_omx(MATRIX_TOKEN * n);
void
gc_omx_get(MATRIX_TOKEN * n);


/*
Layer for R64/CR format

0
1	VISUAL DATA (RGB)
2	DATA FROM NETWORK (SEXP)

*/

#define INVALID_TRANS_TIMEOUT		5
#define INVALID_TRANS_CR_ERR_COUNT	5
#define QUEUE_LENGTH			10
#define TN_OFFSET			10

typedef struct omx_open_work {
	RESOURCE *		r;
	int			(*get_query)(
					XL_SEXP ** query_p,
					XL_SEXP ** tmp_p,
					I_RECT * ir,
					MATRIX_TOKEN * t);
	int			trans_timeout;
	int			cr_err_count;
} OMX_OPEN_WORK;


typedef struct omx_token_work {
	MATRIX_TOKEN *		next;
	XL_SEXP *		data;
	XL_SEXP * 		tmp;
	int			w;
	int			h;
	int			e_flag;
	int			aboat_flag;
} OMX_TOKEN_WORK;

typedef struct omx_dirty {
	struct omx_dirty *	next;
	RESOURCE *		r;
	GB_RECT			rct;
} OMX_DIRTY;

int old_matrix_read_net(MATRIX_TOKEN * t);
void mx_task1(TKEY d);
void mx_task2(TKEY d);
int get_query_omx_r64(
	XL_SEXP ** query_p,
	XL_SEXP ** tmp_p,
	I_RECT * ir,
	MATRIX_TOKEN * t);
int get_query_omx_cr(
	XL_SEXP ** query_p,
	XL_SEXP ** tmp_p,
	I_RECT * ir,
	MATRIX_TOKEN * t);
void omx_new_token(MATRIX_TOKEN *,int);
void omx_free_token(MATRIX_TOKEN * ,int);
void omx_close_matrix_file(MATRIX * );
OMX_OPEN_WORK * get_omx_work(RESOURCE * r);
void omx_trigger(int type,void *t);
MATRIX_TOKEN *
omx_dirty_insert(MATRIX_TOKEN * n3,MATRIX_TOKEN * n_end);
void _exec_dirty(int type);
void insert_dirty(RESOURCE * r,GB_RECT * rct);
void aboat_old_matrix(MATRIX_TOKEN * t);


void
__exec_dirty(TKEY td);

SYS_QUEUE mx_que1;
SYS_QUEUE mx_que2;
OMX_DIRTY * dirty_list;
int	dirty_time;
SEM	omx_lock;
int dirty_flags;

void
init_old_matrix()
{
void mx_task1();
void mx_task2();


	omx_lock = new_lock(LL_OMX);

	memset(&mx_que1,0,sizeof(SYS_QUEUE));
	mx_que1.flags = QF_STACK;
	mx_que1.gc_func = gc_omx;
	mx_que1.gc_get = gc_omx_get;
	mx_que1.key_func = mx_task1;
	mx_que1.pri = PRI_FETCH_MOST_STRONG;
	setup_queue(&mx_que1);

	memset(&mx_que2,0,sizeof(SYS_QUEUE));
	mx_que2.flags = QF_FIFO;
	mx_que2.gc_func =gc_omx;
	mx_que2.gc_get = gc_omx_get;
	mx_que2.key_func = mx_task2;
	mx_que2.total_limit = QUEUE_LENGTH_2*2;
	mx_que2.key_limit = QUEUE_LENGTH_2;
	mx_que2.pri = PRI_FETCH_MOST_STRONG;
	setup_queue(&mx_que2);
	create_task(__exec_dirty,0,PRI_FETCH_MOST_STRONG);
}


OMX_OPEN_WORK * 
get_omx_work(RESOURCE * r)
{
OMX_OPEN_WORK * w;
	w = d_alloc(sizeof(*w));
	w->r = r;
	w->trans_timeout = INVALID_TRANS_TIMEOUT;
	w->cr_err_count = INVALID_TRANS_CR_ERR_COUNT;
	return w;
}


void * get_omx_r64_work(RESOURCE * r)
{
OMX_OPEN_WORK * w;
	w = get_omx_work(r);
	w->get_query = get_query_omx_r64;
	return w;
}


void * get_omx_cr_work(RESOURCE * r)
{
OMX_OPEN_WORK * w;
	w = get_omx_work(r);
	w->get_query = get_query_omx_cr;
	return w;
}


void
open_old_matrix(MATRIX_TOKEN * t)
{
int err;
MATRIX * m;
MATRIX_PARAM p;
int er;
MATRIX_CHANNEL_INFO inf;
OMX_OPEN_WORK * ow;
RS_BUF b;
int dd;

int err_code;

	err_code = 1;

	m = t->wait_matrix;
	ow = m->open_work;

	/* FILE Name on the cache */

	if ( ow->r->h.cache_file_id == 0 ) {
		memset(&b,0,sizeof(b));
		b.r = ow->r;
		set_rs_resource_cache(&b);
	}

	/* FILE Lock Operation */

	if ( ow->r->h.cache_file_id ) {

		m->filename = get_filepath_from_file_id(ow->r->h.cache_file_id,".mtx");
		err = load_matrix_header(m,O_RDWR,0644);


ss_printf("old_matrix err %i\n",err);
		if ( err == 0 ) {
			memset(&p,0,sizeof(p));
			p.write_file = matrix_standard_write_file;
			p.read_file = matrix_standard_read_file;
			p.read_net = old_matrix_read_net;
			p.close_file = omx_close_matrix_file;
			p.new_token = omx_new_token;
			p.free_token = omx_free_token;
			p.trigger = omx_trigger;

	err_code = 2;
			er = set_matrix_param(m,&p);
			if ( er < 0 )
				goto error;
			goto exist_file;
		}
	}


	memset(&p,0,sizeof(p));
	p.channel_nos = CH_MAX;
	p.total_levels = ow->r->pr64.max_level;
	p.modify_time = ow->r->h.modify;
	p.flags = MPF_CACHE_FILE;
	p.dim = 2;
	p.pri_area[MI_FETCH_1_TP] = PR_UP + 0x2000000;
	p.pri_area[MI_FETCH_1_MD] = PR_UP + 0x2000000;
	p.pri_area[MI_FETCH_1_BT] = PR_UP + 0x2000000;
	p.pri_area[MI_FETCH_2_TP] = PR_UP + 0x2000000;
	p.pri_area[MI_FETCH_2_MD] = PR_UP + 0x2000000;
	p.pri_area[MI_FETCH_2_BT] = PR_UP + 0x2000000;
	p.pri_area[MI_VISU_1_TP] = PR_UP + 0x2000000;
	p.pri_area[MI_VISU_1_MD] = PR_UP + 0x2000000;
	p.pri_area[MI_VISU_1_BT] = PR_UP + 0x2000000;
	p.pri_area[MI_SAVE_TP] = PR_STRT + 0x2000000;
	p.pri_area[MI_SAVE_MD] = PR_STRT + 0x2000000;
	p.pri_area[MI_SAVE_BT] = PR_STRT + 0x2000000;


	p.write_file = matrix_standard_write_file;
	p.read_file = matrix_standard_read_file;
	p.read_net = old_matrix_read_net;
	p.close_file = omx_close_matrix_file;
	p.new_token = omx_new_token;
	p.free_token = omx_free_token;
	p.trigger = omx_trigger;

	er = set_matrix_param(m,&p);
	err_code = 3;
	if ( er < 0 )
		goto error;
	er = set_matrix_dim_divide(m,0,1);		// divide 2^1
	err_code = 4;
	if ( er < 0 )
		goto error;
	er = set_matrix_block_size(m,0,8);		// blocksize = 2^8
	err_code = 5;
	if ( er < 0 )
		goto error;
	er = set_matrix_dim_divide(m,1,1);
	err_code = 6;
	if ( er < 0 )
		goto error;
	er = set_matrix_block_size(m,1,8);
	err_code = 7;
	if ( er < 0 )
		goto error;


	er = set_matrix_pixel_size(m,0,ow->r->pr64.width[0]);
	err_code = 8;
	if ( er < 0 )
		goto error;

	er = set_matrix_pixel_size(m,1,ow->r->pr64.height[0]);
	err_code = 9;
	if ( er < 0 )
		goto error;
	
	inf.data_type = &mx_type_sexp;
	inf.flags = 0;
	inf.default_data = 0;
	er = set_matrix_channel_info(m,CH_NET,&inf);
	err_code = 10;
	if ( er < 0 )
		goto error;

	inf.data_type = &mx_type_uint32_v;
	inf.flags = MF_FILE|MF_VISU;
	dd = C_TRANSPARENT;
	inf.default_data = &dd;
	er = set_matrix_channel_info(m,CH_VISU,&inf);
	err_code = 11;
	if ( er < 0 )
		goto error;

exist_file:

	switch ( ow->r->pr64.type ) {
	case 'P':
	case 'G':
	case 'B':

		set_matrix_cal(m,MI_VISU_1_BT,
			sexp_commands(
				std_cm,
		"<mxFinish",
		"	normal-jump-status=\"MS_OK\"",
		"	err-jump-status=\"MS_PROCESS_ERR_1\"/>",
		"(mxSet 1 ([mxUncompressOldFormat format=\"R64\"] (mxCH 2)))",
			0));
		set_matrix_cal_equ(m,MI_VISU_1_MD,MI_VISU_1_BT);
		set_matrix_cal(m,MI_VISU_1_TP,
			sexp_commands(
				std_cm,
			"(mxSet 1 ([mxUncompressOldFormat format=\"R64\"] (mxCH 2)))",
			0));
		break;
	case '0':
	case '1':
	case '2':

		set_matrix_cal(m,MI_VISU_1_BT,
			sexp_commands(
				std_cm,
		"<mxFinish",
		"	normal-jump-status=\"MS_OK\"",
		"	err-jump-status=\"MS_PROCESS_ERR_1\"/>",
		"(mxSet 1 ([mxUncompressOldFormat format=\"CR\"] ([mxCH type=\"parent\"] 1) (mxCH 2)))",
			0));
		set_matrix_cal_equ(m,MI_VISU_1_MD,MI_VISU_1_BT);
		set_matrix_cal(m,MI_VISU_1_TP,
			sexp_commands(
				std_cm,
			"<mxFinish",
			"	normal-jump-status=\"MS_OK\"",
			"	err-jump-status=\"MS_PROCESS_ERR_1\"/>",
			"(mxSet 1 ([mxUncompressOldFormat format=\"CR\"] (mxCH 2)))",
			0));
		break;
	default:
		er_panic("invalid type");
	}

	if ( ow->r->h.cache_file_id ) {

		set_matrix_cal(m,MI_SAVE_TP,
			sexp_commands(
				std_cm,
				"<mxSave/>",
			0));
		set_matrix_cal_equ(m,MI_SAVE_MD,MI_SAVE_TP);
		set_matrix_cal_equ(m,MI_SAVE_BT,MI_SAVE_TP);
		
		set_matrix_cal(m,MI_FETCH_1_TP,
			sexp_commands(
				std_cm,
				"<mxFinish",
				"	err-jump=\"MI_FETCH_2\"",
				"	normal-jump-status=\"MS_OK\"/>",
				"<mxLoad target=\"file\"/>",
			0));
		set_matrix_cal_equ(m,MI_FETCH_1_MD,MI_FETCH_1_TP);
		set_matrix_cal_equ(m,MI_FETCH_1_BT,MI_FETCH_1_TP);

		set_matrix_cal(m,MI_FETCH_2_TP,
			sexp_commands(
				std_cm,
				"<mxFinish",
				"	normal-jump=\"MI_VISU_1\"",
				"	err-jump-status=\"MS_LOADING_ERR_1\"/>",
				"<mxLoad target=\"net\"/>",
			0));
		set_matrix_cal_equ(m,MI_FETCH_2_MD,MI_FETCH_2_TP);
		set_matrix_cal_equ(m,MI_FETCH_2_BT,MI_FETCH_2_TP);
		
		if ( err == ME_DESTROY_FILE || err == ME_CANNOT_OPEN_FILE )
			save_matrix_header(m);

	}

	set_matrix_mode(m,MM_STANBY);
	;
	d_f_ree(t);
	return;
error:
	er_panic("ERROR");
}


void omx_close_matrix_file(MATRIX * m)
{
OMX_OPEN_WORK * w;
	w = m->open_work;
	d_f_ree(w);
	close_matrix_file(m);
}

void omx_new_token(MATRIX_TOKEN * t,int type)
{
OMX_TOKEN_WORK * w;
	if ( type != MPT_NEW_TOKEN_NODE )
		return;
	w = d_alloc(sizeof(*w));
	memset(w,0,sizeof(*w));
	t->work = w;
}

void omx_free_token(MATRIX_TOKEN * t ,int type)
{
	if ( type != MPT_NEW_TOKEN_NODE )
		return;
	d_f_ree(t->work);
	t->work = 0;
}

void
gc_omx(MATRIX_TOKEN * n)
{
OMX_TOKEN_WORK * w;
void gc_gb_sexp();

	for ( ; n ; n = w->next ) {
		w = n->work;
		if ( w == 0 )
			break;
		if ( w->data )
			gc_gb_sexp(w->data);
		if ( w->tmp )
			gc_gb_sexp(w->tmp);
	}
}


void
gc_omx_get(MATRIX_TOKEN * n)
{
void gc_gb_sexp();
OMX_TOKEN_WORK * w;


	for ( ; n ; n = w->next ) {
		w = n->work;
		if ( w == 0 )
			break;
		lock_mem();
		if ( w->data )
			gc_set_nl(w->data,gc_gb_sexp);
		if ( w->tmp )
			gc_set_nl(w->tmp,gc_gb_sexp);
		unlock_mem();
	}
}


/*
int
get_query_cr(
	XL_SEXP ** query_p,
	XL_SEXP ** tmp_p,
	I_RECT * ir,
	TREE_CACHE * 	tc,
	TREE_NODE *	tn)
*/

int get_query_omx_cr(
	XL_SEXP ** query_p,
	XL_SEXP ** tmp_p,
	I_RECT * ir,
	MATRIX_TOKEN * t)
{
RESOURCE * r;
XL_SEXP * query,* query_tmp;
int rect_size;
L_CHAR * f;
int _x,_y;
int xx,yy;
int level;
XL_SEXP * ret;
void gc_gb_sexp();

MATRIX * m;
MATRIX_NODE * n;
OMX_OPEN_WORK * ow;

	n = t->process_node;
	m = n->matrix;
	ow = m->open_work;
	r = ow->r;
	level = n->dim_code[0];

	switch ( r->pr64.type ) {
	case '0':
		rect_size = 64;
		break;
	case '1':
		rect_size = 128;
		break;
	case '2':
		rect_size = 256;
		break;
	default:
		er_panic("get_pixel_cr(1)");
	}

	gc_push(0,0,"get_pixel_cr");
	query = 0;
	query_tmp = 0;
	f = get_url_filepath(&r->h.target);
	for ( _x = 0 ; _x < RECT_SIZE ; _x += rect_size )
		for ( _y = 0 ; _y < RECT_SIZE ; _y += rect_size ) {
			xx = ir->tl.x + _x;
			if ( xx >= ir->br.x )
				continue;
			yy = ir->tl.y + _y;
			if ( yy >= ir->br.y )
				continue;

			query = cons(
				List(n_get_symbol("Get"),
					get_string(f),
					get_integer(level,0),
					get_integer(xx,0),
					get_integer(yy,0),
					-1),
				query);
			query_tmp = cons(
				List(
					get_integer(_x,0),
					get_integer(_y,0),
					get_integer(xx,0),
					get_integer(yy,0),
					-1),
				query_tmp);
		}
	d_f_ree(f);
	query = cons(n_get_symbol("List"),query);

	*query_p = query;
	*tmp_p = query_tmp;
	ret = List(query,query_tmp,-1);
	gc_pop(ret,gc_gb_sexp);
	return 0;
}


/*
int
get_query_r64(
	XL_SEXP ** query_p,
	XL_SEXP ** tmp_p,
	I_RECT * ir,
	TREE_CACHE * 	tc,
	TREE_NODE *	tn)
*/

int get_query_omx_r64(
	XL_SEXP ** query_p,
	XL_SEXP ** tmp_p,
	I_RECT * ir,
	MATRIX_TOKEN * t)
{
L_CHAR * f;

MATRIX * m;
MATRIX_NODE * n;
OMX_OPEN_WORK * ow;
RESOURCE * r;
int level;

	n = t->process_node;
	m = n->matrix;
	ow = m->open_work;
	r = ow->r;
	level = n->dim_code[0];

	*query_p = List(n_get_symbol("Get"),
		get_string(f=get_url_filepath(&r->h.target)),
		get_integer(level,0),
		List(n_get_symbol("List"),
			List(n_get_symbol("List"),
				get_integer(ir->tl.x,0),
				get_integer(ir->tl.y,0),
				-1),
			List(n_get_symbol("List"),
				get_integer(ir->br.x,0),
				get_integer(ir->br.y,0),
				-1),
			-1),
		-1);
	*tmp_p = 0;
	d_f_ree(f);
	return 0;
}

/*
MATRIX_TOKEN *
omx_dirty_insert(MATRIX_TOKEN * n3,MATRIX_TOKEN * n_end)
{
I_RECT ir;
GB_RECT rct;
REAL1 dpm;
RESOURCE * r;
//TREE_NODE * tn;
//TREE_CACHE * tc;
MATRIX_TOKEN * n2;

OMX_TOKEN_WORK * otw2;
OMX_OPEN_WORK * ow2;
MATRIX * m;
MATRIX_NODE * n;

	for ( n2 = n3 ; n2 && n2 != n_end ; ) {
//		tn = n2->tn;
		m = (n =n2->process_node)->matrix;
		ow2 = m->open_work;
		r = ow2->r;

		ir.tl.x = n->dim_code[1] & 
			(- (1<<(n->dim_code[0]*m->dim_divide[0]
			+ m->block_size[0])));
		ir.tl.y = n->dim_code[2] &
			(- (1<<(n->dim_code[0]*m->dim_divide[1]
			+ m->block_size[1])));
		ir.br.x = ir.tl.x +
				(1<<m->block_size[0])*
				(1<<(n->dim_code[0] * m->dim_divide[0]));
		if ( ir.br.x > m->pixel_size[0] )
			ir.br.x = m->pixel_size[0];
		ir.br.y = ir.tl.y +
				(1<<m->block_size[0])*
				(1<<(n->dim_code[1] * m->dim_divide[1]));
		if ( ir.br.y > m->pixel_size[1] )
			ir.br.y = m->pixel_size[1];
		dpm = r->pr64.dpm;
		rct.tl.x = ir.tl.x / dpm;
		rct.tl.y = ir.tl.y / dpm;
		rct.br.x = ir.br.x / dpm;
		rct.br.y = ir.br.y / dpm;
//
		tc = n2->tc;
		if ( n2->req_level <= tn->level ||
				tc->rt_level - n2->req_level 
				> 2*(tc->rt_level - tn->level) )
//
		if ( n->req_level <= n->dim_code[0] ||
				m->total_levels - n->req_level
				> 2*(m->total_levels - n->dim_code[0]) )
			wf_insert_dirty_rect(r,
				&rct,WFF_LUSTER_DIRTY,120,10);

		otw2 = n2->work;
		n2 = otw2->next;
	}
	return n2;
}
*/

void
__exec_dirty(TKEY td)
{
OMX_DIRTY * d;
XL_INTERPRETER * xli;
int tim;

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

ss_printf("EXEC DIRTY\n");
	for ( ; ; ) {
		tim = get_xltime();
		for ( ; ; ) {
			lock_task(omx_lock);
			if ( dirty_list == 0 ) {
				break;
			}
			d = dirty_list;
			dirty_list = d->next;
			unlock_task(omx_lock,"_exec_dirty");
		
			wf_insert_dirty_rect(d->r,
				&d->rct,WFF_LUSTER_DIRTY,120,10);
			d_f_ree(d);
		}
		if ( get_xltime() - tim > 1 ) {
			unlock_task(omx_lock,"_exec_dirty");
			sleep_sec(2);
		}
		else {
			sleep_task((int)__exec_dirty,omx_lock);
		}
	}

	close_self_interpreter();

}

void
_exec_dirty(int data)
{
	wakeup_task((int)__exec_dirty);
}


void
insert_dirty(RESOURCE * r,GB_RECT * rct)
{
OMX_DIRTY * d;
int t;

	lock_task(omx_lock);
	d = d_alloc(sizeof(*d));
	d->r = r;
	d->rct = *rct;
	d->next = dirty_list;
	dirty_list = d;
	wakeup_task((int)__exec_dirty);
	unlock_task(omx_lock,"_exec_dirty");
	t = get_xltime();
//	if ( t - dirty_time >= 2 )
		_exec_dirty(0);
}


void
omx_trigger(int type,void * data)
{
I_RECT ir;
GB_RECT rct;
REAL1 dpm;
RESOURCE * r;
//TREE_NODE * tn;
//TREE_CACHE * tc;

OMX_OPEN_WORK * ow2;
MATRIX * m;
MATRIX_NODE * n;
MATRIX_TOKEN * n2;

	switch ( type ) {
	case TRT_MATRIX_STANBY:
		m = data;
		ow2 = m->open_work;
		r = ow2->r;
		dpm = r->pr64.dpm;
		rct.tl.x = rct.tl.y = 0;
		rct.br.x = m->pixel_size[0] / dpm;
		rct.br.y = m->pixel_size[1] / dpm;
		insert_dirty(r,&rct);
		_exec_dirty(1);
		return;
	case TRT_FINISH:
		_exec_dirty(1);
		return;
	case TRT_TOKEN:
		n2 = data;

	//		tn = n2->tn;
		m = (n =n2->process_node)->matrix;
		ow2 = m->open_work;
		r = ow2->r;

		ir.tl.x = n->dim_code[1] & 
			(- (1<<(n->dim_code[0]*m->dim_divide[0]
			+ m->block_size[0])));
		ir.tl.y = n->dim_code[2] &
			(- (1<<(n->dim_code[0]*m->dim_divide[1]
			+ m->block_size[1])));
		ir.br.x = ir.tl.x +
				(1<<(n->dim_code[0] * m->dim_divide[0] +
					m->block_size[0]));
		if ( ir.br.x > m->pixel_size[0] )
			ir.br.x = m->pixel_size[0];
		ir.br.y = ir.tl.y +
				(1<<(n->dim_code[0] * m->dim_divide[1] +
					m->block_size[1]));
		if ( ir.br.y > m->pixel_size[1] )
			ir.br.y = m->pixel_size[1];
		dpm = r->pr64.dpm;
		rct.tl.x = ir.tl.x / dpm;
		rct.tl.y = ir.tl.y / dpm;
		rct.br.x = ir.br.x / dpm;
		rct.br.y = ir.br.y / dpm;
	/*
		tc = n2->tc;
		if ( n2->req_level <= tn->level ||
				tc->rt_level - n2->req_level 
				> 2*(tc->rt_level - tn->level) )
	*/
	/*
		if ( n->req_level <= n->dim_code[0] ||
				m->total_levels - n->req_level
				> 2*(m->total_levels - n->dim_code[0]) ) {

	*/
	/*
			wf_insert_dirty_rect(r,
				&rct,WFF_LUSTER_DIRTY,120,10);
	*/

			insert_dirty(r,&rct);

	//	}
		break;
	default:
		er_panic("omx_trigger");
	}

}

void
mx_task2(TKEY d)
{
SYS_QUEUE * que;
XL_INTERPRETER * xli;
L_CHAR * key;
MATRIX_TOKEN * n1, * n2, * n3;
OMX_TOKEN_WORK * otw1,* otw2;
XL_SEXP * data, * err;
RESOURCE * r;
unsigned int t;
int nr_count,cr_err_count,cr_err_count_flag;
unsigned int nr_time;
WFID_INCLUDE_RESOURCE * wir;
//int cr_err_q;
//int rr;
int box_f;

OMX_OPEN_WORK * ow1,* ow2;
MATRIX_NODE * mn2;
MATRIX_SEXP * s1;
XL_SEXP * test;

	que = (SYS_QUEUE *)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

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

	nr_count = 0;
	nr_time = 0;
	cr_err_count = 0;
	cr_err_count_flag = 0;
	for ( ; ; ) {
		gc_push(0,0,"tc_task2");
		n1 = delete_queue(que,sq_key_cond,key,0);
		if ( n1 == 0 )
			break;
ss_printf("GET SESSION (%x)\n",n1);
check_point(n1);
/*
		if ( cr_err_count_flag && cr_err_q > 0 ) {
			cr_err_q --;
			goto n1_free;
		}
*/
		ow1 = n1->process_node->matrix->open_work;
		r = ow1->r;
		otw1 = n1->work;

		wir = wf_search_wfid_include_resource(r);
		if ( wir == 0 ) {
			if ( nr_time == 0 )
				nr_time = get_xltime();
	
			if ( get_xltime() - nr_time > ow1->trans_timeout ) {
				if ( nr_count == 0 ) {
					np_divide_p_agent(&r->h.entry);
					aboat_session(otw1->data);
					ow1->trans_timeout *= 2;
					nr_count = 1;
				}
ss_printf("** ** * RESET STREAM %i - %i\n",nr_count,wir);
				goto n1_free;
			}
		}
		else {
			nr_count = 0;
			nr_time = 0;
			ow1->trans_timeout --;
			if (ow1->trans_timeout < INVALID_TRANS_TIMEOUT )
				ow1->trans_timeout = INVALID_TRANS_TIMEOUT;
		}

		switch ( get_type(otw1->data) ) {
		case XLT_ERROR:
ss_printf("EEEEEEE\n");
			log_print_sexp(LOG_MESSAGE,LOG_LAYER_GB,0,
				"r64 get error",otw1->data,0);

			set_inc_status_error(r,otw1->data);

			goto n1_free;
		case XLT_NULL:
		case XLT_PAIR:
			set_inc_status(r,RS_IDLE);
			break;
		default:

			set_inc_status_error(r,
				get_error(
					0,
					0,
					XLE_SEMANTICS_TYPE_MISSMATCH,
					l_string(std_cm,"Get(r64)"),
				n_get_string(
				"server return invalid type data")));

			fprintf(stderr,"r64 get: type missmatch return\n");
			print_sexp(s_stderr,otw1->data,PF_RAW_DISABLE);
			fprintf(stderr,"\n");
			goto n1_free;
		}
		data = otw1->data;

		n3 = n1;
		t = get_xltime();
		for ( n2 = n1 ; n2 ; otw2 = n2->work , n2 = otw2->next ) {
check_point(n2);
//			tn = n2->tn;
			mn2 = n2->process_node;
			ow2 = mn2->matrix->open_work;
			r = ow2->r;
			otw2 = n2->work;
			otw2->e_flag = 0;
/*
			if ( tn->wait_box == 0 ) {
*/
ss_printf("GET SESSION (%x)\n",n2);
			if ( mn2->channel[CH_NET].data == 0 ) {
			retry:
				if ( get_type(data) == XLT_ERROR )
{ss_printf("EEEEEEEEEEEE4\n");
					break;
}
				err = list_error(car(data));
				if ( get_type(err) == XLT_ERROR ) {
ss_printf("EEEEEEEEEEE2\n");
					data = cdr(data);
					otw2->e_flag = 1;
					continue;
				}
/*
				rr = (*n2->tc->get_pixels)(n2->tc,tn,
					car(data),n2->tmp);
*/
				box_f = 0;



				s1 = d_alloc(sizeof(*s1));
				memset(s1,0,sizeof(*s1));
				s1->data = test = List(
					get_integer(otw2->w,0),
					get_integer(otw2->h,0),
					otw2->tmp,
					car(data),
					-1);
				s1->gc_func = gc_gb_sexp;
				_insert_matrix_sexp(s1);
				mn2->channel[CH_NET].data = s1;
				if ( mn2->dim_code[0] )
					allset_dim_code_index(mn2,0);
			}
			else {
				s1 = mn2->channel[CH_NET].data;
				if ( s1->data == 0 ) {
					s1->del = 1;
					goto retry;
				}
ss_printf("CR ERR RE INSERT\n");
/*
				rr = (*n2->tc->get_pixels)(n2->tc,tn,
					get_el(tn->wait_box->data,0),
					get_el(tn->wait_box->data,1));
*/
				box_f = 1;
			}
/*
			if ( rr < 0 )
				cr_err_count ++;
			else {
				cr_err_count = 0;
				cr_err_count_flag = 0;
				n1->tc->cr_err_count --;
				if ( n1->tc->cr_err_count 
					< INVALID_TRANS_CR_ERR_COUNT )
					n1->tc->cr_err_count = 
						INVALID_TRANS_CR_ERR_COUNT;
			}
*/
			if ( box_f == 0 ) 
				data = cdr(data);
/*
			if ( get_xltime() - t >= 2 )
				n3 = omx_dirty_insert(n3,n2);
*/
		}
/*
		if ( cr_err_count > n1->tc->cr_err_count &&
			cr_err_count_flag == 0 ) {
			np_divide_p_agent(&r->h.entry);
			aboat_session(n1->data);
			cr_err_count_flag = 1;
			cr_err_q = QUEUE_LENGTH;
			n1->tc->cr_err_count *= 2;
		}
*/
//		omx_dirty_insert(n3,0);
		for ( n2 = n1 ; n2 ; ) {
			otw2 = n2->work;
			otw2->data = 0;
			otw2->tmp = 0;
			n1 = otw2->next;
			n2->aboat_func = 0;
			if ( otw2->e_flag )
				matrix_token_error(n2);
			else	insert_matrix_access(n2,matrix_exec_cal);
			n2 = n1;
		}

		gc_pop(0,0);
		continue;
	n1_free:
		gc_pop(0,0);
		for ( n2 = n1 ; n2 ; ) {
			n1 = n2;
			otw2 = n2->work;
			n2 = otw2->next;
			n1->aboat_func = 0;
			matrix_token_error(n1);
		}
	}
	gc_pop(0,0);

	release_qkey(que,key);
	d_f_ree(key);

	close_self_interpreter();

}


void
mx_task1(TKEY d)
{
SYS_QUEUE * que;
XL_INTERPRETER * xli;
L_CHAR * key;
int ses;
MATRIX_TOKEN * n1, * n2, * n3, * _n;
OMX_TOKEN_WORK * otw1,*otw3,*otw_n;
XL_SEXP * data, * dd, * tmp;
int cnt;
I_RECT ir;
extern int spiral_count;
WFID_INCLUDE_RESOURCE * wir;

INTEGER64 dim[2];
INTEGER64 lev,br_x,br_y;
MATRIX * m;
OMX_OPEN_WORK * ow;

	que = (SYS_QUEUE *)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

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

	ses = open_session(SEST_OPTIMIZE);

	for ( ; ; ) {

		cnt = 0;
		n2 = 0;
		for ( ; cnt < 1 ; ) {
			lock_task(matrix_lock);
			n1 = delete_queue(que,sq_key_cond,key,0);
			if ( n1 == 0 ) {
				unlock_task(matrix_lock,"tc_task");
				break;
			}
check_point(n1);
			unlock_task(matrix_lock,"tc_task");
			ow = n1->process_node->matrix->open_work;
			otw1 = n1->work;
			if ( ow->r->pr64.loop_no - n1->loop_no
					> spiral_count + 2 ||
				(wir = wf_search_wfid_include_resource(ow->r))
					== 0 ) {
				otw1->next = 0;
				n1->aboat_func = 0;
				matrix_token_error(n1);

				continue;
			}
			free_wfid_include_resource(wir);
			cnt ++;
			otw1->next = n2;
			n2 = n1;
		}
		if ( n2 == 0 )
			break;
		gc_push(0,0,"beam");
		n3 = 0;
		data = 0;
		tmp = 0;
		for ( ; n2 ; ) {
			_n = n2;
			otw_n = _n->work;
			n2 = otw_n->next;

			dim[0] = _n->process_node->dim_code[1];
			dim[1] = _n->process_node->dim_code[2];
			lev = _n->process_node->dim_code[0];
			m = _n->process_node->matrix;
			dim[0] = (dim[0] >> (lev * m->dim_divide[0])) &
					(- (1<<m->block_size[0]));
			dim[1] = dim[1] >> (lev * m->dim_divide[1]) &
					(- (1<<m->block_size[1]));

			br_x = dim[0] + (1<<m->block_size[0]);
			if ( br_x > m->pixel_size_list[lev][0] )
				br_x = m->pixel_size_list[lev][0];
			br_y = dim[1] + (1<<m->block_size[1]);
			if ( br_y > m->pixel_size_list[lev][1] )
				br_y = m->pixel_size_list[lev][1];

			ir.tl.x = dim[0];
			ir.tl.y = dim[1];

			ir.br.x = br_x;
			ir.br.y = br_y;
			otw_n->w = ir.br.x - ir.tl.x;
			otw_n->h = ir.br.y - ir.tl.y;
			ow = m->open_work;
			(*ow->get_query)(&dd,&otw_n->tmp,&ir,_n);
/*
			(*_n->tc->get_query)(
				&dd,
				&otw_n->tmp,
				&ir,
				_n->tc,_n->tn);
*/
			data = cons(dd,data);

			otw_n->data = 0;

			otw_n->next = n3;
token_check(_n);
			n3 = _n;
		}
		data = cons(n_get_symbol("List"),data);
		otw3 = n3->work;
		ow = n3->process_node->matrix->open_work;
		if ( otw3->aboat_flag == 0 ) {
			otw3->data = remote_session(
				gblisp_top_env0,
				ses,
				&ow->r->h.target,
				l_string(std_cm,"gbr64"),
				l_string(std_cm,"user"),
				l_string(std_cm,"Get"),
				List(data,-1),
				0,0,0,0);
		}
		else {
			otw3->data = get_error(
					0,
					0,
					XLE_SEMANTICS_TYPE_MISSMATCH,
					l_string(std_cm,"Get(r64)"),
				n_get_string(
				"trans error"));
		}
ss_printf("REMOTE SESSION (%x) ================= \n",n3);
check_point(n3);
		insert_queue(&mx_que2,n3,1);

		gc_pop(0,0);
	}


	release_qkey(que,key);
	d_f_ree(key);

	close_session(ses);
	close_self_interpreter();
}


void
aboat_old_matrix(MATRIX_TOKEN * t)
{
OMX_TOKEN_WORK * w;
	w = t->work;
	if ( w == 0 )
		return;
	w->aboat_flag = 1;
	aboat_session(w->data);
}

int
old_matrix_read_net(MATRIX_TOKEN * t)
{
MATRIX * m;
int pri;
MATRIX_NODE * n;
int b;
OMX_OPEN_WORK * ow;
OMX_TOKEN_WORK * ww;
	lock_task(matrix_lock);
check_point(t);
	m = t->process_node->matrix;
	ow = m->open_work;
	t->loop_no = ow->r->pr64.loop_no;

	if ( t->process_node->channel[CH_NET].data )
		er_panic("old_matrix_read_net");

	t->h.key = get_server_key(&ow->r->h.target,0);
	t->func = 0;
	t->aboat_func = aboat_old_matrix;
	ww = t->work;
	ww->aboat_flag = 0;
	n = t->process_node;
	m = n->matrix;
	b = m->p.pri_area[t->access_target_id];
	m = n->matrix;
	switch ( b & 0xffff ) {
	case PR_UP:
		pri = ((b >> 16) & 0xffff) + n->dim_code[0];
		break;
	case PR_DOWN:
		pri = ((b >> 16) & 0xffff) - n->dim_code[0]
			+ m->total_levels * 2;
		break;
	case PR_STRT:
		pri = ((b >> 16) & 0xffff);
		break;
	default:
		er_panic("_get_matrix_access");
	}
//	t->h.pri = pri;
check_point(t);
	insert_queue(&mx_que1,t,0);
	unlock_task(matrix_lock,"old_matrx_read_net");
	return 1;
}


