/**********************************************************************
 
	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 ___XL_H___
#define ___XL_H___

#include	"task.h"
#include	"server.h"
#include	"xllisp.h"
#include	"utils.h"
#include	"regular.h"
#include	"queue.h"

#define INTERPRETER_HASH_SIZE	20
#define THREAD_HASH_SIZE 	20

/* open error */
#define XLIE_CANNOT_OPEN_FILE	(-2)
#define XLIE_CANNOT_OPEN_DESCRIPTER (-3)
#define XLIE_CANNOT_OPEN_ACCEPT (-4)
#define XLIE_CANNOT_OPEN_CONNECT (-5)
#define XLIE_CANNOT_OPEN_BUSY	(-6)
#define XLIE_CANNOT_OPEN_DENIED	(-7)
#define XLIE_CANNOT_OPEN_SERVICE_INVALID (-8)

/* LOG LEVEL */
#define LOG_MESSAGE	0
#define LOG_WARNING	1
#define LOG_ERROR	2
#define LOG_SYSTEM	3
#define LOG_DEBUG	4
#define LOG_MAX_LEVEL	5

/* xl accept type */
#define XLA_STDIO	1
#define XLA_FILE	2
#define XLA_IPC		3
#define XLA_ACCEPT	4
#define XLA_CONNECT	5
#define XLA_DESCRIPTER	6
#define XLA_SELF	7
#define XLA_PIPE	8

typedef struct d_sexp {
	DELAY_FUNC		h;
	int			flags;
#define DSF_OK		0x00000001
	XL_SEXP *		ret;
} D_SEXP;


typedef struct xl_result {
	DELAY_FUNC		h;
	struct xl_result *	next;
	struct xl_result *	my_xli_result_next;
	int			seq_from;
	int			seq_to;
	int			remote_seq;
	XL_SEXP *		ret;
	int			flags;
#define XRF_INPUT	0x00000001
#define XRF_RETURN	0x00000002
	XLISP_ENV *		cur_env;
	struct xl_interpreter *	inp_interpreter;
	struct xl_interpreter *	out_interpreter;

	XL_FILE *		file;
	int			line;

	/* for session control */

	XLISP_ENV *		s_env;
	int			s_id;
	URL			s_url;
	L_CHAR *		s_agent;
	L_CHAR * 		s_login_mode;
	L_CHAR * 		s_center_cmd;
	XL_SEXP * 		s_cmd;
	XL_FILE *		s_file;
	int			s_line;
	struct con_session *	s_session;
	int			s_proxy_ses;

	XL_SEXP *		send;

	int			wup_key;
} XL_RESULT;

typedef struct xl_fifo {
	struct xl_fifo *	next;
	XL_SEXP *		cmd;
} XL_FIFO;

typedef struct p_mode {
	struct p_mode *		next;
	L_CHAR *		name;
} P_MODE;

typedef struct permission_list {
	struct permission_list * next;
	ACCESS_PERMISSION 	ap;
	P_MODE *		mode;
} PERMISSION_LIST;


typedef struct delay_que_t {
	Q_HEADER			h;
	XL_SEXP *			ret;
	struct xl_interpreter * 	xli;
	int				line;
} DELAY_QUE_T;

