X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fstatserv.c;h=d183620c9f775e67f60037f536bfc8bc6c65f27a;hb=66d6c2af06d2b293f183cfead975924e9da709c6;hp=7b211a68335cd93db1bbba9decd8984cbb3d6070;hpb=7bb5e2926727e963de8411dbba9cc18df967bfbb;p=yaz-moved-to-github.git diff --git a/src/statserv.c b/src/statserv.c index 7b211a6..d183620 100644 --- a/src/statserv.c +++ b/src/statserv.c @@ -5,7 +5,12 @@ * NT threaded server code by * Chas Woodfield, Fretwell Downing Informatics. * - * $Id: statserv.c,v 1.7 2004-04-30 19:10:35 adam Exp $ + * $Id: statserv.c,v 1.16 2005-01-03 09:18:36 adam Exp $ + */ + +/** + * \file statserv.c + * \brief Implements GFS logic */ #include @@ -43,16 +48,20 @@ static IOCHAN pListener = NULL; -static char *me = "statserver"; +static char *me = "statserver"; /* log prefix */ +static char *programname="statserver"; /* full program name */ /* * default behavior. */ +#define STAT_DEFAULT_LOG_LEVEL "none,fatal,warn,log,server,session,request" +/* the 'none' clears yaz' own default settings, including [log] */ + int check_options(int argc, char **argv); statserv_options_block control_block = { 1, /* dynamic mode */ 0, /* threaded mode */ 0, /* one shot (single session) */ - LOG_DEFAULT_LEVEL, /* log level */ + YLOG_DEFAULT_LEVEL, /* log level */ "", /* no PDUs */ "", /* diagnostic output to stderr */ "tcp:@:9999", /* default listener port */ @@ -84,6 +93,22 @@ statserv_options_block control_block = { static int max_sessions = 0; +static int logbits_set=0; +static int log_session=0; +static int log_server=0; + +/** get_logbits sets global loglevel bits */ +static void get_logbits(int force) +{ /* needs to be called after parsing cmd-line args that can set loglevels!*/ + if (force || !logbits_set) + { + logbits_set=1; + log_session=yaz_log_module_level("session"); + log_server=yaz_log_module_level("server"); + } +} + + /* * handle incoming connect requests. * The dynamic mode is a bit tricky mostly because we want to avoid @@ -233,7 +258,7 @@ void statserv_closedown() /* Now we can really do something */ if (iHandles > 0) { - logf (LOG_LOG, "waiting for %d to die", iHandles); + logf (log_server, "waiting for %d to die", iHandles); /* This will now wait, until all the threads close */ WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE); @@ -265,12 +290,12 @@ static void listener(IOCHAN h, int event) { if ((res = cs_listen(line, 0, 0)) < 0) { - yaz_log(LOG_FATAL, "cs_listen failed"); + yaz_log(YLOG_FATAL, "cs_listen failed"); return; } else if (res == 1) return; - yaz_log(LOG_DEBUG, "listen ok"); + yaz_log(YLOG_DEBUG, "listen ok"); iochan_setevent(h, EVENT_OUTPUT); iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */ } @@ -282,24 +307,24 @@ static void listener(IOCHAN h, int event) if (!new_line) { - yaz_log(LOG_FATAL, "Accept failed."); + yaz_log(YLOG_FATAL, "Accept failed."); iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); return; } - yaz_log(LOG_DEBUG, "Accept ok"); + yaz_log(YLOG_DEBUG, "Accept ok"); if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, EVENT_INPUT))) { - yaz_log(LOG_FATAL, "Failed to create iochan"); + yaz_log(YLOG_FATAL, "Failed to create iochan"); iochan_destroy(h); return; } - yaz_log(LOG_DEBUG, "Creating association"); + yaz_log(YLOG_DEBUG, "Creating association"); if (!(newas = create_association(new_chan, new_line))) { - yaz_log(LOG_FATAL, "Failed to create new assoc."); + yaz_log(YLOG_FATAL, "Failed to create new assoc."); iochan_destroy(h); return; } @@ -307,7 +332,7 @@ static void listener(IOCHAN h, int event) newas->cs_put_mask = 0; newas->cs_accept_mask = 0; - yaz_log(LOG_DEBUG, "Setting timeout %d", control_block.idle_timeout); + yaz_log(YLOG_DEBUG, "Setting timeout %d", control_block.idle_timeout); iochan_setdata(new_chan, newas); iochan_settimeout(new_chan, 60); @@ -317,19 +342,19 @@ static void listener(IOCHAN h, int event) if (newHandle == (HANDLE) -1) { - yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create new thread."); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create new thread."); iochan_destroy(h); return; } /* We successfully created the thread, so add it to the list */ statserv_add(newHandle, new_chan); - yaz_log(LOG_DEBUG, "Created new thread, id = %ld iochan %p",(long) newHandle, new_chan); + yaz_log(YLOG_DEBUG, "Created new thread, id = %ld iochan %p",(long) newHandle, new_chan); iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ } else { - yaz_log(LOG_FATAL, "Bad event on listener."); + yaz_log(YLOG_FATAL, "Bad event on listener."); iochan_destroy(h); return; } @@ -379,26 +404,35 @@ static int no_sessions = 0; static void listener(IOCHAN h, int event) { COMSTACK line = (COMSTACK) iochan_getdata(h); - static int hand[2]; - static int child = 0; int res; if (event == EVENT_INPUT) { - if (control_block.dynamic && !child) + COMSTACK new_line; + if ((res = cs_listen_check(line, 0, 0, control_block.check_ip, + control_block.daemon_name)) < 0) + { + yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_listen failed"); + return; + } + else if (res == 1) + { + yaz_log(YLOG_WARN, "cs_listen incomplete"); + return; + } + new_line = cs_accept(line); + if (!new_line) + { + yaz_log(YLOG_FATAL, "Accept failed."); + iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ + return; + } + no_sessions++; + if (control_block.dynamic) { - int res; - - ++no_sessions; - if (pipe(hand) < 0) - { - yaz_log(LOG_FATAL|LOG_ERRNO, "pipe"); - iochan_destroy(h); - return; - } if ((res = fork()) < 0) { - yaz_log(LOG_FATAL|LOG_ERRNO, "fork"); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "fork"); iochan_destroy(h); return; } @@ -407,102 +441,32 @@ static void listener(IOCHAN h, int event) char nbuf[100]; IOCHAN pp; - close(hand[0]); - child = 1; for (pp = pListener; pp; pp = iochan_getnext(pp)) { - if (pp != h) - { - COMSTACK l = (COMSTACK)iochan_getdata(pp); - cs_close(l); - iochan_destroy(pp); - } + COMSTACK l = (COMSTACK)iochan_getdata(pp); + cs_close(l); + iochan_destroy(pp); } - sprintf(nbuf, "%s(%d)", me, getpid()); + sprintf(nbuf, "%s(%d)", me, no_sessions); yaz_log_init(control_block.loglevel, nbuf, 0); /* ensure that bend_stop is not called when each child exits - - only for the main process .. - */ + only for the main process .. */ control_block.bend_stop = 0; } else /* parent */ { - close(hand[1]); - /* wait for child to take the call */ - for (;;) - { - char dummy[1]; - int res; - - if ((res = read(hand[0], dummy, 1)) < 0 && - yaz_errno() != EINTR) - { - yaz_log(LOG_FATAL|LOG_ERRNO, "handshake read"); - return; - } - else if (res >= 0) - break; - } - yaz_log(LOG_DEBUG, "P: Child has taken the call"); - close(hand[0]); + cs_close(new_line); return; } } - if ((res = cs_listen_check(line, 0, 0, control_block.check_ip, - control_block.daemon_name)) < 0) - { - yaz_log(LOG_WARN|LOG_ERRNO, "cs_listen failed"); - return; - } - else if (res == 1) - return; - yaz_log(LOG_DEBUG, "listen ok"); - iochan_setevent(h, EVENT_OUTPUT); - iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */ - } - /* in dynamic mode, only the child ever comes down here */ - else if (event == EVENT_OUTPUT) - { - COMSTACK new_line = cs_accept(line); - - if (!new_line) - { - yaz_log(LOG_FATAL, "Accept failed."); - iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ - return; - } - yaz_log(LOG_DEBUG, "accept ok"); - if (control_block.dynamic) - { - IOCHAN pp; - /* close our half of the listener socket */ - for (pp = pListener; pp; pp = iochan_getnext(pp)) - { - COMSTACK l = (COMSTACK)iochan_getdata(pp); - cs_close(l); - iochan_destroy(pp); - } - /* release dad */ - yaz_log(LOG_DEBUG, "Releasing parent"); - close(hand[1]); - } - else - { - iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ - ++no_sessions; - } -#if YAZ_POSIX_THREADS if (control_block.threads) { +#if YAZ_POSIX_THREADS pthread_t child_thread; pthread_create (&child_thread, 0, new_session, new_line); pthread_detach (child_thread); - } - else new_session(new_line); #elif YAZ_GNU_THREADS - if (control_block.threads) - { pth_attr_t attr; pth_t child_thread; @@ -510,25 +474,25 @@ static void listener(IOCHAN h, int event) 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"); + yaz_log (YLOG_DEBUG, "pth_spawn begin"); child_thread = pth_spawn (attr, new_session, new_line); - yaz_log (LOG_LOG, "pth_spawn finish"); + yaz_log (YLOG_DEBUG, "pth_spawn finish"); pth_attr_destroy (attr); +#else + new_session(new_line); +#endif } else new_session(new_line); -#else - new_session(new_line); -#endif } else if (event == EVENT_TIMEOUT) { - yaz_log(LOG_LOG, "Shutting down listener."); + yaz_log(log_server, "Shutting down listener."); iochan_destroy(h); } else { - yaz_log(LOG_FATAL, "Bad event on listener."); + yaz_log(YLOG_FATAL, "Bad event on listener."); iochan_destroy(h); } } @@ -557,12 +521,12 @@ static void *new_session (void *vp) if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, mask))) { - yaz_log(LOG_FATAL, "Failed to create iochan"); + yaz_log(YLOG_FATAL, "Failed to create iochan"); return 0; } if (!(newas = create_association(new_chan, new_line))) { - yaz_log(LOG_FATAL, "Failed to create new assoc."); + yaz_log(YLOG_FATAL, "Failed to create new assoc."); return 0; } newas->cs_accept_mask = cs_accept_mask; @@ -575,9 +539,9 @@ static void *new_session (void *vp) #else a = 0; #endif - yaz_log(LOG_LOG, "Starting session %d from %s", - no_sessions, a ? a : "[Unknown]"); - if (max_sessions && no_sessions == max_sessions) + yaz_log(log_session, "Starting session %d from %s (pid=%ld)", + no_sessions, a ? a : "[Unknown]", (long) getpid()); + if (max_sessions && no_sessions >= max_sessions) control_block.one_shot = 1; if (control_block.threads) { @@ -610,25 +574,25 @@ static void inetd_connection(int what) iochan_setdata(chan, assoc); iochan_settimeout(chan, 60); addr = cs_addrstr(line); - yaz_log(LOG_LOG, "Inetd association from %s", + yaz_log(log_session, "Inetd association from %s", addr ? addr : "[UNKNOWN]"); assoc->cs_get_mask = EVENT_INPUT; } else { - yaz_log(LOG_FATAL, "Failed to create association structure"); + yaz_log(YLOG_FATAL, "Failed to create association structure"); } chan->next = pListener; pListener = chan; } else { - yaz_log(LOG_FATAL, "Failed to create iochan"); + yaz_log(YLOG_FATAL, "Failed to create iochan"); } } else { - yaz_log(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0"); + yaz_log(YLOG_ERRNO|YLOG_FATAL, "Failed to create comstack on socket 0"); } } @@ -649,28 +613,28 @@ static int add_listener(char *where, int what) else mode = "static"; - yaz_log(LOG_LOG, "Adding %s %s listener on %s", mode, + yaz_log(log_server, "Adding %s %s listener on %s", mode, what == PROTO_SR ? "SR" : "Z3950", where); l = cs_create_host(where, 2, &ap); if (!l) { - yaz_log(LOG_FATAL, "Failed to listen on %s", where); + yaz_log(YLOG_FATAL, "Failed to listen on %s", where); return -1; } if (*control_block.cert_fname) - cs_set_ssl_certf(l, control_block.cert_fname); + cs_set_ssl_certificate_file(l, control_block.cert_fname); if (cs_bind(l, ap, CS_SERVER) < 0) { - yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to bind to %s", where); cs_close (l); 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"); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create IOCHAN-type"); cs_close (l); return -1; } @@ -712,7 +676,7 @@ static void statserv_reset(void) int statserv_start(int argc, char **argv) { int ret = 0; - + char sep; #ifdef WIN32 /* We need to initialize the thread list */ ThreadList_Initialize(); @@ -720,20 +684,23 @@ int statserv_start(int argc, char **argv) #endif #ifdef WIN32 - if ((me = strrchr (argv[0], '\\'))) - me++; - else - me = argv[0]; + sep='\\'; #else - me = argv[0]; + sep='/'; #endif + if ((me = strrchr (argv[0], sep))) + me++; /* get the basename */ + else + me = argv[0]; + programname=argv[0]; + if (control_block.options_func(argc, argv)) return(1); if (control_block.bend_start) (*control_block.bend_start)(&control_block); #ifdef WIN32 - yaz_log (LOG_LOG, "Starting server %s", me); + yaz_log (log_server, "Starting server %s", me); if (!pListener && *control_block.default_listen) add_listener(control_block.default_listen, control_block.default_proto); @@ -746,25 +713,48 @@ int statserv_start(int argc, char **argv) inetd_connection(control_block.default_proto); else { + static int hand[2]; if (control_block.background) { + /* create pipe so that parent waits until child has created + PID (or failed) */ + if (pipe(hand) < 0) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe"); + return 1; + } switch (fork()) { case 0: break; case -1: return 1; - default: - _exit(0); + default: + close(hand[1]); + while(1) + { + char dummy[1]; + int res = read(hand[0], dummy, 1); + if (res < 0 && yaz_errno() != EINTR) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "read fork handshake"); + break; + } + else if (res >= 0) + break; + } + close(hand[0]); + _exit(0); } - + /* child */ + close(hand[0]); if (setsid() < 0) return 1; close(0); close(1); close(2); - open("/dev/null",O_RDWR); + open("/dev/null", O_RDWR); dup(0); dup(0); } if (!pListener && *control_block.default_listen) @@ -779,7 +769,7 @@ int statserv_start(int argc, char **argv) FILE *f = fopen(control_block.pid_fname, "w"); if (!f) { - yaz_log(LOG_FATAL|LOG_ERRNO, "Couldn't create %s", + yaz_log(YLOG_FATAL|YLOG_ERRNO, "Couldn't create %s", control_block.pid_fname); exit(0); } @@ -787,7 +777,12 @@ int statserv_start(int argc, char **argv) fclose(f); } - yaz_log (LOG_LOG, "Starting server %s pid=%d", me, getpid()); + if (control_block.background) + close(hand[1]); + + yaz_log (log_server, "Starting server %s pid=%ld", programname, + (long) getpid()); + #if 0 sigset_t sigs_to_block; @@ -807,12 +802,12 @@ int statserv_start(int argc, char **argv) if (!(pw = getpwnam(control_block.setuid))) { - yaz_log(LOG_FATAL, "%s: Unknown user", control_block.setuid); + yaz_log(YLOG_FATAL, "%s: Unknown user", control_block.setuid); return(1); } if (setuid(pw->pw_uid) < 0) { - yaz_log(LOG_FATAL|LOG_ERRNO, "setuid"); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid"); exit(1); } } @@ -826,7 +821,7 @@ int statserv_start(int argc, char **argv) ret = 1; else { - yaz_log(LOG_LOG, "Entering event loop."); + yaz_log(YLOG_DEBUG, "Entering event loop."); ret = event_loop(&pListener); } return ret; @@ -837,6 +832,10 @@ int check_options(int argc, char **argv) int ret = 0, r; char *arg; + /* set default log level */ + control_block.loglevel = yaz_log_mask_str(STAT_DEFAULT_LOG_LEVEL); + yaz_log_init_level(control_block.loglevel); + while ((ret = options("1a:iszSTl:v:u:c:w:t:k:d:A:p:DC:", argv, argc, &arg)) != -2) { @@ -877,7 +876,7 @@ int check_options(int argc, char **argv) yaz_log_init(control_block.loglevel, me, control_block.logfile); break; case 'v': - control_block.loglevel = yaz_log_mask_str(arg); + control_block.loglevel = yaz_log_mask_str_x(arg,control_block.loglevel); yaz_log_init(control_block.loglevel, me, control_block.logfile); break; case 'a': @@ -927,7 +926,7 @@ int check_options(int argc, char **argv) case 'p': if (strlen(arg) >= sizeof(control_block.pid_fname)) { - yaz_log(LOG_FATAL, "pid fname too long"); + yaz_log(YLOG_FATAL, "pid fname too long"); exit(1); } strcpy(control_block.pid_fname, arg); @@ -943,6 +942,7 @@ int check_options(int argc, char **argv) return 1; } } + get_logbits(1); return 0; }