ZOOM: generate event Connect rather than None
[yaz-moved-to-github.git] / src / poll.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file
7  * \brief Select, poll wrapper
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <assert.h>
14 #include <string.h>
15 #include <errno.h>
16
17 #include <yaz/log.h>
18 #include <yaz/xmalloc.h>
19 #include <yaz/poll.h>
20
21 #if HAVE_SYS_TYPES_H
22 #include <sys/types.h>
23 #endif
24 #if HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27 #if HAVE_SYS_POLL_H
28 #include <sys/poll.h>
29 #endif
30 #if HAVE_SYS_SELECT_H
31 #include <sys/select.h>
32 #endif
33 #ifdef WIN32
34 #if FD_SETSIZE < 512
35 #define FD_SETSIZE 512
36 #endif
37 #include <winsock.h>
38 #endif
39
40 /*
41   Note that yaz_poll_select is limited as to how many file
42   descriptors it can multiplex due to its use of select() which in
43   turn uses the statically defined fd_set type to be a bitmap of the
44   file descriptors to check.  On Ubuntu 6.06 (and almost certainly on
45   Debian, and probably on all Linuxes, and maybe all Unixes) this is
46   by default set to 1024 (though it may be possible to override this
47   using a #define before including <sys/select.h> -- I've not tried
48   this).  1024 file descriptors is a lot, but not enough in all
49   cases, e.g. when running IRSpy on a large target database.  So you
50   should ensure that YAZ uses ZOOM_yaz_poll_poll() when possible.
51 */
52 int yaz_poll_select(struct yaz_poll_fd *fds, int num_fds, int sec, int nsec)
53 {
54     struct timeval tv;
55     fd_set input, output, except;
56     int i, r;
57     int max_fd = 0;
58
59     FD_ZERO(&input);
60     FD_ZERO(&output);
61     FD_ZERO(&except);
62
63     assert(num_fds >= 0);
64     for (i = 0; i < num_fds; i++)
65     {
66         enum yaz_poll_mask mask = fds[i].input_mask;
67         int fd = fds[i].fd;
68
69         /* Timeout events */
70         if (fd < 0)
71             continue;
72
73         if (mask & yaz_poll_read)
74             FD_SET(fd, &input);
75         if (mask & yaz_poll_write)
76             FD_SET(fd, &output);
77         if (mask & yaz_poll_except)
78             FD_SET(fd, &except);
79         if (max_fd < fd)
80             max_fd = fd;
81     }
82     tv.tv_sec = sec;
83     tv.tv_usec = nsec / 1000;
84
85     r = select(max_fd+1, &input, &output, &except, (sec == -1 ? 0 : &tv));
86     if (r >= 0)
87     {
88         for (i = 0; i < num_fds; i++)
89         {
90             enum yaz_poll_mask mask = yaz_poll_none;
91             int fd = fds[i].fd;
92             if (!r)
93                 yaz_poll_add(mask, yaz_poll_timeout);
94             else if (fd >= 0) {
95                 if (FD_ISSET(fd, &input))
96                     yaz_poll_add(mask, yaz_poll_read);
97                 if (FD_ISSET(fd, &output))
98                     yaz_poll_add(mask, yaz_poll_write);
99                 if (FD_ISSET(fd, &except))
100                     yaz_poll_add(mask, yaz_poll_except);
101             }
102             fds[i].output_mask = mask;
103         }
104     }
105     return r;
106 }
107
108 #if HAVE_SYS_POLL_H
109 int yaz_poll_poll(struct yaz_poll_fd *fds, int num_fds, int sec, int nsec)
110 {
111     int i, r;
112     struct pollfd *pollfds = 0;
113
114     if (num_fds > 0)
115         pollfds = (struct pollfd *) xmalloc(num_fds * sizeof *pollfds);
116
117     assert(num_fds >= 0);
118     for (i = 0; i < num_fds; i++)
119     {
120         enum yaz_poll_mask mask = fds[i].input_mask;
121         int fd = fds[i].fd;
122         short poll_events = 0;
123
124         if (mask & yaz_poll_read)
125             poll_events += POLLIN;
126         if (mask & yaz_poll_write)
127             poll_events += POLLOUT;
128         if (mask & yaz_poll_except)
129             poll_events += POLLERR;
130         pollfds[i].fd = fd;
131         pollfds[i].events = poll_events;
132         pollfds[i].revents = 0;
133     }
134     r = poll(pollfds, num_fds, sec == -1 ? -1 : sec*1000 + nsec/1000000);
135     if (r >= 0)
136     {
137         for (i = 0; i < num_fds; i++)
138         {
139             enum yaz_poll_mask mask = yaz_poll_none;
140             if (!r)
141                 yaz_poll_add(mask, yaz_poll_timeout);
142             else
143             {
144                 if (pollfds[i].revents & POLLIN)
145                     yaz_poll_add(mask, yaz_poll_read);
146                 if (pollfds[i].revents & POLLOUT)
147                     yaz_poll_add(mask, yaz_poll_write);
148                 if (pollfds[i].revents & ~(POLLIN | POLLOUT))
149                 {
150                     yaz_poll_add(mask, yaz_poll_except);
151                 }
152             }
153             fds[i].output_mask = mask;
154         }
155     }
156     xfree(pollfds);
157     return r;
158 }
159 #endif
160
161 int yaz_poll(struct yaz_poll_fd *fds, int num_fds, int sec, int nsec)
162 {
163 #if HAVE_SYS_POLL_H
164     return yaz_poll_poll(fds, num_fds, sec, nsec);
165 #else
166     return yaz_poll_select(fds, num_fds, sec, nsec);
167 #endif
168 }
169
170 /*
171  * Local variables:
172  * c-basic-offset: 4
173  * c-file-style: "Stroustrup"
174  * indent-tabs-mode: nil
175  * End:
176  * vim: shiftwidth=4 tabstop=8 expandtab
177  */
178