28 #include <sys/types.h>
41 #include <libxml/parser.h>
42 #include <libxml/tree.h>
43 #include <libxml/xinclude.h>
59 #include <yaz/xmosi.h>
75 static char *
me =
"statserver";
78 DWORD current_control_tls;
79 static int init_control_tls = 0;
80 #elif YAZ_POSIX_THREADS
81 static pthread_key_t current_control_tls;
82 static int init_control_tls = 0;
90 #define STAT_DEFAULT_LOG_LEVEL "server,session,request"
161 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
162 strcmp((
const char *) ptr->name,
"yazgfs"))
183 for (p = ptr; p; p = p->next)
185 if (p->type == XML_TEXT_NODE)
186 len += xmlStrlen(p->content);
191 for (p = ptr; p; p = p->next)
193 if (p->type == XML_TEXT_NODE)
203 strcat((
char *)str, (
const char *)cp);
207 cp = strlen((
const char *)str) + str;
221 memcpy(&n->
cb, &control_block,
sizeof(control_block));
270 char vhost[128], *cp;
273 strncpy(vhost, host, 127);
275 cp = strchr(vhost,
':');
284 for (gfs = gfs_server_list; gfs; gfs = gfs->
next)
286 int listen_match = 0;
288 if ( !gfs->
host || (host && gfs->
host && !strcmp(host, gfs->
host)))
293 if (listen_match && host_match)
346 for (ptr = ptr->children; ptr; ptr = ptr->next)
348 struct _xmlAttr *attr;
349 if (ptr->type != XML_ELEMENT_NODE)
351 attr = ptr->properties;
352 if (!strcmp((
const char *) ptr->name,
"listen"))
358 const char *address =
360 for ( ; attr; attr = attr->next)
361 if (!xmlStrcmp(attr->name, BAD_CAST
"id")
362 && attr->children && attr->children->type == XML_TEXT_NODE)
367 gfslp = &(*gfslp)->
next;
371 else if (!strcmp((
const char *) ptr->name,
"server"))
373 xmlNodePtr ptr_server = ptr;
375 const char *listenref = 0;
379 for ( ; attr; attr = attr->next)
380 if (!xmlStrcmp(attr->name, BAD_CAST
"listenref")
381 && attr->children && attr->children->type == XML_TEXT_NODE)
383 else if (!xmlStrcmp(attr->name, BAD_CAST
"id")
385 && attr->children->type == XML_TEXT_NODE)
396 for (id_no = 1; gl; gl = gl->
next, id_no++)
397 if (gl->
id && !strcmp(gl->
id, listenref))
404 "config element", listenref);
406 for (ptr = ptr_server->children; ptr; ptr = ptr->next)
408 if (ptr->type != XML_ELEMENT_NODE)
410 if (!strcmp((
const char *) ptr->name,
"host"))
415 else if (!strcmp((
const char *) ptr->name,
"config"))
420 else if (!strcmp((
const char *) ptr->name,
"cql2rpn"))
427 "open CQL transform file '%s'", name);
431 else if (!strcmp((
const char *) ptr->name,
"ccl2rpn"))
437 if ((f = fopen(name,
"r")) == 0) {
445 else if (!strcmp((
const char *) ptr->name,
"directory"))
450 else if (!strcmp((
const char *) ptr->name,
"docpath"))
455 else if (!strcmp((
const char *) ptr->name,
"maximumrecordsize"))
460 else if (!strcmp((
const char *) ptr->name,
"stylesheet"))
467 else if (!strcmp((
const char *) ptr->name,
"explain"))
471 else if (!strcmp((
const char *) ptr->name,
"retrievalinfo"))
488 gfsp = &(*gfsp)->
next;
503 init_control_tls = 1;
504 current_control_tls = TlsAlloc();
505 #elif YAZ_POSIX_THREADS
506 init_control_tls = 1;
507 pthread_key_create(¤t_control_tls, 0);
526 if (noSubstitutions == -1)
550 if (init_control_tls)
551 TlsFree(current_control_tls);
552 #elif YAZ_POSIX_THREADS
553 if (init_control_tls)
554 pthread_key_delete(current_control_tls);
563 for (id_no = 1; gfs; gfs = gfs->
next, id_no++)
575 for (; gfs; gfs = gfs->
next)
601 for (; gfs; gfs = gfs->
next)
615 (*control_block.
bend_stop)(&control_block);
629 typedef struct _ThreadList ThreadList;
638 static ThreadList *pFirstThread;
639 static CRITICAL_SECTION Thread_CritSect;
640 static BOOL bInitialized = FALSE;
642 static void ThreadList_Initialize()
645 InitializeCriticalSection(&Thread_CritSect);
654 static void statserv_add(HANDLE hThread,
IOCHAN pIOChannel)
657 EnterCriticalSection(&Thread_CritSect);
661 ThreadList *pNewThread = (ThreadList *)malloc(
sizeof(ThreadList));
662 pNewThread->hThread = hThread;
663 pNewThread->pIOChannel = pIOChannel;
664 pNewThread->pNext = pFirstThread;
665 pFirstThread = pNewThread;
668 LeaveCriticalSection(&Thread_CritSect);
675 EnterCriticalSection(&Thread_CritSect);
678 ThreadList *pCurrentThread = pFirstThread;
679 ThreadList *pNextThread;
680 ThreadList *pPrevThread =NULL;
683 for (; pCurrentThread != NULL; pCurrentThread = pNextThread)
686 if (pCurrentThread->pIOChannel == pIOChannel)
690 if (pPrevThread == NULL)
691 pFirstThread = pCurrentThread->pNext;
693 pPrevThread->pNext = pCurrentThread->pNext;
696 free(pCurrentThread);
704 pNextThread = pCurrentThread->pNext;
705 pPrevThread = pCurrentThread;
710 LeaveCriticalSection(&Thread_CritSect);
721 HANDLE *pThreadHandles = NULL;
725 EnterCriticalSection(&Thread_CritSect);
730 ThreadList *pCurrentThread = pFirstThread;
733 if (pListener != NULL)
736 for (; pCurrentThread != NULL; pCurrentThread = pCurrentThread->pNext)
740 closesocket(pCurrentThread->pIOChannel->fd);
748 HANDLE *pCurrentHandle ;
751 pThreadHandles = (HANDLE *)malloc(
sizeof(HANDLE) * iHandles);
752 pCurrentHandle = pThreadHandles;
754 for (pCurrentThread = pFirstThread;
755 pCurrentThread != NULL;
756 pCurrentThread = pCurrentThread->pNext, pCurrentHandle++)
759 *pCurrentHandle = pCurrentThread->hThread;
764 LeaveCriticalSection(&Thread_CritSect);
772 WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE);
775 free(pThreadHandles);
780 DeleteCriticalSection(&Thread_CritSect);
846 newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan);
847 if (newHandle == (HANDLE) -1)
855 statserv_add(newHandle, new_chan);
857 yaz_log(
YLOG_DEBUG,
"Created new thread, id = %ld iochan %p",(
long) newHandle, new_chan);
882 for (p = pListener; p; p = p->
next)
928 if ((res = fork()) < 0)
945 sprintf(nbuf,
"%s(%d)",
me, no_sessions);
960 #if YAZ_POSIX_THREADS
961 pthread_t child_thread;
962 pthread_create(&child_thread, 0,
new_session, new_line);
963 pthread_detach(child_thread);
991 unsigned cs_get_mask, cs_accept_mask,
mask =
997 cs_accept_mask =
mask;
1030 no_sessions, a ? a :
"[Unknown]", (
long) getpid());
1040 pListener = new_chan;
1067 addr ? addr :
"[UNKNOWN]");
1100 else if (control_block.
threads)
1146 for (; l; l = l->
next)
1154 while (waitpid(-1, 0, WNOHANG) > 0)
1163 if (init_control_tls)
1167 #elif YAZ_POSIX_THREADS
1168 if (init_control_tls)
1170 pthread_getspecific(current_control_tls);
1174 if (current_control_block)
1188 if (init_control_tls)
1189 TlsSetValue(current_control_tls, block);
1190 #elif YAZ_POSIX_THREADS
1191 if (init_control_tls)
1192 pthread_setspecific(current_control_tls, block);
1194 current_control_block = block;
1204 IOCHAN *pListener = data;
1213 ThreadList_Initialize();
1223 if ((
me = strrchr(argv[0], sep)))
1236 if (control_block.
inetd)
1256 if (pListener == NULL)
1272 strncpy(dst, src ? src :
"", 127);
1285 while ((ret =
options(
"1a:iszSTl:v:u:c:w:t:k:Kd:A:p:DC:f:m:r:",
1286 argv, argc, &arg)) != -2)
1302 fprintf(stderr,
"%s: SR protocol no longer supported\n",
me);
1309 #if YAZ_POSIX_THREADS
1313 fprintf(stderr,
"%s: Threaded mode not available.\n",
me);
1323 fprintf(stderr,
"%s: Specify time format for log file.\n",
me);
1348 if (!arg || !(r = atoi(arg)))
1350 fprintf(stderr,
"%s: Specify positive timeout for -t.\n",
me);
1353 control_block.
idle_timeout = strchr(arg,
's') ? r : 60 * r;
1356 if (!arg || !(r = atoi(arg)))
1358 fprintf(stderr,
"%s: Specify positive size for -k.\n",
me);
1367 control_block.
inetd = 1;
1386 fprintf(stderr,
"%s: Option -f unsupported since YAZ is compiled without Libxml2 support\n",
me);
1394 if (!arg || !(r = atoi(arg)))
1396 fprintf(stderr,
"%s: Specify positive size for -r.\n",
me);
1402 fprintf(stderr,
"Usage: %s [ -a <pdufile> -v <loglevel>"
1403 " -l <logfile> -u <user> -c <config> -t <minutes>"
1404 " -k <kilobytes> -d <daemon> -p <pidfile> -C certfile"
1405 " -zKiDST1 -m <time-format> -w <directory> <listener-addr>... ]\n",
me);
1428 cb->service_name, cb->service_display_name