42#include <libxml/parser.h>
43#include <libxml/tree.h>
44#include <libxml/xinclude.h>
77static char *
me =
"statserver";
80DWORD current_control_tls;
81static int init_control_tls = 0;
82#elif YAZ_POSIX_THREADS
83static pthread_key_t current_control_tls;
84static int init_control_tls = 0;
92#define STAT_DEFAULT_LOG_LEVEL "server,session,request"
161 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
162 strcmp((
const char *) ptr->name,
"yazgfs"))
182 for (p = ptr; p; p = p->next)
184 if (p->type == XML_TEXT_NODE)
185 len += xmlStrlen(p->content);
190 for (p = ptr; p; p = p->next)
192 if (p->type == XML_TEXT_NODE)
202 strcat((
char *)str, (
const char *)cp);
206 cp = strlen((
const char *)str) + str;
270 char vhost[128], *cp;
273 strncpy(vhost, host, 127);
275 cp = strchr(vhost,
':');
286 int listen_match = 0;
299 if (listen_match && host_match)
352 for (ptr = ptr->children; ptr; ptr = ptr->next)
354 struct _xmlAttr *attr;
355 if (ptr->type != XML_ELEMENT_NODE)
357 attr = ptr->properties;
358 if (!strcmp((
const char *) ptr->name,
"listen"))
364 const char *address =
366 for ( ; attr; attr = attr->next)
367 if (!xmlStrcmp(attr->name, BAD_CAST
"id")
368 && attr->children && attr->children->type == XML_TEXT_NODE)
373 gfslp = &(*gfslp)->
next;
377 else if (!strcmp((
const char *) ptr->name,
"server"))
379 xmlNodePtr ptr_server = ptr;
381 const char *listenref = 0;
385 for ( ; attr; attr = attr->next)
386 if (!xmlStrcmp(attr->name, BAD_CAST
"listenref")
387 && attr->children && attr->children->type == XML_TEXT_NODE)
389 else if (!xmlStrcmp(attr->name, BAD_CAST
"id")
391 && attr->children->type == XML_TEXT_NODE)
404 sizeof(
int) * (num + 1));
405 for (i = 0; i < num; i++)
410 for (id_no = 1; gl; gl = gl->
next, id_no++)
411 if (gl->
id && !strcmp(gl->
id, refs[i]))
418 "in server config element", refs[i]);
422 for (ptr = ptr_server->children; ptr; ptr = ptr->next)
424 if (ptr->type != XML_ELEMENT_NODE)
426 if (!strcmp((
const char *) ptr->name,
"host"))
431 else if (!strcmp((
const char *) ptr->name,
"config"))
438 base_path, 0, fpath))
441 else if (!strcmp((
const char *) ptr->name,
"cql2rpn"))
452 "open CQL transform file '%s'", fname);
456 else if (!strcmp((
const char *) ptr->name,
"ccl2rpn"))
458 char *fname, fpath[1024];
465 if ((f = fopen(fname,
"r")) == 0) {
473 else if (!strcmp((
const char *) ptr->name,
"directory"))
478 else if (!strcmp((
const char *) ptr->name,
"docpath"))
483 else if (!strcmp((
const char *) ptr->name,
"maximumrecordsize"))
488 else if (!strcmp((
const char *) ptr->name,
"stylesheet"))
493 else if (!strcmp((
const char *) ptr->name,
494 "client_query_charset"))
499 else if (!strcmp((
const char *) ptr->name,
"explain"))
503 else if (!strcmp((
const char *) ptr->name,
"retrievalinfo"))
522 gfsp = &(*gfsp)->
next;
539 init_control_tls = 1;
540 current_control_tls = TlsAlloc();
541#elif YAZ_POSIX_THREADS
542 init_control_tls = 1;
543 pthread_key_create(¤t_control_tls, 0);
548 if (fname[0] ==
'\0')
562 if (noSubstitutions == -1)
570 last_p = strrchr(fname,
602 if (init_control_tls)
603 TlsFree(current_control_tls);
604#elif YAZ_POSIX_THREADS
605 if (init_control_tls)
606 pthread_key_delete(current_control_tls);
616 for (id_no = 1; gfs; gfs = gfs->
next, id_no++)
629 for (; gfs; gfs = gfs->
next)
655 for (; gfs; gfs = gfs->
next)
683typedef struct _ThreadList ThreadList;
692static ThreadList *pFirstThread;
693static CRITICAL_SECTION Thread_CritSect;
694static BOOL bInitialized = FALSE;
696static void ThreadList_Initialize()
699 InitializeCriticalSection(&Thread_CritSect);
708static void statserv_add(HANDLE hThread,
IOCHAN pIOChannel)
711 EnterCriticalSection(&Thread_CritSect);
715 ThreadList *pNewThread = (ThreadList *)
malloc(
sizeof(ThreadList));
716 pNewThread->hThread = hThread;
717 pNewThread->pIOChannel = pIOChannel;
718 pNewThread->pNext = pFirstThread;
719 pFirstThread = pNewThread;
722 LeaveCriticalSection(&Thread_CritSect);
729 EnterCriticalSection(&Thread_CritSect);
732 ThreadList *pCurrentThread = pFirstThread;
733 ThreadList *pNextThread;
734 ThreadList *pPrevThread =NULL;
737 for (; pCurrentThread != NULL; pCurrentThread = pNextThread)
740 if (pCurrentThread->pIOChannel == pIOChannel)
744 if (pPrevThread == NULL)
745 pFirstThread = pCurrentThread->pNext;
747 pPrevThread->pNext = pCurrentThread->pNext;
750 free(pCurrentThread);
758 pNextThread = pCurrentThread->pNext;
759 pPrevThread = pCurrentThread;
764 LeaveCriticalSection(&Thread_CritSect);
775 HANDLE *pThreadHandles = NULL;
779 EnterCriticalSection(&Thread_CritSect);
784 ThreadList *pCurrentThread = pFirstThread;
790 for (; pCurrentThread != NULL; pCurrentThread = pCurrentThread->pNext)
794 closesocket(pCurrentThread->pIOChannel->fd);
802 HANDLE *pCurrentHandle ;
805 pThreadHandles = (HANDLE *)
malloc(
sizeof(HANDLE) * iHandles);
806 pCurrentHandle = pThreadHandles;
808 for (pCurrentThread = pFirstThread;
809 pCurrentThread != NULL;
810 pCurrentThread = pCurrentThread->pNext, pCurrentHandle++)
813 *pCurrentHandle = pCurrentThread->hThread;
818 LeaveCriticalSection(&Thread_CritSect);
826 WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE);
829 free(pThreadHandles);
834 DeleteCriticalSection(&Thread_CritSect);
900 newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan);
901 if (newHandle == (HANDLE) -1)
909 statserv_add(newHandle, new_chan);
911 yaz_log(
YLOG_DEBUG,
"Created new thread, id = %ld iochan %p",(
long) newHandle, new_chan);
982 if ((res = fork()) < 0)
1014#if YAZ_POSIX_THREADS
1015 pthread_t child_thread;
1016 pthread_create(&child_thread, 0,
new_session, new_line);
1017 pthread_detach(child_thread);
1045 unsigned cs_get_mask, cs_accept_mask,
mask =
1051 cs_accept_mask =
mask;
1084 no_sessions, a ? a :
"[Unknown]", (
long) getpid());
1121 addr ? addr :
"[UNKNOWN]");
1160 listen_id, (
long) getpid());
1200 for (; l; l = l->
next)
1208 while (waitpid(-1, 0, WNOHANG) > 0)
1217 if (init_control_tls)
1221#elif YAZ_POSIX_THREADS
1222 if (init_control_tls)
1224 pthread_getspecific(current_control_tls);
1242 if (init_control_tls)
1243 TlsSetValue(current_control_tls, block);
1244#elif YAZ_POSIX_THREADS
1245 if (init_control_tls)
1246 pthread_setspecific(current_control_tls, block);
1273 char vstr[20], sha1_str[41];
1278 printf(
"YAZ DLL/SO: %s %s\n", vstr, sha1_str);
1287 ThreadList_Initialize();
1297 if ((
me = strrchr(argv[0], sep)))
1367 while ((ret =
options(
"1a:iszSTl:v:u:c:w:t:k:Kd:A:p:DC:f:m:r:V",
1368 argv, argc, &arg)) != -2)
1384 fprintf(stderr,
"%s: SR protocol no longer supported\n",
me);
1391#if YAZ_POSIX_THREADS
1395 fprintf(stderr,
"%s: Threaded mode not available.\n",
me);
1405 fprintf(stderr,
"%s: Specify time format for log file.\n",
me);
1430 if (!arg || !(r = atoi(arg)))
1432 fprintf(stderr,
"%s: Specify positive timeout for -t.\n",
me);
1438 if (!arg || !(r = atoi(arg)))
1440 fprintf(stderr,
"%s: Specify positive size for -k.\n",
me);
1468 fprintf(stderr,
"%s: Option -f unsupported since YAZ is compiled without Libxml2 support\n",
me);
1476 if (!arg || !(r = atoi(arg)))
1478 fprintf(stderr,
"%s: Specify positive size for -r.\n",
me);
1487 fprintf(stderr,
"Usage: %s [ -a <pdufile> -v <loglevel>"
1488 " -l <logfile> -u <user> -c <config> -t <minutes>"
1489 " -k <kilobytes> -d <daemon> -p <pidfile> -C certfile"
1490 " -zKiDSTV1 -m <time-format> -w <directory> <listener-addr>... ]\n",
me);
1513 cb->service_name, cb->service_display_name
void ccl_qual_file(CCL_bibset bibset, FILE *inf)
CCL_bibset ccl_qual_mk(void)
creates Bibset
COMSTACK cs_create_host(const char *vhost, int blocking, void **vp)
void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
const char * cs_strerror(COMSTACK h)
#define cs_bind(handle, ad, mo)
#define cs_addrstr(handle)
#define cs_accept(handle)
#define cs_createbysocket(sock, type, blocking, proto)
#define cs_fileno(handle)
struct comstack * COMSTACK
#define cs_listen(handle, ap, al)
#define cs_listen_check(handle, ap, al, cf, cd)
int yaz_daemon(const char *progname, unsigned int flags, void(*work)(void *data), void *data, const char *pidfile, const char *uid)
daemon utility.
Header for errno utilities.
int iochan_event_loop(IOCHAN *iochans, int *watch_sig)
IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags, int chan_id)
Definitions for event loop handling for GFS.
#define iochan_settimeout(i, t)
#define iochan_getdata(i)
#define iochan_destroy(i)
#define iochan_getnext(i)
#define iochan_setdata(i, d)
#define iochan_setflags(i, d)
void yaz_log_init_prefix(const char *prefix)
sets log message prefix
int yaz_log_mask_str(const char *str)
converts log level string to log level (integer)
void yaz_log_init_max_size(int mx)
sets limit in bytes for size for log file
void yaz_log_init_level(int level)
sets log level
void yaz_log_time_format(const char *fmt)
sets time format for log mesages
void yaz_log(int level, const char *fmt,...)
Writes log message.
void yaz_log_init_file(const char *fname)
sets log file
int yaz_log_module_level(const char *name)
returns level for module
#define YLOG_WARN
log level: warning
#define YLOG_FATAL
log level: fatal
#define YLOG_ERRNO
log level: append system error message
#define YLOG_DEBUG
log level: debugging
#define YLOG_LOG
log level: log (regular)
NMEM nmem_create(void)
returns new NMEM handle
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
struct nmem_control * NMEM
NMEM handle (an opaque pointer to memory).
void nmem_strsplit(NMEM nmem, const char *delim, const char *dstr, char ***darray, int *num)
allocates sub strings out of string using certain delimitors
char * nmem_printf(NMEM nmem, const char *fmt,...)
formats and prints a string into NMEM allocated memory
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
char * nmem_strdup_null(NMEM mem, const char *src)
allocates string on NMEM handle - allows NULL ptr buffer
int options(const char *desc, char **argv, int argc, char **arg)
command-line options parsing for main
Header for command line options parsing utilities.
const char * yaz_retrieval_get_error(yaz_retrieval_t p)
int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
yaz_retrieval_t yaz_retrieval_create()
void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
void yaz_sc_destroy(yaz_sc_t *s)
frees service control handle
int yaz_sc_program(yaz_sc_t s, int argc, char **argv, int(*sc_main)(yaz_sc_t s, int argc, char **argv), void(*sc_stop)(yaz_sc_t s))
registers service controlled program
yaz_sc_t yaz_sc_create(const char *service_name, const char *display_name)
creates service handle
void yaz_sc_running(yaz_sc_t s)
signals that sc_main applicatio starts running
Header for Windows Service Control utility.
association * create_association(IOCHAN channel, COMSTACK link, const char *apdufile)
static void get_logbits(void)
void ir_session(IOCHAN h, int event)
static int log_sessiondetail
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Header for config file reading utilities.
static void * new_session(void *vp)
static void option_copy(char *dst, const char *src)
static xmlDocPtr xml_config_doc
int statserv_main(int argc, char **argv, bend_initresult *(*bend_init)(bend_initrequest *r), void(*bend_close)(void *handle))
static struct gfs_listen * gfs_listen_list
static int statserv_sc_main(yaz_sc_t s, int argc, char **argv)
static struct gfs_server * gfs_server_new(const char *id)
static void gfs_server_chdir(struct gfs_server *gfs)
static char gfs_root_dir[FILENAME_MAX+1]
static char * nmem_dup_xml_content(NMEM n, xmlNodePtr ptr)
static void statserv_reset(void)
static char * programname
static void catchchld(int num)
static void remove_listeners(void)
static struct gfs_server * gfs_server_list
static void inetd_connection(int what)
int control_association(association *assoc, const char *host, int force_open)
static void listener(IOCHAN h, int event)
static void xml_config_close(void)
int check_options(int argc, char **argv)
void statserv_sc_stop(yaz_sc_t s)
static statserv_options_block * current_control_block
statserv_options_block control_block
#define STAT_DEFAULT_LOG_LEVEL
void statserv_setcontrol(statserv_options_block *block)
static int xml_config_add_listeners(void)
statserv_options_block * statserv_getcontrol(void)
static void xml_config_read(const char *base_path)
void statserv_remove(IOCHAN pIOChannel)
static void xml_config_bend_start(void)
static struct gfs_listen * gfs_listen_new(const char *id, const char *address)
static void statserv_closedown(void)
static void normal_stop_handler(int num)
static int add_listener(char *where, int listen_id)
static void daemon_handler(void *data)
static xmlNodePtr xml_config_get_root(void)
static void show_version(void)
static void xml_config_bend_stop(void)
static int xml_config_open(void)
Header for GFS (Obsolete. Use yaz/backend.h).
struct bend_initrequest * init
struct gfs_server * server
statserv_options_block * last_control
Information for the Init handler.
result for init handler (must be filled by handler)
yaz_retrieval_t retrieval
cql_transform_t cql_transform
statserv_options_block cb
char * client_query_charset
bend_initresult *(* bend_init)(bend_initrequest *r)
char configname[BEND_NAME_MAX]
void(* bend_close)(void *handle)
int check_ip_tcpd(void *cd, const char *addr, int len, int type)
int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname)
COMSTACK tcpip_type(int s, int flags, int protocol, void *vp)
Header for TCP/IP + SSL COMSTACK.
char * yaz_filepath_resolve(const char *fname, const char *path, const char *base, char *fullpath)
resolve file on path
unsigned long yaz_version(char *version_str, char *sha1_str)
returns YAZ version
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
WRBUF wrbuf_alloc(void)
construct WRBUF
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
#define xfree(x)
utility macro which calls xfree_f
void yaz_log_xml_errors(const char *prefix, int log_level)
Makes Libxml2 and Libxslt log errors through yaz_log.
Header for YAZ iconv interface.
#define YAZ_VERSION
YAZ version as string.
#define YAZ_VERSION_SHA1
SHA1 ID for YAZ (Git).
void bend_close(void *handle)
bend_initresult * bend_init(bend_initrequest *q)