/**********************************************************************
 
	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	<stdio.h>
#include	"memory_debug.h"
#include	"xlerror.h"
#include	"resource.h"
#include	"utils.h"
#include	"xl.h"
#include	"task.h"
#include	"lock_level.h"
#include	"pri_level.h"
#include	"rs_cache.h"
#include	"save_global.h"
#define HANDLING_MAX		20


extern SEM res_lock;
extern GV_FUNC gv_new_table[RT_MAX];
extern XLISP_ENV * gv_resource_env[RT_MAX];

SYS_QUEUE res_q0,res_q1,res_q2,res_lp1,res_disposer,res_extend;
LOAD_RESOURCE_WORK * first_list;

void _load_resource_task0(TKEY d);
void _load_resource_task1(TKEY d);
void _load_resource_task2(TKEY d);
void _load_resource_task3(TKEY d);
void resource_disposer_task();

void _lr_extend_task1(TKEY d);
void _lr_extend_task2(TKEY d);

int loading_coord();
int setup_coord();

RESOURCE_TYPE_LIST res_type_list[] = {
	{"coordinate","*",0,RT_COORDINATE,loading_coord,setup_coord},
	{"map","xl",0,RT_MAP,0,0},
	{"luster","cr",RTF_TARGET,RT_LUSTER,0,0},
	{"luster","r64",RTF_TARGET,RT_LUSTER,0,0},
	{"vector","pdb",RTF_TARGET,RT_VECTOR,0,0},
	{"vector","xl",0,RT_VECTOR,0,0},
	{0,0,0,0,0,0}
};

void gc_lrw();
void gc_lrw_get();
void gc_gb_sexp();

void
resource_global()
{
	SG_TITLE;

	sg("SEM",	"res_lock",	&res_lock);
	sg("SYS_QUEUE",	"res_q0",	&res_q0);
	sg("SYS_QUEUE",	"res_q1",	&res_q1);
	sg("SYS_QUEUE",	"res_q2",	&res_q2);
	sg("SYS_QUEUE",	"res_lp1",	&res_lp1);
	sg("SYS_QUEUE",	"res_disposer",	&res_disposer);
	sg("SYS_QUEUE",	"res_extend",	&res_extend);
	sg("LOAD_RESOURCE_WORK","first_list",&first_list);
}

void
init_load_resource()
{

	memset(&res_extend,0,sizeof(SYS_QUEUE));
	res_extend.flags = QF_STACK;
	res_extend.gc_func = gc_lrw;
	res_extend.gc_get = gc_lrw_get;
	res_extend.key_func = _lr_extend_task1;
	res_extend.pri = PRI_FETCH;
	setup_queue(&res_extend);

	memset(&res_q0,0,sizeof(SYS_QUEUE));
	res_q0.flags = QF_STACK;
	res_q0.gc_func = gc_lrw;
	res_q0.gc_get = gc_lrw_get;
	res_q0.key_func = _load_resource_task0;
	res_q0.pri = PRI_FETCH;
	setup_queue(&res_q0);

	memset(&res_q1,0,sizeof(SYS_QUEUE));
	res_q1.flags = QF_STACK;
	res_q1.gc_func = gc_lrw;
	res_q1.gc_get = gc_lrw_get;
	res_q1.key_func = _load_resource_task1;
	res_q1.pri = PRI_FETCH;
	setup_queue(&res_q1);

	memset(&res_q2,0,sizeof(SYS_QUEUE));
	res_q2.flags = QF_FIFO;
	res_q2.gc_func = gc_lrw;
	res_q2.gc_get = gc_lrw_get;
	res_q2.key_func = _load_resource_task2;
	res_q2.pri = PRI_FETCH;
	res_q2.total_limit = 4;
	setup_queue(&res_q2);
/*
	memset(&res_q3,0,sizeof(SYS_QUEUE));
	res_q3.flags = QF_FIFO;
	res_q3.gc_func = gc_lrw;
	res_q3.gc_get = gc_lrw_get;
	res_q3.key_func = _load_resource_task3;
	res_q3.pri = PRI_FETCH;
	setup_queue(&res_q3);
*/
	memset(&res_lp1,0,sizeof(SYS_QUEUE));
	res_lp1.flags = QF_FIFO;
	res_lp1.gc_func = gc_lrw;
	res_lp1.gc_get = gc_lrw_get;
	res_lp1.key_func = _lr_extend_task2;
	res_lp1.pri = PRI_FETCH;
	setup_queue(&res_lp1);

	memset(&res_disposer,0,sizeof(SYS_QUEUE));
	res_disposer.flags = QF_FIFO;
	res_disposer.gc_func = gc_lrw;
	res_disposer.gc_get = gc_lrw_get;
	res_disposer.pri = PRI_FETCH;
	setup_queue(&res_disposer);

	create_task(resource_disposer_task,0,PRI_FETCH);

	resource_global();
}


void
_gc_lrw(LOAD_RESOURCE_WORK * w)
{
	gc_gb_sexp(w->meta_result);
	gc_gb_sexp(w->data_result);
	gc_gb_sexp(w->_meta_ret);
}

void
gc_lrw(LOAD_RESOURCE_WORK * w)
{
	for ( ; w ; w = w->que_next )
		_gc_lrw(w);
}

void
_gc_lrw_get(LOAD_RESOURCE_WORK * w)
{
	gc_set_nl(w->meta_result,gc_gb_sexp);
	gc_set_nl(w->data_result,gc_gb_sexp);
	gc_set_nl(w->_meta_ret,gc_gb_sexp);
}

void
gc_lrw_get(LOAD_RESOURCE_WORK * w)
{
	lock_mem();
	for ( ; w ; w = w->que_next )
		_gc_lrw_get(w);
	unlock_mem();
}

typedef struct res_cond_work {
	L_CHAR *		key;
	int			que_pri;
	int			active_pri;
} RES_COND_WORK;


int
res_cond(SYS_QUEUE * q,LOAD_RESOURCE_WORK * lr,RES_COND_WORK * w)
{
int ret;
	ret = sq_key_cond(q,lr,w->key);
	if ( ret < 0 )
		return ret;
	if ( w->active_pri < 0 || w->active_pri > lr->que_pri )
		w->active_pri = lr->que_pri;
	if ( lr->que_pri != w->que_pri )
		return -1;
	return 0;
}


