*** empty log message ***
[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.10  1995-06-16 10:31:33  quinn
8  * Added session timeout.
9  *
10  * Revision 1.9  1995/06/05  10:53:31  quinn
11  * Added a better SCAN.
12  *
13  * Revision 1.8  1995/05/16  08:51:01  quinn
14  * License, documentation, and memory fixes
15  *
16  * Revision 1.7  1995/03/27  15:02:01  quinn
17  * Added some includes for better portability
18  *
19  * Revision 1.6  1995/03/27  08:34:21  quinn
20  * Added dynamic server functionality.
21  * Released bindings to session.c (is now redundant)
22  *
23  * Revision 1.5  1995/03/15  08:37:41  quinn
24  * Now we're pretty much set for nonblocking I/O.
25  *
26  * Revision 1.4  1995/03/14  16:59:48  quinn
27  * Bug-fixes
28  *
29  * Revision 1.3  1995/03/14  11:30:14  quinn
30  * Works better now.
31  *
32  * Revision 1.2  1995/03/14  10:27:59  quinn
33  * More work on demo server.
34  *
35  * Revision 1.1  1995/03/10  18:22:44  quinn
36  * The rudiments of an asynchronous server.
37  *
38  */
39
40 #include <assert.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <errno.h>
46 #include <string.h>
47 #ifdef _AIX
48 #include <sys/select.h>
49 #endif
50
51 #include <eventl.h>
52
53 #include <dmalloc.h>
54
55 static IOCHAN iochans = 0;
56
57 IOCHAN iochan_getchan(void)
58 {
59     return iochans;
60 }
61
62 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
63 {
64     IOCHAN new;
65
66     if (!(new = malloc(sizeof(*new))))
67         return 0;
68     new->destroyed = 0;
69     new->fd = fd;
70     new->flags = flags;
71     new->fun = cb;
72     new->next = iochans;
73     new->force_event = 0;
74     new->last_event = new->max_idle = 0;
75     iochans = new;
76     return new;
77 }
78
79 int event_loop()
80 {
81     do
82     {
83         IOCHAN p, nextp;
84         fd_set in, out, except;
85         int res, max;
86         static struct timeval nullto = {0, 0}, to = {60*5, 0};
87         struct timeval *timeout;
88
89         FD_ZERO(&in);
90         FD_ZERO(&out);
91         FD_ZERO(&except);
92         timeout = &to; /* hang on select */
93         max = 0;
94         for (p = iochans; p; p = p->next)
95         {
96             if (p->force_event)
97                 timeout = &nullto;
98             if (p->flags & EVENT_INPUT)
99                 FD_SET(p->fd, &in);
100             if (p->flags & EVENT_OUTPUT)
101                 FD_SET(p->fd, &out);
102             if (p->flags & EVENT_EXCEPT)
103                 FD_SET(p->fd, &except);
104             if (p->fd > max)
105                 max = p->fd;
106         }
107         if ((res = select(max + 1, &in, &out, &except, timeout)) < 0)
108         {
109             if (errno == EINTR)
110                 continue;
111             return 1;
112         }
113         for (p = iochans; p; p = p->next)
114         {
115             int force_event = p->force_event;
116             time_t now = time(0);
117
118             p->force_event = 0;
119             if (FD_ISSET(p->fd, &in) || force_event == EVENT_INPUT)
120             {
121                 p->last_event = now;
122                 (*p->fun)(p, EVENT_INPUT);
123             }
124             if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
125                 force_event == EVENT_OUTPUT))
126             {
127                 p->last_event = now;
128                 (*p->fun)(p, EVENT_OUTPUT);
129             }
130             if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
131                 force_event == EVENT_EXCEPT))
132             {
133                 p->last_event = now;
134                 (*p->fun)(p, EVENT_EXCEPT);
135             }
136             if (!p->destroyed && p->max_idle && now - p->last_event >
137                 p->max_idle)
138                 (*p->fun)(p, EVENT_TIMEOUT);
139         }
140         for (p = iochans; p; p = nextp)
141         {
142             nextp = p->next;
143
144             if (p->destroyed)
145             {
146                 IOCHAN tmp = p, pr;
147
148                 if (p == iochans)
149                     iochans = p->next;
150                 else
151                 {
152                     for (pr = iochans; pr; pr = pr->next)
153                         if (pr->next == p)
154                             break;
155                     assert(pr); /* grave error if it weren't there */
156                     pr->next = p->next;
157                 }
158                 if (nextp == p)
159                     nextp = p->next;
160                 free(tmp);
161             }
162         }
163     }
164     while (iochans);
165     return 0;
166 }