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 11static 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 37static void fdevent_libev_free(fdevents *ev) { 38 UNUSED(ev); 39} 40 41static 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 59static 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 force_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 86static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) { 87 UNUSED(loop); 88 UNUSED(w); 89 UNUSED(revents); 90 91 ev_timer_stop(loop, w); 92} 93 94 95static int fdevent_libev_poll(fdevents *ev, int timeout_ms) { 96 union { 97 struct ev_watcher w; 98 struct ev_timer timer; 99 } timeout_watcher; 100 101 if (!timeout_ms) timeout_ms = 1; 102 103 ev_init(&timeout_watcher.w, NULL); 104 ev_set_cb(&timeout_watcher.timer, timeout_watcher_cb); 105 timeout_watcher.timer.repeat = ((ev_tstamp) timeout_ms)/1000.0; 106 force_assert(timeout_watcher.timer.repeat); 107 ev_timer_again(ev->libev_loop, &timeout_watcher.timer); 108 109 ev_loop(ev->libev_loop, EVLOOP_ONESHOT); 110 111 ev_timer_stop(ev->libev_loop, &timeout_watcher.timer); 112 113 return 0; 114} 115 116static int fdevent_libev_event_get_revent(fdevents *ev, size_t ndx) { 117 UNUSED(ev); 118 UNUSED(ndx); 119 120 return 0; 121} 122 123static int fdevent_libev_event_get_fd(fdevents *ev, size_t ndx) { 124 UNUSED(ev); 125 UNUSED(ndx); 126 127 return -1; 128} 129 130static int fdevent_libev_event_next_fdndx(fdevents *ev, int ndx) { 131 UNUSED(ev); 132 UNUSED(ndx); 133 134 return -1; 135} 136 137static int fdevent_libev_reset(fdevents *ev) { 138 UNUSED(ev); 139 140 ev_default_fork(); 141 142 return 0; 143} 144 145int fdevent_libev_init(fdevents *ev) { 146 ev->type = FDEVENT_HANDLER_LIBEV; 147#define SET(x) \ 148 ev->x = fdevent_libev_##x; 149 150 SET(free); 151 SET(poll); 152 SET(reset); 153 154 SET(event_del); 155 SET(event_set); 156 157 SET(event_next_fdndx); 158 SET(event_get_fd); 159 SET(event_get_revent); 160 161 if (NULL == (ev->libev_loop = ev_default_loop(0))) { 162 log_error_write(ev->srv, __FILE__, __LINE__, "S", 163 "ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\""); 164 165 return -1; 166 } 167 168 return 0; 169} 170 171#else 172int fdevent_libev_init(fdevents *ev) { 173 UNUSED(ev); 174 175 log_error_write(ev->srv, __FILE__, __LINE__, "S", 176 "libev not supported, try to set server.event-handler = \"poll\" or \"select\""); 177 178 return -1; 179} 180#endif 181