LOAD_RESOURCE_WORK *
delete_res_queue(SYS_QUEUE * q,L_CHAR * key)
{
LOAD_RESOURCE_WORK * ret;
int pri;
RES_COND_WORK w;
	w.key = key;
	w.que_pri = 0;
	w.active_pri = -1;
	ret = delete_queue(q,res_cond,&w,0);
	if ( ret )
		return ret;
	if ( w.active_pri == -1 )
		return 0;
	w.que_pri = w.active_pri;
	w.active_pri = -1;
	ret = delete_queue(q,res_cond,&w,0);
	if ( ret == 0 )
		er_panic("delete_res_queue");
	return ret;
}

LOAD_RESOURCE_WORK *
delete_res_queue_handle_max(SYS_QUEUE * q,L_CHAR * key)
{
int i;
LOAD_RESOURCE_WORK * w, * w2, ** wp;

	w = 0;
	wp = &w;
	for ( i = 0 ; i < HANDLING_MAX ; i ++ ) {
		w2 = delete_res_queue(q,key);
		if ( w2 == 0 )
			break;
		w2->que_next = 0;
		*wp = w2;
		wp = &w2->que_next;
	}
	return w;
}

void
check_lrw_req_next(LOAD_RESOURCE_WORK * w)
{
	printf("CHECK\n");
	for ( ; w ; w = w->req_next );
	printf("CHECK END\n");
}

void
check_lrw_que_next(LOAD_RESOURCE_WORK * w)
{
	printf("CHECK\n");
	for ( ; w ; w = w->que_next );
	printf("CHECK END\n");
}


RESOURCE_TYPE_LIST *
get_resource_type(RESOURCE_TYPE_LIST * rt,char * tag)
{
	if ( rt == 0 )
		rt = &res_type_list[0];
	else if ( rt->tag_name == 0 )
		return 0;
	else 	rt ++;
	for ( ; rt->tag_name ; rt ++ ) {
		if ( strcmp(rt->tag_name,tag) == 0 )
			return rt;
	}
	return 0;
}

RESOURCE_TYPE_LIST *
get_resource_type_by_no(RESOURCE_TYPE_LIST * rt,int no)
{
	if ( rt == 0 )
		rt = &res_type_list[0];
	else if ( rt->tag_name == 0 )
		return 0;
	else 	rt ++;
	for ( ; rt->tag_name ; rt ++ ) {
		if ( rt->resource_type_num == no )
			return rt;
	}
	return 0;
}

void
free_lrw_req_next(LOAD_RESOURCE_WORK * w)
{
int i;
LOAD_RESOURCE_WORK * w2;
	for ( ; w ; w = w2 ) {
		w2 = w->req_next;
		if ( w->err != LRWE_NOTUSE )
			continue;
		free_url(&w->url);
		if ( w->target )
			d_f_ree(w->target);
		d_f_ree(w);
	}
}


void
free_lrw_que_next(LOAD_RESOURCE_WORK * w)
{
int i;
LOAD_RESOURCE_WORK * w2;
	for ( ; w ; w = w2 ) {
		w2 = w->que_next;
		if ( w->err != LRWE_NOTUSE )
			continue;
		free_url(&w->url);
		if ( w->target )
			d_f_ree(w->target);
		d_f_ree(w);
	}
}

LOAD_RESOURCE_WORK *
_search_first_list(LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK * wp;
	for ( wp = first_list ; wp ; wp = wp->first_next )
		if ( l_strcmp(get_url_str2(&w->url),
				get_url_str2(&wp->url)) == 0 &&
				w->option == wp->option )
			return wp;
	return 0;
}

LOAD_RESOURCE_WORK *
_search_first_list_by_url(L_CHAR * url,int opt)
{
LOAD_RESOURCE_WORK * wp;
	for ( wp = first_list ; wp ; wp = wp->first_next )
		if ( l_strcmp(url,
				get_url_str2(&wp->url)) == 0 &&
				opt == wp->option )
			return wp;
	return 0;
}

void
_delete_first_list(LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK ** wp;

	for ( wp = &first_list ; *wp ; wp = &(*wp)->first_next )
		if ( *wp == w ) {
			*wp = w->first_next;
			return;
		}

	er_panic("_delete_first_list");
}

void
_insert_first_list(LOAD_RESOURCE_WORK * w)
{
	w->first_next = first_list;
	first_list = w;
}


void
_release_first_list(LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK * wp;
	for ( wp = w->same_list ; wp ; wp = wp->same_next ) {
		wp->err = w->err;
		wp->result = w->result;
		wakeup_task((int)wp->wup);
	}
	w->same_list = 0;
}

void
release_first_list(LOAD_RESOURCE_WORK * w)
{
	lock_task(res_lock);
	_release_first_list(w);
	_delete_first_list(w);
	unlock_task(res_lock,"release_first");
}

void
_res_end_op_extend(LOAD_RESOURCE_WORK * w,int err,RESOURCE * r,int clear)
{
LOAD_RESOURCE_WORK * wp;
L_CHAR * f, * g;

	w->err = err;
	if ( err < 0 ) {
		f = get_url_str2(&w->url);
		if ( f ) {
			g = ll_copy_str(f);
			purge_rcache(g);
			d_f_ree(g);
		}
	}
	if ( r ) {
		r->h.flags |= RF_LOAD_EXTEND;
		r->h.flags &= ~(RF_LOAD_EXTEND_PROC|clear);
		wakeup_task((int)r);
		rcache_invoke();
	}
	wakeup_task((int)w->wup);
}

void
res_end_op_extend(LOAD_RESOURCE_WORK * w,int err,RESOURCE * r,int clear)
{
int (* func)();

	lock_task(res_lock);
	func = w->wup_func;
	_res_end_op_extend(w,err,r,clear);
	unlock_task(res_lock,"res_end_op_extend");
	if ( func )
		(*func)();
}

