⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statserv.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * * NT threaded server code by *   Chas Woodfield, Fretwell Downing Informatics. * * $Id: statserv.c,v 1.98 2003/03/03 19:57:35 adam Exp $ */#include <stdio.h>#include <string.h>#ifdef WIN32#include <process.h>#include <winsock.h>#include <direct.h>#include "service.h"#else#include <unistd.h>#include <pwd.h>#endif#if YAZ_POSIX_THREADS#include <pthread.h>#elif YAZ_GNU_THREADS#include <pth.h>#endif#include <fcntl.h>#include <signal.h>#include <errno.h>#include <yaz/comstack.h>#include <yaz/tcpip.h>#include <yaz/options.h>#ifdef USE_XTIMOSI#include <yaz/xmosi.h>#endif#include <yaz/log.h>#include "eventl.h"#include "session.h"#include <yaz/statserv.h>static IOCHAN pListener = NULL;static char *me = "statserver";/* * default behavior. */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 */    "",                         /* no PDUs */    "",                         /* diagnostic output to stderr */    "tcp:@:9999",               /* default listener port */    PROTO_Z3950,                /* default application protocol */    15,                         /* idle timeout (minutes) */    1024*1024,                  /* maximum PDU size (approx.) to allow */    "default-config",           /* configuration name to pass to backend */    "",                         /* set user id */    0,                          /* bend_start handler */    0,                          /* bend_stop handler */    check_options,              /* Default routine, for checking the run-time arguments */    check_ip_tcpd,    "",    0,                          /* default value for inet deamon */    0,                          /* handle (for service, etc) */    0,                          /* bend_init handle */    0,                          /* bend_close handle */#ifdef WIN32    "Z39.50 Server",            /* NT Service Name */    "Server",                   /* NT application Name */    "",                         /* NT Service Dependencies */    "Z39.50 Server",            /* NT Service Display Name */#endif /* WIN32 */    0                           /* SOAP handlers */};static int max_sessions = 0;/* * handle incoming connect requests. * The dynamic mode is a bit tricky mostly because we want to avoid * doing all of the listening and accepting in the parent - it's * safer that way. */#ifdef WIN32typedef struct _ThreadList ThreadList;struct _ThreadList{    HANDLE hThread;    IOCHAN pIOChannel;    ThreadList *pNext;};static ThreadList *pFirstThread;static CRITICAL_SECTION Thread_CritSect;static BOOL bInitialized = FALSE;static void ThreadList_Initialize(){    /* Initialize the critical Sections */    InitializeCriticalSection(&Thread_CritSect);     /* Set the first thraed */    pFirstThread = NULL;    /* we have been initialized */    bInitialized = TRUE;}static void statserv_add(HANDLE hThread, IOCHAN pIOChannel){    /* Only one thread can go through this section at a time */    EnterCriticalSection(&Thread_CritSect);    {        /* Lets create our new object */        ThreadList *pNewThread = (ThreadList *)malloc(sizeof(ThreadList));        pNewThread->hThread = hThread;        pNewThread->pIOChannel = pIOChannel;        pNewThread->pNext = pFirstThread;        pFirstThread = pNewThread;        /* Lets let somebody else create a new object now */        LeaveCriticalSection(&Thread_CritSect);    }}void statserv_remove(IOCHAN pIOChannel){    /* Only one thread can go through this section at a time */    EnterCriticalSection(&Thread_CritSect);    {        ThreadList *pCurrentThread = pFirstThread;        ThreadList *pNextThread;        ThreadList *pPrevThread =NULL;        /* Step through alll the threads */        for (; pCurrentThread != NULL; pCurrentThread = pNextThread)        {            /* We only need to compare on the IO Channel */            if (pCurrentThread->pIOChannel == pIOChannel)            {                /* We have found the thread we want to delete */                /* First of all reset the next pointers */                if (pPrevThread == NULL)                    pFirstThread = pCurrentThread->pNext;                else                    pPrevThread->pNext = pCurrentThread->pNext;                /* All we need todo now is delete the memory */                free(pCurrentThread);                /* No need to look at any more threads */                pNextThread = NULL;            }            else            {                /* We need to look at another thread */                pNextThread = pCurrentThread->pNext;                pPrevThread = pCurrentThread;            }        }        /* Lets let somebody else remove an object now */        LeaveCriticalSection(&Thread_CritSect);    }}/* WIN32 statserv_closedown */void statserv_closedown(){    /* Shouldn't do anything if we are not initialized */    if (bInitialized)    {        int iHandles = 0;        HANDLE *pThreadHandles = NULL;        /* We need to stop threads adding and removing while we */	/* start the closedown process */        EnterCriticalSection(&Thread_CritSect);        {            /* We have exclusive access to the thread stuff now */            /* Y didn't i use a semaphore - Oh well never mind */            ThreadList *pCurrentThread = pFirstThread;            /* Before we do anything else, we need to shutdown the listener */            if (pListener != NULL)                iochan_destroy(pListener);            for (; pCurrentThread != NULL; pCurrentThread = pCurrentThread->pNext)            {                /* Just destroy the IOCHAN, that should do the trick */                iochan_destroy(pCurrentThread->pIOChannel);                closesocket(pCurrentThread->pIOChannel->fd);                /* Keep a running count of our handles */                iHandles++;            }            if (iHandles > 0)            {                HANDLE *pCurrentHandle ;                /* Allocate the thread handle array */                pThreadHandles = (HANDLE *)malloc(sizeof(HANDLE) * iHandles);                pCurrentHandle = pThreadHandles;                 for (pCurrentThread = pFirstThread;                     pCurrentThread != NULL;                     pCurrentThread = pCurrentThread->pNext, pCurrentHandle++)                {                    /* Just the handle */                    *pCurrentHandle = pCurrentThread->hThread;                }            }            /* We can now leave the critical section */            LeaveCriticalSection(&Thread_CritSect);        }        /* Now we can really do something */        if (iHandles > 0)        {            logf (LOG_LOG, "waiting for %d to die", iHandles);            /* This will now wait, until all the threads close */            WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE);            /* Free the memory we allocated for the handle array */            free(pThreadHandles);        }	if (control_block.bend_stop)	    (*control_block.bend_stop)(&control_block);        /* No longer require the critical section, since all threads are dead */        DeleteCriticalSection(&Thread_CritSect);    }}void __cdecl event_loop_thread (IOCHAN iochan){    event_loop (&iochan);}/* WIN32 listener */static void listener(IOCHAN h, int event)   {    COMSTACK line = (COMSTACK) iochan_getdata(h);    association *newas;    int res;    HANDLE newHandle;    if (event == EVENT_INPUT)    {        if ((res = cs_listen(line, 0, 0)) < 0)        {	    yaz_log(LOG_FATAL, "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 */    }    else if (event == EVENT_OUTPUT)    {    	COMSTACK new_line = cs_accept(line);    	IOCHAN new_chan;	char *a = NULL;	if (!new_line)	{	    yaz_log(LOG_FATAL, "Accept failed.");	    iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT);	    return;	}	yaz_log(LOG_DEBUG, "Accept ok");	if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,				       EVENT_INPUT)))	{	    yaz_log(LOG_FATAL, "Failed to create iochan");            iochan_destroy(h);            return;	}	yaz_log(LOG_DEBUG, "Creating association");	if (!(newas = create_association(new_chan, new_line)))	{	    yaz_log(LOG_FATAL, "Failed to create new assoc.");            iochan_destroy(h);            return;	}	newas->cs_get_mask = EVENT_INPUT;	newas->cs_put_mask = 0;	newas->cs_accept_mask = 0;	yaz_log(LOG_DEBUG, "Setting timeout %d", control_block.idle_timeout);	iochan_setdata(new_chan, newas);	iochan_settimeout(new_chan, 60);	/* Now what we need todo is create a new thread with this iochan as	   the parameter */        newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan);        if (newHandle == (HANDLE) -1)	{	    	    yaz_log(LOG_FATAL|LOG_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);        iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */    }    else    {    	yaz_log(LOG_FATAL, "Bad event on listener.");        iochan_destroy(h);        return;    }}int statserv_must_terminate(void){    return 0;}#else /* ! WIN32 */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){}void statserv_closedown(){    IOCHAN p;    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){    term_flag = 1;}static void *new_session (void *vp);static int no_sessions = 0;/* UNIX listener */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) 	{	    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");                iochan_destroy(h);                return;	    }	    else if (res == 0) /* child */	    {	    	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);		    }		}		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 */	    {		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]);		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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -