/**********************************************************************
 
	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.

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



#ifndef ___ROUTING_H___
#define ___ROUTING_H___

#include	"queue.h"

#define MP_ROUTE_CACHE_SIZE	1000
#define ERR_ROUTE_TIMEOUT	120

typedef struct mp_path {
	struct mp_path *	next;
	L_CHAR *		url;
} MP_PATH;


typedef struct mpr_check_point {
	struct mpr_check_point *	next;
	char *				file;
	int				line;
} MPR_CHECK_POINT;


typedef struct mp_route {
	struct mp_route *	next;
	struct mp_route *	prev;
	short			sts;
#define RS_LOADING		0
#define RS_OK			1
#define RS_ERR			2
#define RS_COPY			3
#define RS_DELETE		4
	short			flags;
#define RF_DIRTY	0x0001
	int			lock;
	int			lwait;
	MP_PATH * 		head;
	MP_PATH *		tail;
	unsigned int		modify;
	unsigned int		update;

	MPR_CHECK_POINT *	cp;
	int			w_cond;
} MP_ROUTE;


typedef struct mp_cache {
	MP_ROUTE *		cache;
	MP_ROUTE *		root;
	MP_ROUTE *		free_list;
} MP_CACHE;

typedef struct mp_err_route {
	struct mp_err_route *	next;
	unsigned int		err_time;
	L_CHAR *		head;
	L_CHAR * 		tail;
} MP_ERR_ROUTE;

typedef struct mp_route_t {
	Q_HEADER		h;
	L_CHAR *		start;
	L_CHAR *		target;
	int			flags;
#define RQT_LOCK_MASK		0x00000001
#define RQT_RESULT_MASK		0x00000010

#define RQT_UNLOCK		0x00000000
#define RQT_LOCK		0x00000001

#define RQT_ROUTE		0x00000000
#define RQT_MAPHISTORY		0x00000010

#define RQT_ROUTE_RES_MASK	0x00000f00
#define RQT_MH_RES_MASK		0x0000f000
#define RQT_ROUTE_OK		0x00000100
#define RQT_ROUTE_ERR		0x00000200
#define RQT_MH_OK		0x00001000
#define RQT_MH_ERR		0x00002000

#define RQT_ROUTE_REVERSE	0x00010000
/*
	int			wait_mode;
*/
	MP_ROUTE *		route;
	MAP_HISTORY *		mh;

	/* work erea */

	XL_SEXP *		get;

	L_CHAR * 		handle1_start;
	L_CHAR * 		handle1_target;

	L_CHAR * 		handle2_start;
	L_CHAR * 		handle2_target;

	struct mp_route_t *	next;
} MP_ROUTE_T;

#define MP_NO_ROUTE	((MP_ROUTE*)-1)
#define MP_MH_NO_ROUTE	((MAP_HISTORY*)-1)

MP_ROUTE * resolve_route(L_CHAR * start,L_CHAR * target,int wait_flag);
#define RR_WM_NO_WAIT		0
#define RR_WM_DIRECT		3
#define RR_WM_DIRECT_NO_WAIT	4
#define RR_WM_INDIRECT		5
#define RR_WM_INDIRECT_NO_WAIT	6

#define RI_DIRECT	0
#define RI_INDIRECT	1
#define RI_LOADING	2
#define RI_UNRESOLVE	3
#define RI_ERR		4

void flush_route(MP_ROUTE * r);
MAP_HISTORY * get_mh_from_route(int ses,URL * u,MP_ROUTE * mpr);

