Moved HTTP channel address from struct iochan to struct http_channel.
[pazpar2-moved-to-github.git] / src / eventl.c
1 /*
2  * ParaZ - a simple tool for harvesting performance data for parallel
3  * operations using Z39.50.
4  * Copyright (c) 2000-2004 Index Data ApS
5  * See LICENSE file for details.
6  */
7
8 /*
9  * $Id: eventl.c,v 1.4 2007-04-08 23:04:20 adam Exp $
10  * Based on revision YAZ' server/eventl.c 1.29.
11  */
12
13 #include <stdio.h>
14 #include <assert.h>
15
16 #if HAVE_CONFIG_H
17 #include <cconfig.h>
18 #endif
19
20 #ifdef WIN32
21 #include <winsock.h>
22 #else
23 #include <unistd.h>
24 #endif
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28
29 #include <yaz/yconfig.h>
30 #include <yaz/log.h>
31 #include <yaz/comstack.h>
32 #include <yaz/xmalloc.h>
33 #include "eventl.h"
34 #include <yaz/statserv.h>
35
36 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
37 {
38     IOCHAN new_iochan;
39
40     if (!(new_iochan = (IOCHAN)xmalloc(sizeof(*new_iochan))))
41         return 0;
42     new_iochan->destroyed = 0;
43     new_iochan->fd = fd;
44     new_iochan->flags = flags;
45     new_iochan->fun = cb;
46     new_iochan->force_event = 0;
47     new_iochan->last_event = new_iochan->max_idle = 0;
48     new_iochan->next = NULL;
49     return new_iochan;
50 }
51
52 int event_loop(IOCHAN *iochans)
53 {
54     do /* loop as long as there are active associations to process */
55     {
56         IOCHAN p, nextp;
57         fd_set in, out, except;
58         int res, max;
59         static struct timeval nullto = {0, 0}, to;
60         struct timeval *timeout;
61
62         FD_ZERO(&in);
63         FD_ZERO(&out);
64         FD_ZERO(&except);
65         timeout = &to; /* hang on select */
66         to.tv_sec = 30;
67         to.tv_usec = 0;
68         max = 0;
69         for (p = *iochans; p; p = p->next)
70         {
71             if (p->fd < 0)
72                 continue;
73             if (p->force_event)
74                 timeout = &nullto;        /* polling select */
75             if (p->flags & EVENT_INPUT)
76                 FD_SET(p->fd, &in);
77             if (p->flags & EVENT_OUTPUT)
78                 FD_SET(p->fd, &out);
79             if (p->flags & EVENT_EXCEPT)
80                 FD_SET(p->fd, &except);
81             if (p->fd > max)
82                 max = p->fd;
83         }
84         if ((res = select(max + 1, &in, &out, &except, timeout)) < 0)
85         {
86             if (errno == EINTR)
87                 continue;
88             else
89                 abort();
90         }
91         for (p = *iochans; p; p = p->next)
92         {
93             int force_event = p->force_event;
94             time_t now = time(0);
95
96             p->force_event = 0;
97             if (!p->destroyed && ((p->max_idle && now - p->last_event >
98                 p->max_idle) || force_event == EVENT_TIMEOUT))
99             {
100                 p->last_event = now;
101                 (*p->fun)(p, EVENT_TIMEOUT);
102             }
103             if (p->fd < 0)
104                 continue;
105             if (!p->destroyed && (FD_ISSET(p->fd, &in) ||
106                 force_event == EVENT_INPUT))
107             {
108                 p->last_event = now;
109                 (*p->fun)(p, EVENT_INPUT);
110             }
111             if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
112                 force_event == EVENT_OUTPUT))
113             {
114                 p->last_event = now;
115                 (*p->fun)(p, EVENT_OUTPUT);
116             }
117             if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
118                 force_event == EVENT_EXCEPT))
119             {
120                 p->last_event = now;
121                 (*p->fun)(p, EVENT_EXCEPT);
122             }
123         }
124         for (p = *iochans; p; p = nextp)
125         {
126             nextp = p->next;
127
128             if (p->destroyed)
129             {
130                 IOCHAN tmp = p, pr;
131
132                 /* Now reset the pointers */
133                 if (p == *iochans)
134                     *iochans = p->next;
135                 else
136                 {
137                     for (pr = *iochans; pr; pr = pr->next)
138                         if (pr->next == p)
139                             break;
140                     assert(pr); /* grave error if it weren't there */
141                     pr->next = p->next;
142                 }
143                 if (nextp == p)
144                     nextp = p->next;
145                 xfree(tmp);
146             }
147         }
148     }
149     while (*iochans);
150     return 0;
151 }
152
153 /*
154  * Local variables:
155  * c-basic-offset: 4
156  * indent-tabs-mode: nil
157  * End:
158  * vim: shiftwidth=4 tabstop=8 expandtab
159  */