void
_res_end_op(LOAD_RESOURCE_WORK * w,int err,RESOURCE * r)
{
LOAD_RESOURCE_WORK * wp;
L_CHAR * f, * g;

	w->err = err;
	if ( err < 0 ) {
		f = get_url_str2(&w->url);
		if ( f ) {
			g = ll_copy_str(f);
			purge_rcache(g);
			d_f_ree(g);
		}
	}
	if ( r ) {
		r->h.flags |= RF_COMPLETE;
		if ( err < 0 )
			r->h.flags |= RF_ERROR;
		wakeup_task((int)r);
		rcache_invoke();
	}
	wakeup_task((int)w->wup);
	_release_first_list(w);
	_delete_first_list(w);
}

void
res_end_op(LOAD_RESOURCE_WORK * w,int err,RESOURCE * r)
{
	lock_task(res_lock);
	_res_end_op(w,err,r);
	unlock_task(res_lock,"res_end_op");
}

void
_res_end_op_2(LOAD_RESOURCE_WORK * w,int err,RESOURCE * r)
{
LOAD_RESOURCE_WORK * wp;
L_CHAR * f,* g;

	w->err = err;
	if ( err < 0 ) {
		f = get_url_str2(&w->url);
		if ( f ) {
			g = ll_copy_str(f);
			purge_rcache(g);
			d_f_ree(g);
		}
	}
	if ( r ) {
		r->h.flags |= RF_COMPLETE;
		wakeup_task((int)r);
		rcache_invoke();
	}
	wakeup_task((int)w->wup);
	_release_first_list(w);
}

void
res_end_op_2(LOAD_RESOURCE_WORK * w,int err,RESOURCE * r)
{
	lock_task(res_lock);
	_res_end_op_2(w,err,r);
	unlock_task(res_lock,"res_end_op");
}


int
loading_coord(LOAD_RESOURCE_WORK * w)
{
L_CHAR * buf;
int len;
	copy_url(&w->url,&w->result->h.entry);
	len = l_strlen(w->url.resource);
	buf = d_alloc(sizeof(L_CHAR)*(len+10));
	memcpy(buf,w->url.resource,
		sizeof(L_CHAR)*len);
	memcpy(&buf[len],l_string(std_cm,".chi"),sizeof(L_CHAR)*5);
	d_f_ree(w->url.resource);
	w->url.resource = buf;
	return 0;
}

int
setup_coord(LOAD_RESOURCE_WORK * w)
{

ss_printf("LC\n");
	load_children(w->result,w->meta_result);
ss_printf("LC END\n");
	return 0;
}

LOAD_RESOURCE_WORK * 
new_lrw(LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK * ret;
	ret = new_queue_node(sizeof(*ret));
	ret->req_next = w;
	ret->que_next  = 0;
	ret->option = LRO_FULL;
	ret->wup = 0;
	ret->wup_func = 0;
	zero_url(&ret->url);
	ret->err = LRWE_NOTUSE;
	ret->result = 0;
	ret->meta_result = 0;
	ret->data_result = 0;
	ret->target = 0;
	ret->rt = 0;
	ret->_meta_ret = 0;

	ret->same_next = 0;
	ret->same_list = 0;
	ret->first_next = 0;

	ret->que_pri = 0;
	return ret;
}




void
_load_meta_list_insert(int ses,SYS_QUEUE * q,
		char * mode,int data_flag,
		LOAD_RESOURCE_WORK * w,
		int wait_flag)
{
XL_SEXP * ret, * s;
XL_SEXP * gt;
L_CHAR * f;
URL u;
void gc_gb_sexp();
XL_SEXP * query;
LOAD_RESOURCE_WORK * wp,* target;


	gc_push(0,0,"remote_fetch");

	gt = get_symbol(l_string(std_cm,"Get"));
	set_attribute(gt,
		l_string(std_cm,"mode"),
		l_string(std_cm,mode));

	query = 0;
	wp = w;
	target = 0;
	for ( ; wp ; wp = wp->que_next ) {
		wp->_mode = mode;
		wp->_data_flag = data_flag;
		if ( wp->err != LRWE_HANDLING )
			continue;
		if ( target == 0 )
			target = wp;
		f = get_url_filepath(&wp->url);
		query = cons(
			List(gt,
				get_string(f),
				-1),
			query);
		d_f_ree(f);
	}
	if ( target == 0 )
		goto end;
	if ( data_flag ) {
		wp = w;
		for ( ; wp ; wp = wp->que_next ) {

			if ( wp->err != LRWE_HANDLING )
				continue;
			f = get_url_filepath(&wp->url);
			query = cons(
				List(n_get_symbol("Get"),
					get_string(f),
					-1),
				query);
			d_f_ree(f);
		}
	}
	ret = 0;
	for ( ; get_type(query) ; query = cdr(query) )
		ret = cons(car(query),ret);
	query = ret;


	query = cons(n_get_symbol("List"),query);

	w->_meta_ret = remote_session(
		gblisp_top_env0,
		ses,
		&target->url,
		0,
		l_string(std_cm,"user"),
		l_string(std_cm,"Get"),
		List(query,-1),
		0,0,0);

	if ( w->h.key == 0 )
		w->h.key = get_server_key(&target->url);

	insert_queue(q,w,wait_flag);
end:
	gc_pop(0,0);
}


void
print_work(char * str,LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK * wp;
	ss_printf("PW %s\n",str);
	for (  ; w ; w = w->que_next ) {
		if ( w->url.resource ) {
			ss_printf("\t%ls\n",
				get_url_str2(&w->url));
			for ( wp = w->same_list ; wp ; wp = wp->same_next )
				ss_printf("\t\tSAME %ls\n",
					get_url_str2(&wp->url));
		}
		else ss_printf("\tDUMMY\n");
	}
}

