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