2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: eventl.c,v 1.2 2004-10-15 00:19:00 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).
27 #include <yaz/yconfig.h>
29 #include <yaz/comstack.h>
30 #include <yaz/xmalloc.h>
33 #include <yaz/statserv.h>
37 #define YAZ_EV_SELECT pth_select
41 #define YAZ_EV_SELECT select
44 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
48 if (!(new_iochan = (IOCHAN)xmalloc(sizeof(*new_iochan))))
50 new_iochan->destroyed = 0;
52 new_iochan->flags = flags;
54 new_iochan->force_event = 0;
55 new_iochan->last_event = new_iochan->max_idle = 0;
56 new_iochan->next = NULL;
60 int event_loop(IOCHAN *iochans)
62 do /* loop as long as there are active associations to process */
65 fd_set in, out, except;
67 static struct timeval to;
70 if (statserv_must_terminate())
72 for (p = *iochans; p; p = p->next)
73 p->force_event = EVENT_TIMEOUT;
81 for (p = *iochans; p; p = p->next)
84 yaz_log(LOG_DEBUG, "fd=%d flags=%d force_event=%d",
85 p->fd, p->flags, p->force_event);
87 to.tv_sec = 0; /* polling select */
88 if (p->flags & EVENT_INPUT)
90 if (p->flags & EVENT_OUTPUT)
92 if (p->flags & EVENT_EXCEPT)
93 FD_SET(p->fd, &except);
96 if (p->max_idle && p->last_event)
98 ftime = p->last_event + p->max_idle;
107 yaz_log(LOG_DEBUG, "select start %ld", (long) to.tv_sec);
108 res = YAZ_EV_SELECT(max + 1, &in, &out, &except, &to);
109 yaz_log(LOG_DEBUG, "select end");
112 if (yaz_errno() == EINTR)
114 if (statserv_must_terminate())
116 for (p = *iochans; p; p = p->next)
117 p->force_event = EVENT_TIMEOUT;
123 /* Destroy the first member in the chain, and try again */
124 association *assoc = (association *)iochan_getdata(*iochans);
125 COMSTACK conn = assoc->client_link;
128 destroy_association(assoc);
129 iochan_destroy(*iochans);
130 yaz_log(LOG_DEBUG, "error select, destroying iochan %p",
135 for (p = *iochans; p; p = p->next)
137 int force_event = p->force_event;
140 if (!p->destroyed && (FD_ISSET(p->fd, &in) ||
141 force_event == EVENT_INPUT))
144 (*p->fun)(p, EVENT_INPUT);
146 if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
147 force_event == EVENT_OUTPUT))
150 (*p->fun)(p, EVENT_OUTPUT);
152 if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
153 force_event == EVENT_EXCEPT))
156 (*p->fun)(p, EVENT_EXCEPT);
158 if (!p->destroyed && ((p->max_idle && now - p->last_event >=
159 p->max_idle) || force_event == EVENT_TIMEOUT))
162 (*p->fun)(p, EVENT_TIMEOUT);
165 for (p = *iochans; p; p = nextp)
173 /* We need to inform the threadlist that this channel has been destroyed */
176 /* Now reset the pointers */
181 for (pr = *iochans; pr; pr = pr->next)
184 assert(pr); /* grave error if it weren't there */