LOAD_RESOURCE_WORK *
__load_meta_list_delete(int * ret_f,int ses,SYS_QUEUE * q,L_CHAR * key,
	int extend_flag)
{
LOAD_RESOURCE_WORK * w,* wp, * wp2;
XL_SEXP * ret,* s;
int limit;

	*ret_f = 1;

	w = delete_queue(q,sq_key_cond,key,0);
	if ( w == 0 ) {
		*ret_f = 0;
		goto end;
	}

	ret = w->_meta_ret;
	w->_meta_ret = 0;

	if ( get_type(ret) != XLT_ERROR ) {
		wp = w;
		s = ret;

		for ( ; wp ; wp = wp->que_next ) {
			if ( wp->err != LRWE_HANDLING )
				continue;
			if ( get_type(s) == XLT_ERROR )
				goto err;
			wp->meta_result = car(s);
			s = cdr(s) ;
		}
		if ( w->_data_flag ) {
			wp = w;
			for ( ; wp ; wp = wp->que_next ) {
				if ( wp->err != LRWE_HANDLING )
					continue;
				if ( get_type(s) == XLT_ERROR )
					goto err;
				wp->data_result = car(s);
				s = cdr(s);
			}
		}
	}
	else {
	err:
		if ( w->que_next == 0 ) {
ss_printf("+++++++++++++++++++++ ");
print_sexp(s_stdout,ret,0);
ss_printf("\n");
			if ( extend_flag )
				res_end_op_extend(w,LRWE_ERROR_GET1,
					w->result,0);
			else	res_end_op(w,LRWE_ERROR_GET1,0);
		}
		else {
ss_printf("+++++++++++++++++++++ ER\n");
			wp = w;
			for ( ; wp ; ) {
				wp2 = wp->que_next;
				wp->que_next = 0;
				_load_meta_list_insert(ses,q,
					wp->_mode,
					wp->_data_flag,
					wp,Q_WAIT_FORCE_INSERT);
				wp = wp2;
			}
			w = 0;
		}
	}
end:
	return w;
}


LOAD_RESOURCE_WORK *
_load_meta_list_delete(int ses,SYS_QUEUE * q,L_CHAR * key)
{
LOAD_RESOURCE_WORK * w, *w2, ** wp;
int ret_f;
int cnt;
	w = 0;
	wp = &w;
	cnt = HANDLING_MAX;
	for ( ; cnt > 0 ; ) {
		w2 = __load_meta_list_delete(&ret_f,ses,q,key,0);
		if ( ret_f == 0 )
			break;
		if ( w2 == 0 )
			continue;
		*wp = w2;
		cnt --;
		for ( ; w2->que_next ; w2 = w2->que_next , cnt -- );
		wp = &w2->que_next;
	}
	return w;
}

void
_load_resource_list1(int ses,LOAD_RESOURCE_WORK * w,L_CHAR * key)
{
LOAD_RESOURCE_WORK * wp, * lp, * lpp;
XL_SEXP * cat,* file, * ret,* meta;
RESOURCE_TYPE_LIST * rt;
L_CHAR * _cat;
RESOURCE * rr;
XL_SEXP * set_resource_header();
XLISP_ENV * env;
XL_SEXP * last_tag;
COORDINATE_UNIT * cup;



	gc_push(0,0,"_load_resource_list");

	wp = w;
	for ( ; wp ; wp = wp->que_next ) {
		if ( wp->err != LRWE_HANDLING )
			continue;
		cat = get_el_by_symbol(
			meta = get_el_by_symbol(
				wp->meta_result,
				l_string(std_cm,"meta"),0),
			l_string(std_cm,"category"),0);
		if ( cat == 0 ) {
			res_end_op(wp,LRWE_ERROR_FORMAT1,0);
			continue;
		}
		cat = get_el(cat,1);
		if ( cat == 0 ) {
			res_end_op(wp,LRWE_ERROR_FORMAT2,0);
			continue;
		}
		if ( get_type(cat) != XLT_STRING ) {
			res_end_op(wp,LRWE_ERROR_FORMAT3,0);
			continue;
		}
		_cat = cat->string.data;
		rt = 0;
		for ( ; ; ) {
			rt = get_resource_type(rt,n_string(std_cm,_cat));
			if ( rt == 0 ) {
				res_end_op(wp,LRWE_ERROR_NO_RES_TYPE,0);
				goto next;
			}
			if ( strcmp(rt->file_type,"*") == 0 )
				file = get_el_by_symbol(
					meta,
					l_string(std_cm,"file"),
					0);
			else	file = get_el_by_symbol(
					meta,
					l_string(std_cm,"file"),
					l_string(std_cm,"type"),
					l_string(std_cm,rt->file_type),
					0);
			if ( file == 0 )
				continue;
			if ( rt->flags & RTF_TARGET ) {
				file = get_el(file,1);
				if ( get_type(file) != XLT_STRING )
					continue;
				wp->target = compose_url(
					get_url_str2(&wp->url),
					file->string.data);
			}
			else {
				wp->target = 0;
			}
			wp->rt = rt;
			break;
		}
	next:
		{}
	}
	wp = w;
	cup = d_alloc(sizeof(*cup));
	for ( ; wp ; wp = wp->que_next ) {
		if ( wp->err != LRWE_HANDLING )
			continue;
		switch ( wp->option ) {
		case LRO_UNIT:
			setup_c_unit(cup,ses,get_url_str2(&wp->url),
				wp->meta_result,0);
			wp->result = 0;
			res_end_op(wp,LRWE_OK,0);
			free_c_unit(cup);
			break;
		}
	}
	d_f_ree(cup);

	wp = w;
	for ( ; wp ; wp = wp->que_next ) {
		if ( wp->err != LRWE_HANDLING )
			continue;
		rr = search_resource_by_entry(&wp->url);
		if ( rr ) {
			lock_task(res_lock);
			if ( rr->h.initial_status == RS_ERROR )
				_res_end_op(wp,LRWE_ERROR_HEADER_INIT,rr);
			else {
				wp->result = rr;
				_res_end_op(wp,LRWE_OK,0);
			}
			unlock_task(res_lock,"res");
			continue;
		}
		rr = new_resource_entry(
			wp->rt->resource_type_num,&wp->url);
		if ( wp->target ) {
		URL u;
			get_url2(&u,wp->target);
			set_resource_target(rr,&u);
			free_url(&u);
		}
		else	set_resource_target(rr,&wp->url);

		gc_push(0,0,"new_resouce");
		gc_push(0,0,"new_resouce1");

		meta = get_el_by_symbol(
			wp->meta_result,
			l_string(std_cm,"meta"),0);

		ret = set_resource_header(rr,meta);
		if ( get_type(ret) == XLT_ERROR ) {
ss_printf("META LOADING %x ",wp->meta_result);
print_sexp(s_stdout,wp->meta_result,0);
ss_printf("\n");
			set_init_status_error(rr,ret);
			res_end_op(wp,LRWE_ERROR_HEADER_INIT,rr);
			goto err_end;
		}
		ret = (*gv_new_table[wp->rt->resource_type_num])
			(rr,meta,NR_NEW);
		if ( get_type(ret) == XLT_ERROR ) {
			set_init_status_error(rr,ret);
			res_end_op(wp,LRWE_ERROR_BODY_INIT,rr);
			goto err_end;
		}

		new_resource_option();

		if ( wp->rt->resource_type_num == RT_COORDINATE )
			call_gv_event(RID_HIDE_COORD,
				l_string(std_cm,"insert-coord"));
		gc_pop(0,0);

		gc_push(0,0,"new_resouce2");

		if ( gv_resource_env[rr->h.type] ) {
			env = new_env(
				new_env_pair(gv_resource_env[rr->h.type],
					gblisp_top_env0));
			set_env(env,l_string(std_cm,"__resource"),
				get_ptr(rr,0));
			rr->h.data = last_tag = wp->data_result;
			for ( ; get_type(last_tag) == XLT_PAIR &&
				get_type(cdr(last_tag)) != XLT_NULL ;
				last_tag = cdr(last_tag) );
			if ( get_type(last_tag) != XLT_PAIR ) {
				set_init_status_error(rr,0);
				res_end_op(wp,LRWE_ERROR_NO_ROOT_XML,rr);
ss_printf("--------- ERROR %i\n",rr->h.type);
print_sexp(s_stdout,wp->data_result,0);
ss_printf("\n");
print_sexp(s_stdout,ret,0);
ss_printf("\n");
				goto err_end;
			}
			ret = eval(env,car(last_tag));
			if ( get_type(ret) == XLT_ERROR ) {
ss_printf("ERROR BODY 1\n");
print_sexp(s_stdout,rr->h.data,0);
ss_printf("\n");
				set_init_status_error(rr,ret);
				res_end_op(wp,LRWE_ERROR_BODY_EVAL,rr);
				goto err_end;
			}
		}
		wp->result = rr;
/*
		release_first_list(wp);
*/
	err_end:

		gc_pop(0,0);
		gc_pop(0,0);
	}
	wp = w;
	for ( ; wp ; wp = wp->que_next ) {
		if ( wp->err == LRWE_HANDLING ) {
			if ( wp->rt->loading_function == 0 )
				wp->result->h.flags |= RF_LOAD_EXTEND;
			res_end_op(wp,LRWE_OK,wp->result);
		}
	}
/*
	lp = 0;
	for ( ; wp ; wp = wp->que_next ) {
		if ( wp->err == LRWE_HANDLING ) {
			if ( wp->rt->loading_function ) {
				lp = new_lrw(lp);
				lp->h.key = ll_copy_str(key);
				lp->que_next = lp->req_next;
				lp->err = LRWE_HANDLING;
				(*wp->rt->loading_function)(lp,wp);
			}
			else {
				res_end_op(wp,LRWE_OK,wp->result);
			}
		}
	}
	if ( lp ) {
		for ( lpp = lp ; lpp ; lpp = lpp->que_next )
			lpp->wup = (int)lp;
		_load_meta_list_insert(ses,&res_lp1,"data",0,lp);
		lp = new_lrw(lp);
		lp->h.key = ll_copy_str(key);
		lp->err = LRWE_HANDLING;
		insert_queue(&res_q3,lp,1);
	}
*/

	gc_pop(0,0);
}


