1 #include "fdevent.h"
2 #include "buffer.h"
3 #include "log.h"
4
5 #include <assert.h>
6
7 #ifdef USE_LIBEV
8
9 # include <ev.h>
10
io_watcher_cb(struct ev_loop * loop,ev_io * w,int revents)11 static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) {
12 fdevents *ev = w->data;
13 fdnode *fdn = ev->fdarray[w->fd];
14 int r = 0;
15 UNUSED(loop);
16
17 if (revents & EV_READ) r |= FDEVENT_IN;
18 if (revents & EV_WRITE) r |= FDEVENT_OUT;
19 if (revents & EV_ERROR) r |= FDEVENT_ERR;
20
21 switch (r = (*fdn->handler)(ev->srv, fdn->ctx, r)) {
22 case HANDLER_FINISHED:
23 case HANDLER_GO_ON:
24 case HANDLER_WAIT_FOR_EVENT:
25 case HANDLER_WAIT_FOR_FD:
26 break;
27 case HANDLER_ERROR:
28 /* should never happen */
29 SEGFAULT();
30 break;
31 default:
32 log_error_write(ev->srv, __FILE__, __LINE__, "d", r);
33 break;
34 }
35 }
36
fdevent_libev_free(fdevents * ev)37 static void fdevent_libev_free(fdevents *ev) {
38 UNUSED(ev);
39 }
40
fdevent_libev_event_del(fdevents * ev,int fde_ndx,int fd)41 static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) {
42 fdnode *fdn;
43 ev_io *watcher;
44
45 if (-1 == fde_ndx) return -1;
46
47 fdn = ev->fdarray[fd];
48 watcher = fdn->handler_ctx;
49
50 if (!watcher) return -1;
51
52 ev_io_stop(ev->libev_loop, watcher);
53 free(watcher);
54 fdn->handler_ctx = NULL;
55
56 return -1;
57 }
58
fdevent_libev_event_set(fdevents * ev,int fde_ndx,int fd,int events)59 static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
60 fdnode *fdn = ev->fdarray[fd];
61 ev_io *watcher = fdn->handler_ctx;
62 int ev_events = 0;
63 UNUSED(fde_ndx);
64
65 if (events & FDEVENT_IN) ev_events |= EV_READ;
66 if (events & FDEVENT_OUT) ev_events |= EV_WRITE;
67
68 if (!watcher) {
69 fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io));
70 assert(watcher);
71
72 ev_io_init(watcher, io_watcher_cb, fd, ev_events);
73 watcher->data = ev;
74 ev_io_start(ev->libev_loop, watcher);
75 } else {
76 if ((watcher->events & (EV_READ | EV_WRITE)) != ev_events) {
77 ev_io_stop(ev->libev_loop, watcher);
78 ev_io_set(watcher, watcher->fd, ev_events);
79 ev_io_start(ev->libev_loop, watcher);
80 }
81 }
82
83 return fd;
84 }
85
timeout_watcher_cb(struct ev_loop * loop,ev_timer * w,int revents)86 static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) {
87 UNUSED(loop);
88 UNUSED(w);
89 UNUSED(revents);
90 }
91
92
fdevent_libev_poll(fdevents * ev,int timeout_ms)93 static int fdevent_libev_poll(fdevents *ev, int timeout_ms) {
94 ev_timer timeout_watcher;
95
96 ev_init(&timeout_watcher, timeout_watcher_cb);
97 ev_timer_set(&timeout_watcher, ((ev_tstamp) timeout_ms)/1000.0, 0.0);
98 ev_timer_start(ev->libev_loop, &timeout_watcher);
99
100 ev_loop(ev->libev_loop, EVLOOP_ONESHOT);
101
102 ev_timer_stop(ev->libev_loop, &timeout_watcher);
103
104 return 0;
105 }
106
fdevent_libev_event_get_revent(fdevents * ev,size_t ndx)107 static int fdevent_libev_event_get_revent(fdevents *ev, size_t ndx) {
108 UNUSED(ev);
109 UNUSED(ndx);
110
111 return 0;
112 }
113
fdevent_libev_event_get_fd(fdevents * ev,size_t ndx)114 static int fdevent_libev_event_get_fd(fdevents *ev, size_t ndx) {
115 UNUSED(ev);
116 UNUSED(ndx);
117
118 return -1;
119 }
120
fdevent_libev_event_next_fdndx(fdevents * ev,int ndx)121 static int fdevent_libev_event_next_fdndx(fdevents *ev, int ndx) {
122 UNUSED(ev);
123 UNUSED(ndx);
124
125 return -1;
126 }
127
fdevent_libev_reset(fdevents * ev)128 static int fdevent_libev_reset(fdevents *ev) {
129 UNUSED(ev);
130
131 ev_default_fork();
132
133 return 0;
134 }
135
fdevent_libev_init(fdevents * ev)136 int fdevent_libev_init(fdevents *ev) {
137 ev->type = FDEVENT_HANDLER_LIBEV;
138 #define SET(x) \
139 ev->x = fdevent_libev_##x;
140
141 SET(free);
142 SET(poll);
143 SET(reset);
144
145 SET(event_del);
146 SET(event_set);
147
148 SET(event_next_fdndx);
149 SET(event_get_fd);
150 SET(event_get_revent);
151
152 if (NULL == (ev->libev_loop = ev_default_loop(0))) {
153 log_error_write(ev->srv, __FILE__, __LINE__, "S",
154 "ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\"");
155
156 return -1;
157 }
158
159 return 0;
160 }
161
162 #else
fdevent_libev_init(fdevents * ev)163 int fdevent_libev_init(fdevents *ev) {
164 UNUSED(ev);
165
166 log_error_write(ev->srv, __FILE__, __LINE__, "S",
167 "libev not supported, try to set server.event-handler = \"poll\" or \"select\"");
168
169 return -1;
170 }
171 #endif
172