X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=server%2Fstatserv.c;h=3480c5d3406f0665ec8b05a461fd84dc612d3cd8;hp=f7d20254236a56d439fd8ea71528dc3c83db9bb4;hb=ac286ae76051058c8e340bf84eb98391340b7d22;hpb=7f6f1b2def7cb8f2124168f90ea3e2e728bd39b3 diff --git a/server/statserv.c b/server/statserv.c index f7d2025..3480c5d 100644 --- a/server/statserv.c +++ b/server/statserv.c @@ -1,242 +1,12 @@ /* - * Copyright (c) 1995-2000, Index Data + * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * NT server based on threads by + * NT threaded server code by * Chas Woodfield, Fretwell Downing Informatics. * - * $Log: statserv.c,v $ - * Revision 1.69 2000-12-01 17:56:41 adam - * on WIN32 function statserv_closedown closes socket(s) to provoke close. - * - * Revision 1.68 2000/11/29 14:22:47 adam - * Implemented XML/SGML attributes for data1 so that d1_read reads them - * and d1_write generates proper attributes for XML/SGML records. Added - * register locking for threaded version. - * - * Revision 1.67 2000/11/23 10:58:32 adam - * SSL comstack support. Separate POSIX thread support library. - * - * Revision 1.66 2000/10/06 12:00:28 adam - * Fixed Handle leak for WIN32. - * - * Revision 1.65 2000/09/04 08:58:15 adam - * Added prefix yaz_ for most logging utility functions. - * - * Revision 1.64 2000/04/05 07:39:55 adam - * Added shared library support (libtool). - * - * Revision 1.63 2000/03/20 19:06:25 adam - * Added Segment request for fronend server. Work on admin for client. - * - * Revision 1.62 2000/03/17 12:47:02 adam - * Minor changes to admin client. - * - * Revision 1.61 2000/03/15 12:59:49 adam - * Added handle member to statserv_control. - * - * Revision 1.60 2000/03/14 09:06:11 adam - * Added POSIX threads support for frontend server. - * - * Revision 1.59 1999/11/30 13:47:12 adam - * Improved installation. Moved header files to include/yaz. - * - * Revision 1.58 1999/08/27 09:40:32 adam - * Renamed logf function to yaz_log. Removed VC++ project files. - * - * Revision 1.57 1999/07/06 12:17:15 adam - * Added option -1 that runs server once (for profiling purposes). - * - * Revision 1.56 1999/06/10 11:45:30 adam - * Added bend_start, bend_stop handlers and removed pre_init. - * Handlers bend_start/bend_stop are called when service/daemon is - * started/stopped. - * - * Revision 1.55 1999/06/10 09:18:54 adam - * Modified so that pre_init is called when service/server is started. - * - * Revision 1.54 1999/04/16 14:45:55 adam - * Added interface for tcpd wrapper for access control. - * - * Revision 1.53 1999/02/02 13:57:39 adam - * Uses preprocessor define WIN32 instead of WINDOWS to build code - * for Microsoft WIN32. - * - * Revision 1.52 1998/08/21 14:13:34 adam - * Added GNU Configure script to build Makefiles. - * - * Revision 1.51 1998/07/07 15:51:03 adam - * Changed server so that it stops if bind fails - "address already in - * use" typically causes this. - * - * Revision 1.50 1998/06/22 11:32:39 adam - * Added 'conditional cs_listen' feature. - * - * Revision 1.49 1998/02/27 14:04:55 adam - * Fixed bug in statserv_remove. - * - * Revision 1.48 1998/02/11 11:53:36 adam - * Changed code so that it compiles as C++. - * - * Revision 1.47 1998/02/10 10:28:57 adam - * Added app_name, service_dependencies, service_display_name and - * options_func. options_func allows us to specify a different function - * to interogate the command line arguments. The other members allow us - * to pass the full service details accross to the service manager (CW). - * - * - * Revision 1.46 1998/01/30 15:24:57 adam - * Fixed bug in inetd code. The server listened on tcp:@:9999 even - * though it was started in inetd mode. - * - * Revision 1.45 1998/01/29 13:30:23 adam - * Better event handle system for NT/Unix. - * - * Revision 1.44 1997/11/07 13:31:52 adam - * Added NT Service name part of statserv_options_block. Moved NT - * service utility to server library. - * - * Revision 1.43 1997/10/31 12:20:09 adam - * Improved memory debugging for xmalloc/nmem.c. References to NMEM - * instead of ODR in n ESPEC-1 handling in source d1_espec.c. - * Bug fix: missing fclose in data1_read_espec1. - * - * Revision 1.42 1997/10/27 14:03:02 adam - * Added new member to statserver_options_block, pre_init, which - * specifies a callback to be invoked after command line parsing and - * before the server listens for the first time. - * - * Revision 1.41 1997/09/29 07:19:32 adam - * Server library uses nmem_init/nmem_exit. The log prefix no longer - * includes leading path on NT. - * - * Revision 1.40 1997/09/17 12:10:41 adam - * YAZ version 1.4. - * - * Revision 1.39 1997/09/09 10:10:19 adam - * Another MSV5.0 port. Changed projects to include proper - * library/include paths. - * Server starts server in test-mode when no options are given. - * - * Revision 1.38 1997/09/04 14:19:14 adam - * Added credits. - * - * Revision 1.37 1997/09/01 08:53:01 adam - * New windows NT/95 port using MSV5.0. The test server 'ztest' was - * moved a separate directory. MSV5.0 project server.dsp created. - * As an option, the server can now operate as an NT service. - * - * Revision 1.36 1996/07/06 19:58:36 quinn - * System headerfiles gathered in yconfig - * - * Revision 1.35 1996/05/29 10:03:28 quinn - * Options work - * - * Revision 1.34 1996/02/21 13:12:07 quinn - * *** empty log message *** - * - * Revision 1.33 1996/02/10 12:23:49 quinn - * Enable inetd operations fro TCP/IP stack - * - * Revision 1.32 1996/01/19 15:41:52 quinn - * *** empty log message *** - * - * Revision 1.31 1995/11/17 11:09:39 adam - * Added new option '-c' to specify configuration name in control block. - * - * Revision 1.30 1995/11/01 13:54:59 quinn - * Minor adjustments - * - * Revision 1.29 1995/10/30 12:41:29 quinn - * Added hostname lookup for server. - * - * Revision 1.28 1995/09/29 17:12:30 quinn - * Smallish - * - * Revision 1.27 1995/09/27 15:03:02 quinn - * Modified function heads & prototypes. - * - * Revision 1.26 1995/08/29 14:44:51 quinn - * Reset timeouts. - * - * Revision 1.25 1995/08/29 11:18:02 quinn - * Added code to receive close - * - * Revision 1.24 1995/06/16 10:31:39 quinn - * Added session timeout. - * - * Revision 1.23 1995/06/15 12:30:48 quinn - * Setuid-facility. - * - * Revision 1.22 1995/06/15 07:45:17 quinn - * Moving to v3. - * - * Revision 1.21 1995/06/06 08:15:40 quinn - * Cosmetic. - * - * Revision 1.20 1995/05/29 08:12:09 quinn - * Moved oid to util - * - * Revision 1.19 1995/05/16 09:37:27 quinn - * Fixed bug - * - * Revision 1.18 1995/05/16 08:51:09 quinn - * License, documentation, and memory fixes - * - * Revision 1.17 1995/05/15 11:56:42 quinn - * Asynchronous facilities. Restructuring of seshigh code. - * - * Revision 1.16 1995/04/10 10:23:40 quinn - * Some work to add scan and other things. - * - * Revision 1.15 1995/03/31 10:16:51 quinn - * Fixed logging. - * - * Revision 1.14 1995/03/31 09:18:58 quinn - * Added logging. - * - * Revision 1.13 1995/03/30 16:08:39 quinn - * Little mods. - * - * Revision 1.12 1995/03/30 13:29:02 quinn - * Smallish - * - * Revision 1.11 1995/03/30 12:18:17 quinn - * Fixed bug. - * - * Revision 1.10 1995/03/29 15:40:16 quinn - * Ongoing work. Statserv is now dynamic by default - * - * Revision 1.9 1995/03/27 08:34:30 quinn - * Added dynamic server functionality. - * Released bindings to session.c (is now redundant) - * - * Revision 1.8 1995/03/20 09:46:26 quinn - * Added osi support. - * - * Revision 1.7 1995/03/16 13:29:04 quinn - * Partitioned server. - * - * Revision 1.6 1995/03/15 15:18:52 quinn - * Little changes to better support nonblocking I/O - * Added backend.h - * - * Revision 1.5 1995/03/15 08:37:45 quinn - * Now we're pretty much set for nonblocking I/O. - * - * Revision 1.4 1995/03/14 16:59:48 quinn - * Bug-fixes - * - * Revision 1.3 1995/03/14 11:30:15 quinn - * Works better now. - * - * Revision 1.2 1995/03/14 10:28:03 quinn - * More work on demo server. - * - * Revision 1.1 1995/03/10 18:22:45 quinn - * The rudiments of an asynchronous server. - * + * $Id: statserv.c,v 1.92 2003-02-14 18:49:24 adam Exp $ */ #include @@ -247,12 +17,16 @@ #include #include "service.h" #else -#if HAVE_PTHREAD_H -#include -#endif #include #include #endif + +#if YAZ_POSIX_THREADS +#include +#elif YAZ_GNU_THREADS +#include +#endif + #include #include #include @@ -296,13 +70,14 @@ statserv_options_block control_block = { 0, /* default value for inet deamon */ 0, /* handle (for service, etc) */ 0, /* bend_init handle */ - 0 /* bend_close handle */ + 0, /* bend_close handle */ #ifdef WIN32 - ,"Z39.50 Server", /* NT Service Name */ + "Z39.50 Server", /* NT Service Name */ "Server", /* NT application Name */ "", /* NT Service Dependencies */ - "Z39.50 Server" /* NT Service Display Name */ + "Z39.50 Server", /* NT Service Display Name */ #endif /* WIN32 */ + 0 /* SOAP handlers */ }; /* @@ -469,7 +244,7 @@ void statserv_closedown() } } -void event_loop_thread (IOCHAN iochan) +void __cdecl event_loop_thread (IOCHAN iochan) { event_loop (&iochan); } @@ -556,9 +331,22 @@ static void listener(IOCHAN h, int event) } } +int statserv_must_terminate(void) +{ + return 0; +} + #else /* ! WIN32 */ -/* To save having an #ifdef in event_loop we need to define this empty function */ +static int term_flag = 0; +/* To save having an #ifdef in event_loop we need to + define this empty function +*/ +int statserv_must_terminate(void) +{ + return term_flag; +} + void statserv_remove(IOCHAN pIOChannel) { } @@ -569,18 +357,19 @@ void statserv_closedown() if (control_block.bend_stop) (*control_block.bend_stop)(&control_block); - for (p = pListener; p; p = p->next) + { iochan_destroy(p); + } } void sigterm(int sig) { - statserv_closedown(); - exit (0); + term_flag = 1; } static void *new_session (void *vp); +static int no_sessions = 0; /* UNIX listener */ static void listener(IOCHAN h, int event) @@ -596,6 +385,7 @@ static void listener(IOCHAN h, int event) { int res; + ++no_sessions; if (pipe(hand) < 0) { yaz_log(LOG_FATAL|LOG_ERRNO, "pipe"); @@ -626,6 +416,10 @@ static void listener(IOCHAN h, int event) } sprintf(nbuf, "%s(%d)", me, getpid()); yaz_log_init(control_block.loglevel, nbuf, 0); + /* ensure that bend_stop is not called when each child exits - + only for the main process .. + */ + control_block.bend_stop = 0; } else /* parent */ { @@ -636,7 +430,8 @@ static void listener(IOCHAN h, int event) char dummy[1]; int res; - if ((res = read(hand[0], dummy, 1)) < 0 && errno != EINTR) + if ((res = read(hand[0], dummy, 1)) < 0 && + yaz_errno() != EINTR) { yaz_log(LOG_FATAL|LOG_ERRNO, "handshake read"); return; @@ -652,7 +447,7 @@ static void listener(IOCHAN h, int event) if ((res = cs_listen_check(line, 0, 0, control_block.check_ip, control_block.daemon_name)) < 0) { - yaz_log(LOG_WARN, "cs_listen failed"); + yaz_log(LOG_WARN|LOG_ERRNO, "cs_listen failed"); return; } else if (res == 1) @@ -688,9 +483,11 @@ static void listener(IOCHAN h, int event) close(hand[1]); } else + { iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ - -#if HAVE_PTHREAD_H + ++no_sessions; + } +#if YAZ_POSIX_THREADS if (control_block.threads) { pthread_t child_thread; @@ -699,15 +496,36 @@ static void listener(IOCHAN h, int event) } else new_session(new_line); +#elif YAZ_GNU_THREADS + if (control_block.threads) + { + pth_attr_t attr; + pth_t child_thread; + + attr = pth_attr_new (); + pth_attr_set (attr, PTH_ATTR_JOINABLE, FALSE); + pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 32*1024); + pth_attr_set (attr, PTH_ATTR_NAME, "session"); + yaz_log (LOG_LOG, "pth_spawn begin"); + child_thread = pth_spawn (attr, new_session, new_line); + yaz_log (LOG_LOG, "pth_spawn finish"); + pth_attr_destroy (attr); + } + else + new_session(new_line); #else new_session(new_line); #endif } + else if (event == EVENT_TIMEOUT) + { + yaz_log(LOG_LOG, "Shutting down listener."); + iochan_destroy(h); + } else { yaz_log(LOG_FATAL, "Bad event on listener."); iochan_destroy(h); - return; } } @@ -749,8 +567,8 @@ static void *new_session (void *vp) iochan_setdata(new_chan, newas); iochan_settimeout(new_chan, control_block.idle_timeout * 60); a = cs_addrstr(new_line); - yaz_log(LOG_LOG, "Accepted connection from %s", a ? a : "[Unknown]"); - + yaz_log(LOG_LOG, "Starting session %d from %s", + no_sessions, a ? a : "[Unknown]"); if (control_block.threads) { event_loop(&new_chan); @@ -763,7 +581,8 @@ static void *new_session (void *vp) return 0; } -#endif /* WIN32 */ +/* UNIX */ +#endif static void inetd_connection(int what) { @@ -781,7 +600,9 @@ static void inetd_connection(int what) iochan_setdata(chan, assoc); iochan_settimeout(chan, control_block.idle_timeout * 60); addr = cs_addrstr(line); - yaz_log(LOG_LOG, "Inetd association from %s", addr ? addr : "[UNKNOWN]"); + yaz_log(LOG_LOG, "Inetd association from %s", + addr ? addr : "[UNKNOWN]"); + assoc->cs_get_mask = EVENT_INPUT; } else { @@ -804,81 +625,59 @@ static void inetd_connection(int what) /* * Set up a listening endpoint, and give it to the event-handler. */ -static void add_listener(char *where, int what) +static int add_listener(char *where, int what) { COMSTACK l; - CS_TYPE type; - char mode[100], addr[100]; void *ap; IOCHAN lst = NULL; + const char *mode; - if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2) - { - yaz_log (LOG_WARN, "%s: Address format: ('tcp'|'ssl')':'
", - me); - return; - } - if (!strcmp(mode, "tcp")) - type = tcpip_type; - else if (!strcmp(mode, "ssl")) - { -#if HAVE_OPENSSL_SSL_H - type = ssl_type; -#else - yaz_log (LOG_WARN, "SSL Transport not allowed by configuration."); - return; -#endif - } + if (control_block.dynamic) + mode = "dynamic"; + else if (control_block.threads) + mode = "threaded"; else + mode = "static"; + + yaz_log(LOG_LOG, "Adding %s %s listener on %s", mode, + what == PROTO_SR ? "SR" : "Z3950", where); + + l = cs_create_host(where, 0, &ap); + if (!l) { - yaz_log (LOG_WARN, "You must specify either 'ssl:' or 'tcp:'"); - return; - } - yaz_log(LOG_LOG, "Adding %s %s listener on %s", - control_block.dynamic ? "dynamic" : - (control_block.threads ? "threaded" : "static"), - what == PROTO_SR ? "SR" : "Z3950", where); - if (!(l = cs_create(type, 0, what))) - { - yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create listener"); - return; - } - ap = cs_straddr (l, addr); - if (!ap) - { - fprintf(stderr, "Address resolution failed.\n"); - cs_close (l); - return; + yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to listen on %s", where); + return -1; } if (cs_bind(l, ap, CS_SERVER) < 0) { yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where); cs_close (l); - return; + return -1; } if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT | EVENT_EXCEPT))) { yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create IOCHAN-type"); cs_close (l); - return; + return -1; } iochan_setdata(lst, l); /* Ensure our listener chain is setup properly */ lst->next = pListener; pListener = lst; + return 0; /* OK */ } #ifndef WIN32 -/* For windows we don't need to catch the signals */ +/* UNIX only (for windows we don't need to catch the signals) */ static void catchchld(int num) { while (waitpid(-1, 0, WNOHANG) > 0) ; signal(SIGCHLD, catchchld); } -#endif /* WIN32 */ +#endif statserv_options_block *statserv_getcontrol(void) { @@ -893,15 +692,42 @@ void statserv_setcontrol(statserv_options_block *block) memcpy(&control_block, block, sizeof(*block)); } +void statserv_add_soap_handler(int (*h)(struct bend_soap_rr *rr), + const char *ns) +{ + struct bend_soap_handler *sh = (struct bend_soap_handler *) + xmalloc(sizeof(*sh)); + + sh->handler = h; + sh->ns = xstrdup(ns); + sh->next = control_block.soap_handlers; + control_block.soap_handlers = sh; + yaz_log(LOG_LOG, "soap handler added"); +} + +static void statserv_reset(void) +{ + struct bend_soap_handler *sh = control_block.soap_handlers; + + control_block.soap_handlers = 0; + while (sh) + { + struct bend_soap_handler *sh_next = sh->next; + xfree (sh->ns); + xfree (sh); + sh = sh_next; + } +} + int statserv_start(int argc, char **argv) { int ret; - nmem_init (); #ifdef WIN32 /* We need to initialize the thread list */ ThreadList_Initialize(); -#endif /* WIN32 */ +/* WIN32 */ +#endif #ifdef WIN32 if ((me = strrchr (argv[0], '\\'))) @@ -917,13 +743,14 @@ int statserv_start(int argc, char **argv) if (control_block.bend_start) (*control_block.bend_start)(&control_block); #ifdef WIN32 - logf (LOG_LOG, "Starting server %s", me); + yaz_log (LOG_LOG, "Starting server %s", me); #else +/* UNIX */ if (control_block.inetd) inetd_connection(control_block.default_proto); else { - logf (LOG_LOG, "Starting server %s pid=%d", me, getpid()); + yaz_log (LOG_LOG, "Starting server %s pid=%d", me, getpid()); #if 0 sigset_t sigs_to_block; @@ -952,8 +779,10 @@ int statserv_start(int argc, char **argv) exit(1); } } -#endif /* WIN32 */ - +/* UNIX */ +#endif + + if ((pListener == NULL) && *control_block.default_listen) add_listener(control_block.default_listen, control_block.default_proto); @@ -965,7 +794,6 @@ int statserv_start(int argc, char **argv) yaz_log(LOG_LOG, "Entering event loop."); ret = event_loop(&pListener); } - nmem_exit (); return ret; } @@ -979,7 +807,8 @@ int check_options(int argc, char **argv) switch (ret) { case 0: - add_listener(arg, control_block.default_proto); + if (add_listener(arg, control_block.default_proto)) + return 1; /* failed to create listener */ break; case '1': control_block.one_shot = 1; @@ -989,13 +818,17 @@ int check_options(int argc, char **argv) control_block.default_proto = PROTO_Z3950; break; case 's': - control_block.default_proto = PROTO_SR; + fprintf (stderr, "%s: SR protocol no longer supported\n", me); + exit (1); break; case 'S': control_block.dynamic = 0; break; case 'T': -#if HAVE_PTHREAD_H +#if YAZ_POSIX_THREADS + control_block.dynamic = 0; + control_block.threads = 1; +#elif YAZ_GNU_THREADS control_block.dynamic = 0; control_block.threads = 1; #else @@ -1053,7 +886,7 @@ int check_options(int argc, char **argv) fprintf(stderr, "Usage: %s [ -a -v " " -l -u -c -t " " -k -d " - " -zsiST -w ... ]\n", me); + " -ziST1 -w ... ]\n", me); return 1; } } @@ -1093,7 +926,7 @@ int statserv_main(int argc, char **argv, /* Now setup the service with the service controller */ SetupService(argc, argv, &ArgDetails, SZAPPNAME, cb->service_name, /* internal service name */ - cb->service_name, /* displayed name of the service */ + cb->service_display_name, /* displayed name */ SZDEPENDENCIES); return 0; } @@ -1116,8 +949,11 @@ void StopAppService(void *pHandle) { /* Stops the app */ statserv_closedown(); + statserv_reset(); } +/* WIN32 */ #else +/* UNIX */ int statserv_main(int argc, char **argv, bend_initresult *(*bend_init)(bend_initrequest *r), void (*bend_close)(void *handle)) @@ -1131,6 +967,7 @@ int statserv_main(int argc, char **argv, statserv_setcontrol(cb); ret = statserv_start (argc, argv); statserv_closedown (); + statserv_reset(); return ret; } #endif