void
_resource_fix_wait(RESOURCE * r)
{
	for ( ; r->h.flags & RF_FIX ; ) {
		sleep_task((int)r,res_lock);
		lock_task(res_lock);
	}
}

void
_lr_extend_insert(int ses,LOAD_RESOURCE_WORK * w,L_CHAR * key)
{
LOAD_RESOURCE_WORK * lp, * wp1;
RESOURCE_TYPE_LIST * rt;

	lp = 0;

	for ( ; w ; ) {

		wp1 = w;
		w = w->que_next;
		wp1->que_next = 0;

		if ( wp1->err != LRWE_HANDLING )
			goto free_next;
		lock_task(res_lock);
		if ( !(wp1->result->h.flags & RF_COMPLETE) )
			er_panic("_lr_extend_insert");
		if ( wp1->result->h.flags & 
				RF_LOAD_EXTEND_PROC ){
			goto free_next_in_lock;
		}
		if ( wp1->result->h.flags &
				RF_LOAD_EXTEND ) {
			_res_end_op_extend(wp1,LRWE_OK,wp1->result,0);
			goto free_next_in_lock;
		}
		_resource_fix_wait(wp1->result);
		wp1->result->h.flags |= RF_LOAD_EXTEND_PROC;
		unlock_task(res_lock,"_lr_option_insert");


		rt = get_resource_type_by_no(0,wp1->result->h.type);
		if ( rt->loading_function ) {
			(*rt->loading_function)(wp1);
			wp1->rt = rt;

			wp1->que_next = lp;
			lp = wp1;
		}
		else {
			res_end_op_extend(wp1,LRWE_OK,wp1->result,0);
			goto free_next;
		}
		continue;

	free_next_in_lock:
		free_lrw_que_next(wp1);
		unlock_task(res_lock,"_lr_option_insert");
		continue;
	free_next:
		free_lrw_que_next(wp1);
	}
	if ( lp )
		_load_meta_list_insert(ses,&res_lp1,"data",0,lp,Q_WAIT_WAIT);
}




int
lrw_len_req_next(LOAD_RESOURCE_WORK * wp)
{
int ret;
	ret = 0;
	for ( ; wp ; wp = wp->req_next )
		ret ++;
	return ret;
}

int
lrw_len_que_next(LOAD_RESOURCE_WORK * wp)
{
int ret;
	ret = 0;
	for ( ; wp ; wp = wp->que_next )
		ret ++;
	return ret;
}

