65 struct timespec timeout; |
65 struct timespec timeout; |
66 timeout.tv_nsec = 0; |
66 timeout.tv_nsec = 0; |
67 timeout.tv_sec = 600; |
67 timeout.tv_sec = 600; |
68 |
68 |
69 struct kevent events[64]; |
69 struct kevent events[64]; |
70 struct kevent changes[64]; |
70 struct kevent changes[128]; |
71 int numchanges = 0; |
71 int numchanges = 0; |
72 |
72 |
73 for(;;) { |
73 for(;;) { |
74 // wait for events |
74 // wait for events |
75 int nev = kevent(ev->kqueue, changes, numchanges, events, 64, &timeout); |
75 int nev = kevent(ev->kqueue, changes, numchanges, events, 64, &timeout); |
76 if(nev == -1) { |
76 if(nev == -1) { |
77 // TODO: check for error |
77 log_ereport(LOG_FAILURE, "kevent: %s", strerror(errno)); |
78 perror("kevent"); |
|
79 continue; |
78 continue; |
80 } |
79 } |
81 |
80 |
82 numchanges = 0; |
81 numchanges = 0; |
83 for(int i=0;i<nev;i++) { |
82 for(int i=0;i<nev;i++) { |
84 Event *event = (Event*)events[i].udata; |
83 Event *event = (Event*)events[i].udata; |
|
84 if(!event) { |
|
85 if(events[i].flags == 0) { |
|
86 log_ereport(LOG_WARN, "Unknown kevent (ident=%d)", (int)events[i].ident); |
|
87 } |
|
88 // don't warn in case flags is not 0, because socket EOF events |
|
89 // are triggered even if we apply EV_DELETE in the changelist |
|
90 // the only way to stop this is to apply the changelist without |
|
91 // getting new events, but that comes with a performance penalty |
|
92 |
|
93 continue; |
|
94 } |
|
95 int event_events = event->events; |
|
96 |
85 if(event->fn) { |
97 if(event->fn) { |
86 int ep = event->events; |
98 int saved_ev = event->events; |
87 if(event->fn(ev, event)) { |
99 if(!event->fn(ev, event)) { |
88 if(event->events != ep) { |
100 // ret 0 => remove event |
89 changes[numchanges++].filter = ev_convert2sys_events(ep); |
101 |
|
102 if(event->finish) { |
|
103 event->finish(ev, event); |
90 } |
104 } |
91 } else if(event->finish) { |
105 |
92 changes[numchanges++].filter = ev_convert2sys_events(ep); |
106 event_events = 0; |
93 event->finish(ev, event); |
107 } else { |
|
108 event_events = event->events; |
|
109 } |
|
110 |
|
111 // if events have changed, we need to add/remove filters |
|
112 if(saved_ev != event_events) { |
|
113 int e = event_events; |
|
114 int e_fd = events[i].ident; |
|
115 if((e & EVENT_POLLIN) != (saved_ev & EVENT_POLLIN)) { |
|
116 if((e & EVENT_POLLIN) == EVENT_POLLIN) { |
|
117 // add |
|
118 EV_SET(&changes[numchanges++], e_fd, EVFILT_READ, EV_ADD, 0, 0, event); |
|
119 } else { |
|
120 // delete |
|
121 EV_SET(&changes[numchanges++], e_fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); |
|
122 } |
|
123 } |
|
124 if((e & EVENT_POLLOUT) != (saved_ev & EVENT_POLLOUT)) { |
|
125 if((e & EVENT_POLLOUT) == EVENT_POLLOUT) { |
|
126 // add |
|
127 EV_SET(&changes[numchanges++], e_fd, EVFILT_WRITE, EV_ADD, 0, 0, event); |
|
128 } else { |
|
129 // delete |
|
130 EV_SET(&changes[numchanges++], e_fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); |
|
131 } |
|
132 } |
94 } |
133 } |
95 } |
134 } |
96 } |
135 } |
97 } |
136 } |
98 } |
|
99 |
|
100 int ev_convert2sys_events(int events) { |
|
101 int e = 0; |
|
102 if((events & EVENT_POLLIN) == EVENT_POLLIN) { |
|
103 e |= EVFILT_READ; |
|
104 } |
|
105 if((events & EVENT_POLLOUT) == EVENT_POLLOUT) { |
|
106 e |= EVFILT_WRITE; |
|
107 } |
|
108 return e; |
|
109 } |
137 } |
110 |
138 |
111 int ev_pollin(EventHandler *h, int fd, Event *event) { |
139 int ev_pollin(EventHandler *h, int fd, Event *event) { |
112 event->events = EVENT_POLLIN; |
140 event->events = EVENT_POLLIN; |
113 struct kevent kev; |
141 struct kevent kev; |
120 struct kevent kev; |
148 struct kevent kev; |
121 EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, event); |
149 EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, event); |
122 return kevent(h->kqueue, &kev, 1, NULL, 0, NULL); |
150 return kevent(h->kqueue, &kev, 1, NULL, 0, NULL); |
123 } |
151 } |
124 |
152 |
|
153 int ev_remove_poll(EventHandler *h, int fd) { |
|
154 struct kevent kev; |
|
155 EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); |
|
156 int r1 = kevent(h->kqueue, &kev, 1, NULL, 0, NULL); |
|
157 EV_SET(&kev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); |
|
158 int r2 = kevent(h->kqueue, &kev, 1, NULL, 0, NULL); |
|
159 // in caase r1 or r2 was successful, we return 0 (no error) |
|
160 return r1 != -1 || r2 != -1 ? 0 : 1; |
|
161 } |
|
162 |
125 int event_send(EventHandler *h, Event *event) { |
163 int event_send(EventHandler *h, Event *event) { |
126 return 0; |
164 return 0; |
127 } |
165 } |
|
166 |
|
167 // TODO: remove this fake aio |
|
168 int ev_aioread(int fd, aiocb_s *cb) { |
|
169 ssize_t result = pread(fd, cb->buf, cb->nbytes, cb->offset); |
|
170 cb->result = result; |
|
171 if(result < 0) { |
|
172 cb->result_errno = errno; |
|
173 } |
|
174 return event_send(cb->evhandler, cb->event); |
|
175 } |
|
176 |
|
177 int ev_aiowrite(int fd, aiocb_s *cb) { |
|
178 ssize_t result = pwrite(fd, cb->buf, cb->nbytes, cb->offset); |
|
179 cb->result = result; |
|
180 if(result < 0) { |
|
181 cb->result_errno = errno; |
|
182 } |
|
183 return event_send(cb->evhandler, cb->event); |
|
184 } |