~ubuntu-branches/ubuntu/wily/syslog-ng/wily-proposed

« back to all changes in this revision

Viewing changes to lib/ivykis/src/iv_fd_dev_poll.c

  • Committer: Package Import Robot
  • Author(s): Gergely Nagy, Gergely Nagy
  • Date: 2013-11-04 15:27:37 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131104152737-mqh6eqtna2xk97jq
Tags: 3.5.1-1
[ Gergely Nagy <algernon@madhouse-project.org> ]
* New upstream release.
  + Support auto-loading modules (Closes: #650814)
  + The SMTP module is available in syslog-ng-mod-smtp (Closes: #722746)
  + New modules: amqp, geoip, stomp, redis and smtp.
  + Multi-line input support (indented multiline and regexp-based)
  + Template type hinting for the MongoDB destination and $(format-json)
  + Support for unit suffixes in the configuration file
  + New filters, template functions and other miscellaneous changes
* New (team) maintainer, Laszlo Boszormenyi, Attila Szalay and myself
  added to Uploaders.
* Ship /var/lib/syslog-ng in the syslog-ng-core package, instead of
  creating it in the init script. Thanks Michael Biebl
  <biebl@debian.org> for the report & assistance. (Closes: #699942, #719910)
* Use dh-systemd for proper systemd-related maintainer scripts. Based on
  a patch by Michael Biebl <biebl@debian.org>. (Closes: #713982,
  #690067)
* Do not wait for syslog-ng to settle down during installation / update.
  This also fixes installing via debootstrap and a fake
  start-stop-daemon. (Closes: #714254)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ivykis, an event handling library
 
3
 * Copyright (C) 2002, 2003, 2009 Lennert Buytenhek
 
4
 * Dedicated to Marija Kulikova.
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU Lesser General Public License version
 
8
 * 2.1 as published by the Free Software Foundation.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU Lesser General Public License version 2.1 for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License version 2.1 along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 
18
 * Boston, MA 02110-1301, USA.
 
19
 */
 
20
 
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <fcntl.h>
 
24
#include <string.h>
 
25
#include <sys/devpoll.h>
 
26
#include "iv_private.h"
 
27
#include "iv_fd_private.h"
 
28
 
 
29
#define UPLOAD_BATCH            1024
 
30
 
 
31
static int iv_fd_avl_compare(struct iv_avl_node *_a, struct iv_avl_node *_b)
 
32
{
 
33
        struct iv_fd_ *a = iv_container_of(_a, struct iv_fd_, u.avl_node);
 
34
        struct iv_fd_ *b = iv_container_of(_b, struct iv_fd_, u.avl_node);
 
35
 
 
36
        if (a->fd < b->fd)
 
37
                return -1;
 
38
 
 
39
        if (a->fd > b->fd)
 
40
                return 1;
 
41
 
 
42
        return 0;
 
43
}
 
44
 
 
45
static int iv_fd_dev_poll_init(struct iv_state *st)
 
46
{
 
47
        int poll_fd;
 
48
 
 
49
#ifdef O_CLOEXEC
 
50
        poll_fd = open("/dev/poll", O_RDWR | O_CLOEXEC);
 
51
        if (poll_fd < 0)
 
52
                return -1;
 
53
#else
 
54
        poll_fd = open("/dev/poll", O_RDWR);
 
55
        if (poll_fd < 0)
 
56
                return -1;
 
57
 
 
58
        iv_fd_set_cloexec(poll_fd);
 
59
#endif
 
60
 
 
61
        INIT_IV_AVL_TREE(&st->u.dev_poll.fds, iv_fd_avl_compare);
 
62
        st->u.dev_poll.poll_fd = poll_fd;
 
63
        INIT_IV_LIST_HEAD(&st->u.dev_poll.notify);
 
64
 
 
65
        return 0;
 
66
}
 
67
 
 
68
static void xwrite(int fd, const void *buf, size_t count)
 
69
{
 
70
        while (count) {
 
71
                int ret;
 
72
 
 
73
                do {
 
74
                        ret = write(fd, buf, count);
 
75
                } while (ret < 0 && errno == EINTR);
 
76
 
 
77
                if (ret < 0) {
 
78
                        iv_fatal("iv_fd_dev_poll_flush_pending: got error "
 
79
                                 "%d[%s]", errno, strerror(errno));
 
80
                }
 
81
 
 
82
                buf += ret;
 
83
                count -= ret;
 
84
        }
 
85
}
 
86
 
 
87
static int bits_to_poll_mask(int bits)
 
88
{
 
89
        int mask;
 
90
 
 
91
        mask = 0;
 
92
        if (bits & MASKIN)
 
93
                mask |= POLLIN;
 
94
        if (bits & MASKOUT)
 
95
                mask |= POLLOUT;
 
96
 
 
97
        return mask;
 
98
}
 
99
 
 
100
static void iv_fd_dev_poll_flush_pending(struct iv_state *st)
 
101
{
 
102
        int poll_fd;
 
103
        struct pollfd pfd[UPLOAD_BATCH];
 
104
        int num;
 
105
 
 
106
        poll_fd = st->u.dev_poll.poll_fd;
 
107
        num = 0;
 
108
 
 
109
        while (!iv_list_empty(&st->u.dev_poll.notify)) {
 
110
                struct iv_list_head *ilh;
 
111
                struct iv_fd_ *fd;
 
112
 
 
113
                if (num > UPLOAD_BATCH - 2) {
 
114
                        xwrite(poll_fd, pfd, num * sizeof(pfd[0]));
 
115
                        num = 0;
 
116
                }
 
117
 
 
118
                ilh = st->u.dev_poll.notify.next;
 
119
                iv_list_del_init(ilh);
 
120
 
 
121
                fd = iv_list_entry(ilh, struct iv_fd_, list_notify);
 
122
 
 
123
                if (fd->registered_bands & ~fd->wanted_bands) {
 
124
                        pfd[num].fd = fd->fd;
 
125
                        pfd[num].events = POLLREMOVE;
 
126
                        num++;
 
127
                }
 
128
 
 
129
                if (fd->wanted_bands) {
 
130
                        pfd[num].fd = fd->fd;
 
131
                        pfd[num].events = bits_to_poll_mask(fd->wanted_bands);
 
132
                        num++;
 
133
                }
 
134
 
 
135
                fd->registered_bands = fd->wanted_bands;
 
136
        }
 
137
 
 
138
        if (num)
 
139
                xwrite(poll_fd, pfd, num * sizeof(pfd[0]));
 
140
}
 
141
 
 
142
static struct iv_fd_ *iv_fd_avl_find(struct iv_avl_tree *root, int fd)
 
143
{
 
144
        struct iv_avl_node *an;
 
145
 
 
146
        an = root->root;
 
147
        while (an != NULL) {
 
148
                struct iv_fd_ *p;
 
149
 
 
150
                p = iv_container_of(an, struct iv_fd_, u.avl_node);
 
151
                if (fd == p->fd)
 
152
                        return p;
 
153
 
 
154
                if (fd < p->fd)
 
155
                        an = an->left;
 
156
                else
 
157
                        an = an->right;
 
158
        }
 
159
 
 
160
        return NULL;
 
161
}
 
162
 
 
163
static void
 
164
iv_fd_dev_poll_poll(struct iv_state *st,
 
165
                    struct iv_list_head *active, struct timespec *to)
 
166
{
 
167
        struct pollfd batch[st->numfds ? : 1];
 
168
        struct dvpoll dvp;
 
169
        int ret;
 
170
        int i;
 
171
 
 
172
        iv_fd_dev_poll_flush_pending(st);
 
173
 
 
174
        dvp.dp_fds = batch;
 
175
        dvp.dp_nfds = ARRAY_SIZE(batch);
 
176
        dvp.dp_timeout = 1000 * to->tv_sec + ((to->tv_nsec + 999999) / 1000000);
 
177
 
 
178
        ret = ioctl(st->u.dev_poll.poll_fd, DP_POLL, &dvp);
 
179
        if (ret < 0) {
 
180
                if (errno == EINTR)
 
181
                        return;
 
182
 
 
183
                iv_fatal("iv_fd_dev_poll_poll: got error %d[%s]",
 
184
                         errno, strerror(errno));
 
185
        }
 
186
 
 
187
        for (i = 0; i < ret; i++) {
 
188
                struct iv_fd_ *fd;
 
189
                int revents;
 
190
 
 
191
                fd = iv_fd_avl_find(&st->u.dev_poll.fds, batch[i].fd);
 
192
                if (fd == NULL) {
 
193
                        iv_fatal("iv_fd_dev_poll_poll: got event for "
 
194
                                 "unknown fd %d", batch[i].fd);
 
195
                }
 
196
 
 
197
                revents = batch[i].revents;
 
198
 
 
199
                if (revents & (POLLIN | POLLERR | POLLHUP))
 
200
                        iv_fd_make_ready(active, fd, MASKIN);
 
201
 
 
202
                if (revents & (POLLOUT | POLLERR | POLLHUP))
 
203
                        iv_fd_make_ready(active, fd, MASKOUT);
 
204
 
 
205
                if (revents & (POLLERR | POLLHUP))
 
206
                        iv_fd_make_ready(active, fd, MASKERR);
 
207
        }
 
208
}
 
209
 
 
210
static void iv_fd_dev_poll_register_fd(struct iv_state *st, struct iv_fd_ *fd)
 
211
{
 
212
        int ret;
 
213
 
 
214
        ret = iv_avl_tree_insert(&st->u.dev_poll.fds, &fd->u.avl_node);
 
215
        if (ret) {
 
216
                iv_fatal("iv_fd_dev_poll_register_fd: got error %d[%s]",
 
217
                         ret, strerror(ret));
 
218
        }
 
219
}
 
220
 
 
221
static void iv_fd_dev_poll_unregister_fd(struct iv_state *st, struct iv_fd_ *fd)
 
222
{
 
223
        iv_avl_tree_delete(&st->u.dev_poll.fds, &fd->u.avl_node);
 
224
 
 
225
        if (!iv_list_empty(&fd->list_notify))
 
226
                iv_fd_dev_poll_flush_pending(st);
 
227
}
 
228
 
 
229
static void iv_fd_dev_poll_notify_fd(struct iv_state *st, struct iv_fd_ *fd)
 
230
{
 
231
        iv_list_del_init(&fd->list_notify);
 
232
        if (fd->registered_bands != fd->wanted_bands)
 
233
                iv_list_add_tail(&fd->list_notify, &st->u.dev_poll.notify);
 
234
}
 
235
 
 
236
static int iv_fd_dev_poll_notify_fd_sync(struct iv_state *st, struct iv_fd_ *fd)
 
237
{
 
238
        struct pollfd pfd;
 
239
        int ret;
 
240
 
 
241
        pfd.fd = fd->fd;
 
242
        pfd.events = bits_to_poll_mask(fd->wanted_bands);
 
243
 
 
244
        do {
 
245
                ret = write(st->u.dev_poll.poll_fd, &pfd, sizeof(pfd));
 
246
        } while (ret < 0 && errno == EINTR);
 
247
 
 
248
        if (ret == sizeof(pfd)) {
 
249
                fd->registered_bands = fd->wanted_bands;
 
250
                return 0;
 
251
        }
 
252
 
 
253
        return -1;
 
254
}
 
255
 
 
256
static void iv_fd_dev_poll_deinit(struct iv_state *st)
 
257
{
 
258
        close(st->u.dev_poll.poll_fd);
 
259
}
 
260
 
 
261
 
 
262
struct iv_fd_poll_method iv_fd_poll_method_dev_poll = {
 
263
        .name           = "dev_poll",
 
264
        .init           = iv_fd_dev_poll_init,
 
265
        .poll           = iv_fd_dev_poll_poll,
 
266
        .register_fd    = iv_fd_dev_poll_register_fd,
 
267
        .unregister_fd  = iv_fd_dev_poll_unregister_fd,
 
268
        .notify_fd      = iv_fd_dev_poll_notify_fd,
 
269
        .notify_fd_sync = iv_fd_dev_poll_notify_fd_sync,
 
270
        .deinit         = iv_fd_dev_poll_deinit,
 
271
};