void
rs_cache_setup_c_unit(int ses,URL * u,COORDINATE_UNIT * cu)
{
L_CHAR * url;
int ret;
RESOURCE * rr;
RS_BUF rsb;
	url = ll_copy_str(get_url_str2(u));
	setup_c_unit(cu,-1,url,0,0);

	if ( cu->system )
		goto end;

	setup_c_unit(cu,ses,url,0,0);

end:
	d_f_ree(url);
}


void
bomb()
{
/*
	gc_tick_notin_tick();
*/
}


void
_load_resource_task0(TKEY d)
{
int ses;
LOAD_RESOURCE_WORK * wp;
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
int i;
XLISP_ENV * env;
RS_BUF rsb;
XL_SEXP * ret, * last_tag;
L_CHAR * f;

	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_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_load_resource_task1");

		lock_task(res_lock);
		unlock_task(res_lock,"_load_resource_task1");

		wp = delete_queue(&res_q0,0,0,0);
		if ( wp == 0 ) {
			gc_pop(0,0);
			break;
		}
		if ( wp->que_next )
			er_panic("resource");
		switch ( wp->option ) {
		case LRO_FULL:
bomb();
			if ( get_rs_resource_cache(&rsb,
					get_url_str2(&wp->url)) < 0 ) {
/*
ss_printf("GET EMPTY %ls\n",get_url_str2(&wp->url));
*/
				insert_queue(&res_q1,wp,1);
				break;;
			}
/*
ss_printf("GET SUCCESS %ls\n",get_url_str2(&wp->url));
*/
			if ( rsb.flags & RSBF_MAP ) {
/*
ss_printf("MAP--------\n");
*/
				rs_cache_setup_c_unit(
					ses,
					&rsb.r->map.src,
					&rsb.r->map.cu_src);
				if ( rsb.r->map.cu_src.system == 0 ) {
					f = ll_copy_str(get_url_str2(&rsb.r->map.src));
					set_c_unit(&rsb.r->map.cu_src,
						f,
						l_string(std_cm,"base"),
						l_string(std_cm,"m"));
					rsb.r->h.flags |= RF_UNCACHE;
					d_f_ree(f);
				}
				rs_cache_setup_c_unit(
					ses,
					&rsb.r->map.dest,
					&rsb.r->map.cu_dest);
				if ( rsb.r->map.cu_dest.system == 0 ) {
					f = ll_copy_str(get_url_str2(&rsb.r->map.dest));
					set_c_unit(&rsb.r->map.cu_dest,
						f,
						l_string(std_cm,"base"),
						l_string(std_cm,"m"));
					rsb.r->h.flags |= RF_UNCACHE;
					d_f_ree(f);
				}
			}
			wp->result = rsb.r;
			wp->data_result = rsb.sexp;
			if ( gv_resource_env[rsb.r->h.type] ) {
				env = new_env(
					new_env_pair(gv_resource_env[rsb.r->h.type],
						gblisp_top_env0));
				set_env(env,l_string(std_cm,"__resource"),
					get_ptr(rsb.r,0));
				last_tag = wp->data_result;
				for ( ; get_type(last_tag) == XLT_PAIR &&
					get_type(cdr(last_tag)) != XLT_NULL ;
					last_tag = cdr(last_tag) );
				if ( get_type(last_tag) != XLT_PAIR ) {
					set_init_status_error(rsb.r,0);
					res_end_op(wp,LRWE_ERROR_NO_ROOT_XML,rsb.r);
ss_printf("--------- CACHE ERROR %i\n",rsb.r->h.type);
print_sexp(s_stdout,wp->data_result,0);
ss_printf("\n");
print_sexp(s_stdout,ret,0);
ss_printf("\n");
					break;
				}
				ret = eval(env,car(last_tag));
				if ( get_type(ret) == XLT_ERROR ) {
ss_printf("ERROR BODY 2\n");
print_sexp(s_stdout,rsb.sexp,0);
ss_printf("\n\n");
print_sexp(s_stdout,ret,0);
ss_printf("\n");

					set_init_status_error(rsb.r,ret);
					res_end_op(wp,LRWE_ERROR_BODY_EVAL,rsb.r);
					break;
				}
			}
			res_end_op(wp,LRWE_OK,wp->result);
			break;
		case LRO_UNIT:
			insert_queue(&res_q1,wp,1);
			break;
		default:
			er_panic("task0");
		}
	next:
		gc_pop(0,0);
	}

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

	close_session(ses);
	close_self_interpreter();

}


void
_load_resource_task1(TKEY d)
{
int ses;
LOAD_RESOURCE_WORK * wp;
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
int i;




	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_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_load_resource_task1");

		lock_task(res_lock);
		unlock_task(res_lock,"_load_resource_task1");
		wp = delete_res_queue_handle_max(que,key);
		if ( wp == 0 ) {
			gc_pop(0,0);
			break;
		}
		_load_meta_list_insert(ses,&res_q2,"meta",1,wp,Q_WAIT_WAIT);
		gc_pop(0,0);
	}

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

	close_session(ses);
	close_self_interpreter();

}



void
_load_resource_task2(TKEY d)
{
int ses;
LOAD_RESOURCE_WORK * wp, * _wp, ** wpp;
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
int i;


	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_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_load_resource_task2");
		wp = _load_meta_list_delete(ses,que,key);
		if ( wp == 0 ) {
			gc_pop(0,0);
			break;
		}
		_load_resource_list1(ses,wp,key);
		gc_pop(0,0);
	}

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

	close_session(ses);
	close_self_interpreter();

}


void
_lr_extend_task1(TKEY d)
{
int ses;
LOAD_RESOURCE_WORK * wp;
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
int i;


	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_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_lr_extend_task1");

		lock_task(res_lock);
		unlock_task(res_lock,"_load_resource_task1");
		wp = delete_res_queue_handle_max(que,key);
		if ( wp == 0 ) {
			gc_pop(0,0);
			break;
		}
		_lr_extend_insert(ses,wp,key);

		gc_pop(0,0);
	}

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

	close_session(ses);
	close_self_interpreter();

}



