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