int check_routing_table(L_CHAR * start,L_CHAR * target);
int check_mappath(L_CHAR * org,L_CHAR * target,int);
void init_routing();
void routing_global();
void init_mp_cache(MP_CACHE * c);
void gc_routing_get(MP_ROUTE_T * n);
void gc_routing(MP_ROUTE_T * n);
void insert_rring(MP_CACHE * c,MP_ROUTE * r);
void delete_rring(MP_ROUTE * r);
MP_ROUTE_T * new_mp_route_t(L_CHAR * start,L_CHAR * target,int flags);
void _insert_purge_url(L_CHAR * url);
void insert_purge_url(L_CHAR * url);
L_CHAR * _delete_purge_url();
L_CHAR *delete_purge_url();
void free_mp_route_t(MP_ROUTE_T * n);
void _wait_mp_route(MP_ROUTE_T * n);
MP_ERR_ROUTE * _search_err_route(L_CHAR * head,L_CHAR * tail);
MP_ERR_ROUTE * search_err_route(L_CHAR * head,L_CHAR * tail);
MP_ERR_ROUTE * _new_err_route(L_CHAR * head,L_CHAR * tail);
MP_ERR_ROUTE * new_err_route(L_CHAR * head,L_CHAR * tail);
void err_route_tick();
void free_path(MP_ROUTE * r);
void _delete_route(MP_CACHE * c,MP_ROUTE * r);
void free_mp_path(MP_PATH * p);
void free_copy_route(MP_ROUTE * r);
MP_ROUTE * _xx_copy_route(MP_ROUTE * r,char*,int);
#define _copy_route(r)	_xx_copy_route(r,__FILE__,__LINE__)
MP_PATH * copy_mp_path(MP_PATH * p);
MP_PATH * sr_url(MP_PATH * path,L_CHAR * u);
void dump_route(MP_CACHE * cc);
MP_ROUTE * _xx_new_route(MP_CACHE * cc,char *,int);
#define _new_route(cc)	_xx_new_route(cc,__FILE__,__LINE__)
MP_ROUTE * _xx_new_route2(MP_CACHE * cc,L_CHAR * start,L_CHAR * target,char*,int);
#define _new_route2(cc,start,target)	_xx_new_route2(cc,start,target,__FILE__,__LINE__)
MP_ROUTE *_search_route(MP_CACHE * cc,L_CHAR * start,L_CHAR * target);
void _delete_route_cache(MP_CACHE * cc,L_CHAR * start,L_CHAR * target);
MP_PATH * copy_mp_path_list(MP_PATH * p);
int cmp_mp_path(MP_PATH * a,MP_PATH * b);
MP_ROUTE * _insert_route(MP_ROUTE * r,XL_SEXP * list,L_CHAR * start,L_CHAR * target);
MP_PATH * path_optimization(MP_PATH * path);
MP_PATH * _resolve_indirect_path(L_CHAR * start,L_CHAR * target);
MP_ROUTE *_resolve_direct(L_CHAR * start,L_CHAR * target);
MP_ROUTE *_resolve_indirect(int * sts,L_CHAR * start,L_CHAR * target);
MP_ROUTE * _get_in_file(L_CHAR * start,L_CHAR * target);
MP_ROUTE * _resolve_in_file(MP_ROUTE ** org,L_CHAR * start,L_CHAR * target);
L_CHAR *  get_body(L_CHAR * url);
void _resolve_route(MP_ROUTE_T * n);
int rr_task2_cond(SYS_QUEUE * q,MP_ROUTE_T * n,L_CHAR * key);
void routing_cache_invoke();
MP_ROUTE * identify_routing(L_CHAR * start);
int path_length(MP_PATH * p);
void print_mpr(MP_ROUTE * mpr);
void ss_print_mpr(MP_ROUTE * mpr);
void _check_mappath_mh(L_CHAR * org,L_CHAR * target,MAP_HISTORY * mh,MP_ROUTE * mpr);
void check_mappath_mh(L_CHAR * org,L_CHAR * target,MAP_HISTORY * mh,MP_ROUTE * mpr);
int check_mh_from_route(URL * u,MP_ROUTE * mpr,int loading_flag);
XL_SEXP * gb_resolve_mapping_path(
	XLISP_ENV * env,
	XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf);
void init_gb_resolve_mapping_path(XLISP_ENV * env);
void _new_mpr_cp(MP_ROUTE * r,char * f,int ln);
void _free_mpr_cp(MP_ROUTE * r);
void new_mpr_cp(MP_ROUTE * r,char * f,int ln);
void free_mpr_cp(MP_ROUTE * r);
#define _check_mpr_cp(r)	_new_mpr_cp(r,__FILE__,__LINE__)
#define check_mpr_cp(r)	new_mpr_cp(r,__FILE__,__LINE__)



#define CRT_NOTHING		0
#define CRT_LOADING		1
#define CRT_ROUTING_EXIST	2
#define CRT_LOADING_RES		3
#define CRT_EXIST		4
#define CRT_ERROR		5
#define CRT_MAX			6

#endif