typedef struct xl_interpreter {
	struct xl_interpreter *	next;
	unsigned int	id;
	XL_FIFO *	fifo_head;
	XL_FIFO *	fifo_tail;
	XL_RESULT *	result_head;
	int		mode;
#define XIM_RUN		0
#define XIM_FLONT_WAIT	1
#define XIM_QUEUE_WAIT	2
#define XIM_RELAY_WAIT	3
#define XIM_CLOSE	4
#define XIM_ERROR 	5
	int		front_thread;
	int		relay_thread;
	int		silent_cnt;
	int		connection_cnt;
	int		flags;
#define XIF_BREAK	0x00000001
#define XIF_CANCEL	0x00000002
#define XIF_TERMINAL	0x00010000
#define XIF_ASYNC	0x00020000
#define XIF_PERMISSION	0x00040000
#define XIF_P_MASK	0x00700000
#define XIF_P_ALLOW	0x00100000
#define XIF_P_DENIED	0x00200000
#define XIF_P_BUSY	0x00300000
#define XIF_P_ERROR	0x00400000
#define XIF_P_STREAM	0x00500000
#define XIF_FIX_CODE	0x01000000
#define XIF_CODE_SYNC	0x02000000
#define XIF_CTO_LOCK	0x04000000
#define XIF_LOCK_F	0x08000000
#define XIF_LOCK_DISE	0x10000000
	unsigned int	open_timeout;


	struct xl_result *
			result_list;
	struct xl_interpreter *
			inp_interpreter;
	int		inp_line;

	int		out_lock;
	int		out_lock_task;

	int		connect_ip;

	char		accept_lock;
	unsigned int	accept_last_dec;

	/* user definition */
	int		ps_flags;
	char		a_type;
	char		thread_mode;
#define TM_1		1
#define TM_2		2
#define TM_SELF		3
	char		proxy_type;
#define PT_NO_PROXY		0x01
#define PT_XLoHTTP		0x02
#define PT_HTTP_PROXY		0x04
#define PT_NATIVE_PROXY		0x08
#define PT_DONT_CARE		0x40
	char		result_flag;
	L_CHAR *	msg;
	STREAM *	inp;
	STREAM *	out;
	STREAM *	err;
	XLISP_ENV *	env;

	int		port;
	int		port_limit;
	int		ip;
	L_CHAR *	hostname;
	int		max_connection;
	L_CHAR *	input_file_name;
	L_CHAR *	output_file_name;
	L_CHAR *	error_file_name;
	int		connection_timeout;
	int		silent_timeout;
	int		environment;
	PERMISSION_LIST * pl_head;
	PERMISSION_LIST * pl_tail;
	PERMISSION_LIST * pl_accept;
	int		inp_desc;
	int		out_desc;
	int		err_desc;
	int		desc_type;

	unsigned int	accept_interval;

	int		delay_que_cnt;
} XL_INTERPRETER;

typedef struct xl_thread {
	struct xl_thread *	next;
	int			tid;
	XL_INTERPRETER *	xli;
} XL_THREAD;

typedef struct xl_gf_cmd {
	struct xl_gf_cmd *	next;
	L_CHAR *		cmd;
} XL_GF_CMD;

typedef struct xl_getfile {
	struct xl_getfile *	next;
	int			flags;
#define XLGFM_XLDIR		0x00000003
#define XLGF_XLSYS_ONLY		0x00000000
#define XLGF_XLDOC_ONLY		0x00000001
#define XLGF_XLSYS_PRECEDENCE	0x00000002
#define XLGF_XLDOC_PRECEDENCE	0x00000003
#define XLGFM_LOCK		0x0000000c
#define XLGF_LOCK_OFF		0x00000000
#define XLGF_URL_PATH		0x00000004
#define XLGF_FULL_PATH		0x00000008
	L_CHAR *		prefix;
	L_CHAR *		agent;
	L_CHAR *		mode;
	XL_GF_CMD *		cmd;
} XL_GETFILE;
#define GETFILE_HASH_SIZE	100

typedef struct server_info {
	int			active_flags;
#define SIA_STATUS		0x00000001
#define SIA_IP			0x00000002
#define SIA_NAME		0x00000004
#define SIA_THPUT		0x00000008
#define SIA_DATA		0x00000010
	int			status;
#define SIS_UNKNOWN		0x00000001
#define SIS_UNRESOLVE		0x00000002
#define SIS_MISSING		0x00000004
#define SIS_CONNECTABLE		0x00000008
#define SIS_CONNECT		0x00000010
#define SIS_ALL			0xffffffff
	char *			name;
	unsigned int		ip;
	int			thput;
	int			data;
} SERVER_INFO;

#define SIC_SET		1
#define SIC_SET_IF_ZERO	2
#define SIC_AVG		3

#define SI_HASH_SIZE	13


typedef struct call_lock_descripter {
	void *		d;
	int		tid;
} CALL_LOCK_DESCRIPTER;
#define CLT_READ_LOCK		1
#define CLT_WRITE_LOCK		2

CALL_LOCK_DESCRIPTER
call_lock(L_CHAR * lock_dir,int type);
int
call_unlock(CALL_LOCK_DESCRIPTER d);
XL_SEXP * get_cl_error(XL_SEXP *,char *);
int cl_error_check(CALL_LOCK_DESCRIPTER);
CALL_LOCK_DESCRIPTER cl_invalid();