void
_lr_extend_task2(TKEY d)
{
int ses;
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
LOAD_RESOURCE_WORK * lp, * w;
int ret_f;


	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_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_load_resource_task3");
		w = lp = __load_meta_list_delete(&ret_f,ses,&res_lp1,key,1);

		if ( ret_f == 0 ) {
			gc_pop(0,0);
			break;
		}
		for ( ; lp  ; lp = lp->que_next ) {
			if ( lp->rt->setup_function )
				(*lp->rt->setup_function)(lp);
			res_end_op_extend(lp,LRWE_OK,lp->result,RF_CACHE);
		}
		free_lrw_que_next(w);
		gc_pop(0,0);
	}

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

	close_session(ses);
	close_self_interpreter();

}


/*
void
_load_resource_task3(TKEY d)
{
int ses;
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
LOAD_RESOURCE_WORK * w, * dw;


	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_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_load_resource_task4");
		w = delete_queue(&res_q3,sq_key_cond,key,0);
		if ( w == 0 ) {
			gc_pop(0,0);
			break;
		}
		dw = w;
		w = w->req_next;
		dw->req_next = 0;
		free_lrw_req_next(dw);
		_load_resource_list2(ses,w,key);
		gc_pop(0,0);
	}

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

	close_session(ses);
	close_self_interpreter();

}
*/



void
lrl_test(LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK * wp;
	fflush(stdout);
	ss_printf("LRL\n");
	for ( wp = w ; wp ; wp = wp->req_next ) {
		ss_printf("\t%ls %i %x %x %x %x\n",
			get_url_str2(&wp->url),
			wp->err,
			wp->result,
			wp->meta_result,
			wp->data_result);
/*
		if ( wp->meta_result ) {
			ss_printf("\tmeta:");
			print_sexp(s_stdout,wp->meta_result,0);
			ss_printf("\n");
		}
		if ( wp->data_result ) {
			ss_printf("\tdata:");
			print_sexp(s_stdout,wp->data_result,0);
			ss_printf("\n");
		}
*/
	}
	ss_printf("LRL END\n");
}

int
get_que_pri(URL * u)
{
int len;
	len = l_strlen(u->resource);
	if ( l_strcmp(&u->resource[len-4],
			l_string(std_cm,".crd")) == 0 )
		return Q_PRI_CRD;
	if ( l_strcmp(&u->resource[len-4],
			l_string(std_cm,".vct")) == 0 )
		return Q_PRI_CRD;
	if ( l_strcmp(&u->resource[len-4],
			l_string(std_cm,".lst")) == 0 )
		return Q_PRI_CRD;
	return Q_PRI_OTHER;
}

void
load_resource_list(LOAD_RESOURCE_WORK * w,int pri,int wait_flag)
{
L_CHAR * entry;
LOAD_RESOURCE_WORK * wp, * f;
int handling;


	if ( w == 0 )
		return;

	wp = w;
	handling = 0;
/*
ss_printf("IN (%i) - \n",get_tid());
*/
	for ( ; wp ; wp = wp->req_next ) {
		entry = get_url_str2(&wp->url);
/*
ss_printf("IN (%i) %ls\n",get_tid(),entry);
*/
		if ( entry == 0 ) {
			wp->err = LRWE_ERROR_URL;
			continue;
		}
		entry = ll_copy_str(entry);
		wp->result = search_resource_by_entry(&wp->url);
		wp->meta_result = 0;
		wp->wup = (int)w;
		if ( wp->result )
			wp->err = LRWE_OK;
		else 	wp->err = LRWE_HANDLING;
		wp->que_pri = get_que_pri(&wp->url);
		wp->h.key = get_server_key(&wp->url);
		switch ( wp->option ) {
		case 0:
			break;
		case LRO_UNIT:
			wp->que_pri = Q_PRI_CRD_META;
			if ( search_c_unit(entry) )
				wp->err = LRWE_OK;
			break;
		default:
			er_panic("load_resource_list");
		}
		wp->que_pri += pri;
		if ( wp->err == LRWE_HANDLING ) {
			handling ++;

			lock_task(res_lock);
			f = _search_first_list(wp);
			if ( f ) {
				wp->same_next = f->same_list;
				f->same_list = wp;
				wp->err = LRWE_DUP;
			}
			else {
				_insert_first_list(wp);
			}
			unlock_task(res_lock,"load_resource_list");
		}
		d_f_ree(entry);
	}
	lock_task(res_lock);
	if ( handling == 0 )
		goto slp2;
	wp = w;
	for ( ; wp ; wp = wp->req_next ) {
		if ( wp->err == LRWE_HANDLING )
			insert_queue(&res_q0,wp,1);
		else if ( wp->err == LRWE_DUP )
			wp->err = LRWE_HANDLING;
	}
	if ( wait_flag == 0 ) {
		unlock_task(res_lock,"load_resource_list");
		return;
	}
slp:

	sleep_task((int)w,res_lock);
	lock_task(res_lock);
	wp = w;
	for ( ; wp ; wp = wp->req_next )
		if ( wp->err == LRWE_HANDLING )
			goto slp;
slp2:
	for ( wp = w ; wp ; wp = wp->req_next ) {
		if ( wp->err != LRWE_OK )
			continue;
		if ( wp->result == 0 )
			continue;
		if ( !(wp->result->h.flags & RF_COMPLETE) ) {
			sleep_task((int)wp->result,res_lock);
			lock_task(res_lock);
			goto slp2;
		}
	}
	unlock_task(res_lock,"load_resource_list");
/*
ss_printf("OUT (%i)\n",get_tid());
*/

	return;
}


void
wait_setup_resource(LOAD_RESOURCE_WORK * w)
{
LOAD_RESOURCE_WORK * wp;

retry:
	lock_task(res_lock);
	wp = w;
	for ( ; wp ; wp = wp->req_next )
		if ( wp->err == LRWE_HANDLING || wp->err == LRWE_DUP ) {
			sleep_task((int)w->wup,res_lock);
			goto retry;
		}
slp2:
	for ( wp = w ; wp ; wp = wp->req_next ) {
		if ( wp->terminate != LRWE_OK &&
				wp->err == wp->terminate )
			continue;
		if ( wp->err != LRWE_OK )
			continue;
		if ( wp->result == 0 )
			continue;
		if ( !(wp->result->h.flags & RF_COMPLETE) ) {
			sleep_task((int)wp->result,res_lock);
			lock_task(res_lock);
			goto slp2;
		}
	}
	unlock_task(res_lock,"load_resource_list");
}

