Fiddling with the variant stuff.
[yaz-moved-to-github.git] / server / eventl.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: eventl.c,v $
7  * Revision 1.18  1995-11-13 09:27:41  quinn
8  * Fiddling with the variant stuff.
9  *
10  * Revision 1.17  1995/11/07  12:37:44  quinn
11  * Added support for forcing TIMEOUT event.
12  *
13  * Revision 1.16  1995/11/01  13:54:56  quinn
14  * Minor adjustments
15  *
16  * Revision 1.15  1995/09/15  14:44:15  quinn
17  * *** empty log message ***
18  *
19  * Revision 1.14  1995/08/29  14:44:50  quinn
20  * Reset timeouts.
21  *
22  * Revision 1.13  1995/08/29  11:17:56  quinn
23  * Added code to receive close
24  *
25  * Revision 1.12  1995/08/29  10:41:18  quinn
26  * Small.
27  *
28  * Revision 1.11  1995/06/19  12:39:09  quinn
29  * Fixed bug in timeout code. Added BER dumper.
30  *
31  * Revision 1.10  1995/06/16  10:31:33  quinn
32  * Added session timeout.
33  *
34  * Revision 1.9  1995/06/05  10:53:31  quinn
35  * Added a better SCAN.
36  *
37  * Revision 1.8  1995/05/16  08:51:01  quinn
38  * License, documentation, and memory fixes
39  *
40  * Revision 1.7  1995/03/27  15:02:01  quinn
41  * Added some includes for better portability
42  *
43  * Revision 1.6  1995/03/27  08:34:21  quinn
44  * Added dynamic server functionality.
45  * Released bindings to session.c (is now redundant)
46  *
47  * Revision 1.5  1995/03/15  08:37:41  quinn
48  * Now we're pretty much set for nonblocking I/O.
49  *
50  * Revision 1.4  1995/03/14  16:59:48  quinn
51  * Bug-fixes
52  *
53  * Revision 1.3  1995/03/14  11:30:14  quinn
54  * Works better now.
55  *
56  * Revision 1.2  1995/03/14  10:27:59  quinn
57  * More work on demo server.
58  *
59  * Revision 1.1  1995/03/10  18:22:44  quinn
60  * The rudiments of an asynchronous server.
61  *
62  */
63
64 #include <stdio.h>
65 #include <assert.h>
66 #include <sys/time.h>
67 #include <sys/types.h>
68 #include <unistd.h>
69 #include <stdlib.h>
70 #include <errno.h>
71 #include <string.h>
72 #ifdef _AIX
73 #include <sys/select.h>
74 #endif
75
76 #include <eventl.h>
77
78 #include <xmalloc.h>
79
80 static IOCHAN iochans = 0;
81
82 IOCHAN iochan_getchan(void)
83 {
84     return iochans;
85 }
86
87 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
88 {
89     IOCHAN new;
90
91     if (!(new = xmalloc(sizeof(*new))))
92         return 0;
93     new->destroyed = 0;
94     new->fd = fd;
95     new->flags = flags;
96     new->fun = cb;
97     new->next = iochans;
98     new->force_event = 0;
99     new->last_event = new->max_idle = 0;
100     iochans = new;
101     return new;
102 }
103
104 int event_loop()
105 {
106     do /* loop as long as there are active associations to process */
107     {
108         IOCHAN p, nextp;
109         fd_set in, out, except;
110         int res, max;
111         static struct timeval nullto = {0, 0}, to;
112         struct timeval *timeout;
113
114         FD_ZERO(&in);
115         FD_ZERO(&out);
116         FD_ZERO(&except);
117         timeout = &to; /* hang on select */
118         to.tv_sec = 5*60;
119         to.tv_usec = 0;
120         max = 0;
121         for (p = iochans; p; p = p->next)
122         {
123             if (p->force_event)
124                 timeout = &nullto;        /* polling select */
125             if (p->flags & EVENT_INPUT)
126                 FD_SET(p->fd, &in);
127             if (p->flags & EVENT_OUTPUT)
128                 FD_SET(p->fd, &out);
129             if (p->flags & EVENT_EXCEPT)
130                 FD_SET(p->fd, &except);
131             if (p->fd > max)
132                 max = p->fd;
133         }
134         if ((res = select(max + 1, &in, &out, &except, timeout)) < 0)
135         {
136             if (errno == EINTR)
137                 continue;
138             return 1;
139         }
140         for (p = iochans; p; p = p->next)
141         {
142             int force_event = p->force_event;
143             time_t now = time(0);
144
145             p->force_event = 0;
146             if (FD_ISSET(p->fd, &in) || force_event == EVENT_INPUT)
147             {
148                 p->last_event = now;
149                 (*p->fun)(p, EVENT_INPUT);
150             }
151             if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
152                 force_event == EVENT_OUTPUT))
153             {
154                 p->last_event = now;
155                 (*p->fun)(p, EVENT_OUTPUT);
156             }
157             if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
158                 force_event == EVENT_EXCEPT))
159             {
160                 p->last_event = now;
161                 (*p->fun)(p, EVENT_EXCEPT);
162             }
163             if (!p->destroyed && (p->max_idle && now - p->last_event >
164                 p->max_idle) || force_event == EVENT_TIMEOUT)
165             {
166                 p->last_event = now;
167                 (*p->fun)(p, EVENT_TIMEOUT);
168             }
169         }
170         for (p = iochans; p; p = nextp)
171         {
172             nextp = p->next;
173
174             if (p->destroyed)
175             {
176                 IOCHAN tmp = p, pr;
177
178                 if (p == iochans)
179                     iochans = p->next;
180                 else
181                 {
182                     for (pr = iochans; pr; pr = pr->next)
183                         if (pr->next == p)
184                             break;
185                     assert(pr); /* grave error if it weren't there */
186                     pr->next = p->next;
187                 }
188                 if (nextp == p)
189                     nextp = p->next;
190                 xfree(tmp);
191             }
192         }
193     }
194     while (iochans);
195     return 0;
196 }