void init_xl(int);
void init_function(XLISP_ENV *,XLISP_ENV *,int,char **);
XL_INTERPRETER * new_xl_interpreter();
void init_xl_interpreter(XL_INTERPRETER * xs);
void put_xl_fifo(XL_INTERPRETER *,XL_SEXP *);
XL_SEXP * get_xl_fifo(XL_INTERPRETER *,int);
#define XFF_BLOCK	0
#define XFF_NONBLOCK	1
int check_fifo(XL_INTERPRETER *);
void close_xl_fifo(XL_INTERPRETER *);
int return_result(XL_INTERPRETER *,XL_SEXP *);
XL_SEXP * remote_query(int,XLISP_ENV *,L_CHAR *,XL_SEXP *);
XL_SEXP * local_query(XLISP_ENV *,L_CHAR *,XL_SEXP *);
XL_SEXP * local_eval(int seq_no,XL_SEXP * cmd_sexp);
int setup_i(XL_INTERPRETER*);

void new_interpreter(XL_INTERPRETER *);
void close_interpreter(int id);
int setup_xl_interpreter(XL_INTERPRETER *);
void wait_stop_interpreter(int );
void wait_stop_all();

XL_INTERPRETER * _search_xli_id(unsigned int);
XL_INTERPRETER * search_xli_id(int);
XL_INTERPRETER * _search_xli_thread(unsigned int tid);
int check_iid(int);

XL_INTERPRETER * _get_my_xli();
XL_INTERPRETER * get_my_xli();
XL_SEXP * get_user_ip(XLISP_ENV *);
int get_my_iid();

void
new_permission_list(XL_INTERPRETER * xli,XL_SEXP * mode);

XL_SEXP * _q_xml(XLISP_ENV *,XL_SEXP*,XLISP_ENV*,XL_SYM_FIELD*);

XL_GETFILE * search_getfile(L_CHAR *,L_CHAR *);
void insert_getfile(L_CHAR *,L_CHAR *,L_CHAR *,int,XL_SEXP *);
XL_GETFILE * search_getfile_by_prefix(L_CHAR * ,XL_GETFILE *);
XL_SEXP *
get_path(L_CHAR * target[2],XL_GETFILE ** gfp,
	 L_CHAR * _filename,XL_SEXP * s,L_CHAR * func_name);

extern int (*agent_open_xli)();
extern int (*agent_close_xli)();

XL_SEXP * connect_lock(XL_SEXP * s,L_CHAR * dir,char * type);
void connect_unlock(XL_SEXP * s,int id,L_CHAR * dir);

XL_SEXP *
load_file(XLISP_ENV * env,XL_SEXP * s,int type,L_CHAR * filename,
	L_CHAR * ,AUTOMATON * ,int,void (*func)(),void * work);
void send_code_sync(int iid);

int open_session(int type);
#define SEST_OPTIMIZE	1
#define SEST_DIRECT	2

void close_session();
XL_SEXP *
remote_session(
	XLISP_ENV * env,
	int id,
	URL * u,
	L_CHAR * agent,
	L_CHAR * login_mode,
	L_CHAR * center_cmd,
	XL_SEXP * cmd,
	XL_FILE * f,
	int ln,
	int session_lock_enable);
L_CHAR * compose_path(L_CHAR *,L_CHAR *);
XL_SEXP * err_handler(XL_SEXP *,XL_FILE *,int);

/* Relational Operation flags */
#define RO_SORT1	0x00000001
#define RO_SORT2	0x00000002

int log_printf(int,char*,...);
void set_log_path(L_CHAR*,int,int);
int
log_print_sexp(
	int level,
	char * str,
	XL_SEXP * s,
	int flags);
L_CHAR get_proper_code(XL_SEXP *,int);

void inp_lock_function(L_CHAR *);
void out_lock_function(int);
void set_lock_function(L_CHAR*);
void unlock_xli_out_iid(int iid);
void lock_xli_out_iid(int iid);

void xl_setup_file(int,char **);

int get_serverinfo(SERVER_INFO *);
int set_serverinfo(SERVER_INFO *,int cmd,int set_if);

XL_SEXP * reverse(XL_SEXP *);
void close_self_interpreter();

XL_SEXP * new_d_sexp(D_SEXP ** d);
void set_d_sexp(D_SEXP * d,XL_SEXP * ret);

int check_remote_delay(XL_RESULT * resp,int key);
int _check_remote_delay(XL_RESULT * resp,int key);
int check_remote_session_delay(XL_RESULT * resp,int key);


int set_c_timeout(int,int);
int get_c_timeout(int);


int set_initial_sexp(int,XLISP_ENV*,XL_SEXP*);
int set_native_proxy(URL * u);
int set_native_proxy_direct_access(L_CHAR *);
XL_SEXP * get_native_proxyinfo();
void compare_gc_check_point(char * msg,void * p);
void *  get_gc_check_point();
void np_divide_p_agent(URL * u);



#endif