RESOURCE *
get_lrw(LOAD_RESOURCE_WORK * w,URL * u)
{
LOAD_RESOURCE_WORK * wp;

	wp = w;
	for ( ; wp ; wp = wp->req_next ){

		if ( wp->err != LRWE_OK )
			continue;
		if ( 	l_strcmp(wp->url.proto,u->proto) == 0 &&
			l_strcmp(wp->url.server,u->server) == 0 &&
			wp->url.port == u->port &&
			l_strcmp(wp->url.db,u->db) == 0 &&
			l_strcmp(wp->url.resource,u->resource) == 0 )  {

			return wp->result;
		}
	}
	return 0;
}


RESOURCE *
load_resource(int ses,URL * u,int pri)
{
LOAD_RESOURCE_WORK * w;
RESOURCE * r;

	w = new_lrw(0);
	copy_url(&w->url,u);
	w->err = LRWE_HANDLING;
	load_resource_list(w,pri,1);
	if ( w->err != LRWE_OK ) {
		r = 0;
	}
	else {
		r = w->result;
		free_lrw_req_next(w);
	}
	return r;
}



void
resource_disposer_task()
{
int ses;
XL_INTERPRETER * xli;
LOAD_RESOURCE_WORK * w, * dw;

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


	ses = open_session(SEST_DIRECT);
	for ( ; ; ) {
		gc_push(0,0,"_load_resource_task5");
		w = delete_queue(&res_disposer,0,0,1);
		dw = w;
		w = w->req_next;
		dw->req_next = 0;
		free_lrw_req_next(dw);
		wait_setup_resource(w);
		free_lrw_req_next(w);
		gc_pop(0,0);
	}

}


void
dispose_lrw(LOAD_RESOURCE_WORK * w,int err)
{
LOAD_RESOURCE_WORK * wp;
	w = new_lrw(w);
	for ( wp = w ; wp ; wp = wp->req_next )
		wp->terminate = err;
	insert_queue(&res_disposer,w,1);
}

int
resource_check(L_CHAR * url_str,int option)
{
RESOURCE * r;
URL u;
	get_url2(&u,url_str);
	r = search_resource_by_entry(&u);
	free_url(&u);
	if ( r == 0 ) {
		lock_task(res_lock);
		if ( _search_first_list_by_url(url_str,option) ) {
			unlock_task(res_lock,"resource_check");
			return CRS_LOADING;
		}
		unlock_task(res_lock,"resource_check");
		if ( option != LRO_UNIT )
			return CRS_NOTHING;
		if ( search_c_unit(url_str) )
			return CRS_EXIST;
		return CRS_NOTHING;
	}
	if ( r->h.initial_status == RS_ERROR )
		return CRS_ERROR;
	if ( r->h.flags & RF_COMPLETE )
		return CRS_EXIST;
	return CRS_LOADING;
}

void
set_lrw_err(LOAD_RESOURCE_WORK * w,int err)
{
	res_end_op_2(w,err,0);
}


int
lr_extend(RESOURCE * r,int (*wup_func)())
{
LOAD_RESOURCE_WORK * wp;

	wp = new_lrw(0);
	wp->err = LRWE_HANDLING;
	wp->wup_func = wup_func;
	wp->result = r;
	wp->h.key = get_server_key(&r->h.entry);
	wp->que_pri = 0;
	insert_queue(&res_extend,wp,1);
	return 0;
}

void
free_resource_entry(RESOURCE * r)
{
	printf("free_Resource_entry\n");
er_panic("free_resource_entry");
	return;
}

int
_check_lrw_status(LOAD_RESOURCE_WORK * w,int * sts,int len,
	int flags,int mask)
{
int i;
int ret;
	ret = -1;
	for ( i = 0 ; i < len ; i ++ ) {
		if ( w->err == sts[i] )
			ret = 0;
	}
	if ( ret < 0 )
		return -1;
	if ( w->result == 0 ) {
		if ( flags == 0 && mask == 0 )
			return 0;
		return -1;
	}
	if ( (w->result->h.flags & mask) == flags )
		return 0;
	return -1;
}

int
check_lrw_status(LOAD_RESOURCE_WORK * w,int * sts,int len,
	int flags,int mask)
{
int ret;
	lock_task(res_lock);
	ret = _check_lrw_status(w,sts,len,flags,mask);
	unlock_task(res_lock,"check_lrw_status");
	return ret;
}


void
_resource_cache_invoke(RESOURCE * r)
{
RS_BUF b;
	b.r = r;
	b.sexp = r->h.data;
	set_rs_resource_cache(&b);

	r->h.data = 0;
}


void
resource_cache_invoke()
{
int i;
RESOURCE * r;
extern RESOURCE ** res_no_hash_table;
RESOURCE_TYPE_LIST * rt;
int cnt,limit;

printf("RESORCE CACHE INVOKE\n");
	cnt = 0;
	limit = 1;
	for ( i = 0 ; i < RES_HASH_SIZE ; ) {
		lock_task(res_lock);
		for ( r = res_no_hash_table[i] ; r ; r = r->h.no_next )
			if ( (r->h.flags & (RF_CACHE|RF_COMPLETE|RF_LOAD_EXTEND_PROC|RF_UNCACHE|RF_ERROR))
					== RF_COMPLETE ) {
				break;
			}
		if ( r == 0 ) {
			unlock_task(res_lock,"resource_cache_invoke");
			i ++;
			continue;
		}
		r->h.flags |= RF_FIX;
		unlock_task(res_lock,"reource_cache_invoke");

		_resource_cache_invoke(r);

		lock_task(res_lock);
		r->h.flags &= ~RF_FIX;
		r->h.flags |= RF_CACHE;
		wakeup_task((int)r);
		unlock_task(res_lock,"resource_cache_invoke");
		cnt ++;
		if ( cnt >= limit ) {
			sleep_sec(1);
			cnt = 0;
			limit = limit << 1;
		}
	}
	flush_rs_cache();
}


