2 * Copyright (C) 1995-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: eventl.c,v 1.13 2007-11-09 18:49:19 adam Exp $
10 * \brief Implements event loop handling for GFS.
12 * This source implements the main event loop for the Generic Frontend
13 * Server. It uses select(2).
23 #include <sys/types.h>
32 #include <yaz/comstack.h>
33 #include <yaz/xmalloc.h>
36 #include <yaz/statserv.h>
38 static int log_level=0;
39 static int log_level_initialized=0;
41 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags, int chan_id)
45 if (!log_level_initialized)
47 log_level=yaz_log_module_level("eventl");
48 log_level_initialized=1;
51 if (!(new_iochan = (IOCHAN)xmalloc(sizeof(*new_iochan))))
53 new_iochan->destroyed = 0;
55 new_iochan->flags = flags;
57 new_iochan->force_event = 0;
58 new_iochan->last_event = new_iochan->max_idle = 0;
59 new_iochan->next = NULL;
60 new_iochan->chan_id = chan_id;
65 int iochan_is_alive(IOCHAN chan)
67 static struct timeval to;
68 fd_set in, out, except;
78 FD_SET(chan->fd, &in);
82 res = YAZ_EV_SELECT(max + 1, &in, 0, 0, &to);
85 if (!ir_read(chan, EVENT_INPUT))
90 int event_loop(IOCHAN *iochans)
92 do /* loop as long as there are active associations to process */
98 struct yaz_poll_fd *fds = 0;
100 time_t now = time(0);
102 if (statserv_must_terminate())
104 for (p = *iochans; p; p = p->next)
105 p->force_event = EVENT_TIMEOUT;
107 for (p = *iochans; p; p = p->next)
109 fds = xmalloc(no_fds * sizeof(*fds));
110 for (i = 0, p = *iochans; p; p = p->next, i++)
113 enum yaz_poll_mask input_mask = 0;
114 yaz_log(log_level, "fd=%d flags=%d force_event=%d",
115 p->fd, p->flags, p->force_event);
117 tv_sec = 0; /* polling select */
118 if (p->flags & EVENT_INPUT)
119 input_mask += yaz_poll_read;
120 if (p->flags & EVENT_OUTPUT)
121 input_mask += yaz_poll_write;
122 if (p->flags & EVENT_EXCEPT)
123 input_mask += yaz_poll_except;
124 if (p->max_idle && p->last_event)
126 ftime = p->last_event + p->max_idle;
135 fds[i].input_mask = input_mask;
137 res = yaz_poll(fds, no_fds, tv_sec);
140 if (yaz_errno() == EINTR)
142 if (statserv_must_terminate())
144 for (p = *iochans; p; p = p->next)
145 p->force_event = EVENT_TIMEOUT;
152 /* Destroy the first member in the chain, and try again */
153 association *assoc = (association *)iochan_getdata(*iochans);
154 COMSTACK conn = assoc->client_link;
157 destroy_association(assoc);
158 iochan_destroy(*iochans);
159 yaz_log(log_level, "error select, destroying iochan %p",
164 for (i = 0, p = *iochans; p; p = p->next, i++)
166 int force_event = p->force_event;
167 enum yaz_poll_mask output_mask = fds[i].output_mask;
170 if (!p->destroyed && ((output_mask & yaz_poll_read) ||
171 force_event == EVENT_INPUT))
174 (*p->fun)(p, EVENT_INPUT);
176 if (!p->destroyed && ((output_mask & yaz_poll_write) ||
177 force_event == EVENT_OUTPUT))
180 (*p->fun)(p, EVENT_OUTPUT);
182 if (!p->destroyed && ((output_mask & yaz_poll_except) ||
183 force_event == EVENT_EXCEPT))
186 (*p->fun)(p, EVENT_EXCEPT);
188 if (!p->destroyed && ((p->max_idle && now - p->last_event >=
189 p->max_idle) || force_event == EVENT_TIMEOUT))
192 (*p->fun)(p, EVENT_TIMEOUT);
196 for (p = *iochans; p; p = nextp)
204 /* We need to inform the threadlist that this channel has been destroyed */
207 /* Now reset the pointers */
212 for (pr = *iochans; pr; pr = pr->next)
215 assert(pr); /* grave error if it weren't there */
230 * indent-tabs-mode: nil
232 * vim: shiftwidth=4 tabstop=8 expandtab