0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
IOHandler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 3
9  * of the License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
28 #include <Common/Compat.h>
29 
30 #include "IOHandler.h"
31 #include "Reactor.h"
32 #include "ReactorRunner.h"
33 
34 #include <Common/Logger.h>
35 
36 #include <cstdio>
37 #include <iostream>
38 
39 extern "C" {
40 #include <errno.h>
41 #if defined(__APPLE__) || defined(__FreeBSD__)
42 #include <sys/event.h>
43 #elif defined(__sun__)
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #endif
47 }
48 
49 using namespace Hypertable;
50 using namespace std;
51 
52 #define HANDLE_POLL_INTERFACE_MODIFY \
53  if (ReactorFactory::use_poll) \
54  return m_reactor->modify_poll_interest(m_sd, poll_events(m_poll_interest));
55 
56 #define HANDLE_POLL_INTERFACE_ADD \
57  if (ReactorFactory::use_poll) \
58  return m_reactor->add_poll_interest(m_sd, poll_events(m_poll_interest), this);
59 
60 void IOHandler::display_event(struct pollfd *event) {
61  char buf[128];
62 
63  buf[0] = 0;
64  if (event->revents & POLLIN)
65  strcat(buf, "POLLIN ");
66  if (event->revents & POLLRDNORM)
67  strcat(buf, "POLLRDNORM ");
68  if (event->revents & POLLRDBAND)
69  strcat(buf, "POLLRDBAND ");
70  if (event->revents & POLLPRI)
71  strcat(buf, "POLLPRI ");
72  if (event->revents & POLLOUT)
73  strcat(buf, "POLLOUT ");
74  if (event->revents & POLLWRNORM)
75  strcat(buf, "POLLWRNORM ");
76  if (event->revents & POLLWRBAND)
77  strcat(buf, "POLLWRBAND ");
78  if (event->revents & POLLERR)
79  strcat(buf, "POLLERR ");
80  if (event->revents & POLLHUP)
81  strcat(buf, "POLLHUP ");
82  if (event->revents & POLLNVAL)
83  strcat(buf, "POLLNVAL ");
84 
85  if (buf[0] == 0)
86  sprintf(buf, "0x%x ", event->revents);
87 
88  clog << "poll events = " << buf << endl;
89 }
90 
91 int IOHandler::start_polling(int mode) {
93  m_poll_interest = mode;
94  return m_reactor->add_poll_interest(m_sd, poll_events(mode), this);
95  }
96 #if defined(__APPLE__) || defined(__sun__) || defined(__FreeBSD__)
97  return add_poll_interest(mode);
98 #elif defined(__linux__)
99  struct epoll_event event;
100  memset(&event, 0, sizeof(struct epoll_event));
101  event.data.ptr = this;
102  if (mode & PollEvent::READ)
103  event.events |= EPOLLIN;
104  if (mode & PollEvent::WRITE)
105  event.events |= EPOLLOUT;
107  event.events |= POLLRDHUP | EPOLLET;
108  m_poll_interest = mode;
109  if (epoll_ctl(m_reactor->poll_fd, EPOLL_CTL_ADD, m_sd, &event) < 0) {
110  HT_DEBUGF("epoll_ctl(%d, EPOLL_CTL_ADD, %d, %x) failed : %s",
111  m_reactor->poll_fd, m_sd, event.events, strerror(errno));
112  return Error::COMM_POLL_ERROR;
113  }
114 #endif
115  return Error::OK;
116 }
117 
118 
119 #if defined(__linux__)
120 
121 int IOHandler::add_poll_interest(int mode) {
122 
123  m_poll_interest |= mode;
124 
126 
128  struct epoll_event event;
129 
130  memset(&event, 0, sizeof(struct epoll_event));
131  event.data.ptr = this;
132 
133  if (m_poll_interest & PollEvent::READ)
134  event.events |= EPOLLIN;
135  if (m_poll_interest & PollEvent::WRITE)
136  event.events |= EPOLLOUT;
137 
138  if (epoll_ctl(m_reactor->poll_fd, EPOLL_CTL_MOD, m_sd, &event) < 0) {
139  HT_DEBUGF("epoll_ctl(%d, EPOLL_CTL_MOD, sd=%d) (mode=%x, interest=%x) : %s",
140  m_reactor->poll_fd, m_sd, mode, m_poll_interest, strerror(errno));
141  return Error::COMM_POLL_ERROR;
142  }
143  }
144  return Error::OK;
145 }
146 
147 
148 
149 int IOHandler::remove_poll_interest(int mode) {
150  m_poll_interest &= ~mode;
151 
153 
155  struct epoll_event event;
156 
157  memset(&event, 0, sizeof(struct epoll_event));
158  event.data.ptr = this;
159 
160  if (m_poll_interest & PollEvent::READ)
161  event.events |= EPOLLIN;
162  if (m_poll_interest & PollEvent::WRITE)
163  event.events |= EPOLLOUT;
164 
165  if (epoll_ctl(m_reactor->poll_fd, EPOLL_CTL_MOD, m_sd, &event) < 0) {
166  HT_DEBUGF("epoll_ctl(EPOLL_CTL_MOD, sd=%d) (mode=%x) : %s",
167  m_sd, mode, strerror(errno));
168  return Error::COMM_POLL_ERROR;
169  }
170  }
171  return Error::OK;
172 }
173 
174 
175 
176 void IOHandler::display_event(struct epoll_event *event) {
177  char buf[128];
178 
179  buf[0] = 0;
180  if (event->events & EPOLLIN)
181  strcat(buf, "EPOLLIN ");
182  else if (event->events & EPOLLOUT)
183  strcat(buf, "EPOLLOUT ");
184  else if (event->events & EPOLLPRI)
185  strcat(buf, "EPOLLPRI ");
186  else if (event->events & EPOLLERR)
187  strcat(buf, "EPOLLERR ");
188  else if (event->events & EPOLLHUP)
189  strcat(buf, "EPOLLHUP ");
190  else if (ReactorFactory::ms_epollet && event->events & POLLRDHUP)
191  strcat(buf, "POLLRDHUP ");
192  else if (event->events & EPOLLET)
193  strcat(buf, "EPOLLET ");
194 #if defined(EPOLLONESHOT)
195  else if (event->events & EPOLLONESHOT)
196  strcat(buf, "EPOLLONESHOT ");
197 #endif
198 
199  if (buf[0] == 0)
200  sprintf(buf, "0x%x ", event->events);
201 
202  clog << "epoll events = " << buf << endl;
203 
204  return;
205 }
206 
207 #elif defined(__sun__)
208 
209 int IOHandler::add_poll_interest(int mode) {
210  int events = 0;
211 
212  m_poll_interest |= mode;
213 
215 
216  if (m_poll_interest & PollEvent::WRITE)
217  events |= POLLOUT;
218 
219  if (m_poll_interest & PollEvent::READ)
220  events |= POLLIN;
221 
222  if (events) {
223  if (port_associate(m_reactor->poll_fd, PORT_SOURCE_FD,
224  m_sd, events, this) < 0) {
225  HT_DEBUGF("port_associate(%d, POLLIN, %d) - %s", m_reactor->poll_fd, m_sd,
226  strerror(errno));
227  return Error::COMM_POLL_ERROR;
228  }
229  }
230  return Error::OK;
231 }
232 
233 int IOHandler::remove_poll_interest(int mode) {
234  int error = Error::OK;
235 
236  if ((m_poll_interest & mode) == 0)
237  return Error::OK;
238 
239  m_poll_interest &= ~mode;
240 
242 
243  if (m_poll_interest)
244  error = reset_poll_interest();
245  else {
246  if (port_dissociate(m_reactor->poll_fd, PORT_SOURCE_FD, m_sd) < 0) {
247  HT_DEBUGF("port_dissociate(%d, PORT_SOURCE_FD, %d) - %s",
248  m_reactor->poll_fd, m_sd, strerror(errno));
249  return Error::COMM_POLL_ERROR;
250  }
251  }
252  return error;
253 }
254 
255 void IOHandler::display_event(port_event_t *event) {
256  char buf[128];
257 
258  buf[0] = 0;
259 
260  if (event->portev_events & POLLIN)
261  strcat(buf, "POLLIN ");
262  if (event->portev_events & POLLPRI)
263  strcat(buf, "POLLPRI ");
264  if (event->portev_events & POLLOUT)
265  strcat(buf, "POLLOUT ");
266  if (event->portev_events & POLLRDNORM)
267  strcat(buf, "POLLRDNORM ");
268  if (event->portev_events & POLLRDBAND)
269  strcat(buf, "POLLRDBAND ");
270  if (event->portev_events & POLLWRBAND)
271  strcat(buf, "POLLWRBAND ");
272  if (event->portev_events & POLLERR)
273  strcat(buf, "POLLERR ");
274  if (event->portev_events & POLLHUP)
275  strcat(buf, "POLLHUP ");
276  if (event->portev_events & POLLNVAL)
277  strcat(buf, "POLLNVAL ");
278  if (event->portev_events & POLLREMOVE)
279  strcat(buf, "POLLREMOVE ");
280 
281  if (buf[0] == 0)
282  sprintf(buf, "0x%x ", event->portev_events);
283 
284  clog << "port events = " << buf << endl;
285 
286 }
287 
288 #elif defined(__APPLE__) || defined(__FreeBSD__)
289 
290 int IOHandler::add_poll_interest(int mode) {
291  struct kevent events[2];
292  int count=0;
293 
294  m_poll_interest |= mode;
295 
297 
298  if (mode & PollEvent::READ) {
299  EV_SET(&events[count], m_sd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, this);
300  count++;
301  }
302  if (mode & PollEvent::WRITE) {
303  EV_SET(&events[count], m_sd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, this);
304  count++;
305  }
306  assert(count > 0);
307 
308  if (kevent(m_reactor->kqd, events, count, 0, 0, 0) == -1) {
309  HT_DEBUGF("kevent(sd=%d) (mode=%x) : %s", m_sd, mode, strerror(errno));
310  return Error::COMM_POLL_ERROR;
311  }
312  return Error::OK;
313 }
314 
315 
316 int IOHandler::remove_poll_interest(int mode) {
317  struct kevent devents[2];
318  int count = 0;
319 
320  m_poll_interest &= ~mode;
321 
323 
324  if (mode & PollEvent::READ) {
325  EV_SET(&devents[count], m_sd, EVFILT_READ, EV_DELETE, 0, 0, 0);
326  count++;
327  }
328 
329  if (mode & PollEvent::WRITE) {
330  EV_SET(&devents[count], m_sd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
331  count++;
332  }
333 
334  if (kevent(m_reactor->kqd, devents, count, 0, 0, 0) == -1
335  && errno != ENOENT) {
336  HT_DEBUGF("kevent(sd=%d) (mode=%x) : %s", m_sd, mode, strerror(errno));
337  return Error::COMM_POLL_ERROR;
338  }
339  return Error::OK;
340 }
341 
342 
346 void IOHandler::display_event(struct kevent *event) {
347 
348  clog << "kevent: ident=" << hex << (long)event->ident;
349 
350  switch (event->filter) {
351  case EVFILT_READ:
352  clog << ", EVFILT_READ, fflags=";
353  if (event->fflags & NOTE_LOWAT)
354  clog << "NOTE_LOWAT";
355  else
356  clog << event->fflags;
357  break;
358  case EVFILT_WRITE:
359  clog << ", EVFILT_WRITE, fflags=";
360  if (event->fflags & NOTE_LOWAT)
361  clog << "NOTE_LOWAT";
362  else
363  clog << event->fflags;
364  break;
365  case EVFILT_AIO:
366  clog << ", EVFILT_AIO, fflags=" << event->fflags;
367  break;
368  case EVFILT_VNODE:
369  clog << ", EVFILT_VNODE, fflags={";
370  if (event->fflags & NOTE_DELETE)
371  clog << " NOTE_DELETE";
372  if (event->fflags & NOTE_WRITE)
373  clog << " NOTE_WRITE";
374  if (event->fflags & NOTE_EXTEND)
375  clog << " NOTE_EXTEND";
376  if (event->fflags & NOTE_ATTRIB)
377  clog << " NOTE_ATTRIB";
378  if (event->fflags & NOTE_LINK)
379  clog << " NOTE_LINK";
380  if (event->fflags & NOTE_RENAME)
381  clog << " NOTE_RENAME";
382  if (event->fflags & NOTE_REVOKE)
383  clog << " NOTE_REVOKE";
384  clog << " }";
385  break;
386  case EVFILT_PROC:
387  clog << ", EVFILT_VNODE, fflags={";
388  if (event->fflags & NOTE_EXIT)
389  clog << " NOTE_EXIT";
390  if (event->fflags & NOTE_FORK)
391  clog << " NOTE_FORK";
392  if (event->fflags & NOTE_EXEC)
393  clog << " NOTE_EXEC";
394  if (event->fflags & NOTE_TRACK)
395  clog << " NOTE_TRACK";
396  if (event->fflags & NOTE_TRACKERR)
397  clog << " NOTE_TRACKERR";
398  if (event->fflags & NOTE_CHILD)
399  clog << " NOTE_CHILD";
400  clog << " pid=" << (event->flags & NOTE_PDATAMASK);
401  break;
402  case EVFILT_SIGNAL:
403  clog << ", EVFILT_SIGNAL, fflags=" << event->fflags;
404  break;
405  case EVFILT_TIMER:
406 #ifdef __FreeBSD__
407  clog << ", EVFILT_TIMER, fflags=" << event->fflags;
408 #else
409  clog << ", EVFILT_TIMER, fflags={";
410  if (event->fflags & NOTE_SECONDS)
411  clog << " NOTE_SECONDS";
412  if (event->fflags & NOTE_USECONDS)
413  clog << " NOTE_USECONDS";
414  if (event->fflags & NOTE_NSECONDS)
415  clog << " NOTE_NSECONDS";
416  if (event->fflags & NOTE_ABSOLUTE)
417  clog << " NOTE_ABSOLUTE";
418  clog << " }";
419 #endif
420  break;
421  }
422 
423  if(event->flags != 0) {
424  clog << ", flags=";
425  if ((event->flags & EV_EOF) || (event->flags & EV_ERROR)) {
426  clog << "{";
427  if (event->flags & EV_EOF)
428  clog << " EV_EOF";
429  if (event->flags & EV_ERROR)
430  clog << " EV_ERROR";
431  clog << "}";
432  }
433  else
434  clog << hex << event->flags;
435  }
436  clog << ", data=" << dec << (long)event->data << endl;
437 }
438 
439 #else
441 #endif
int start_polling(int mode=PollEvent::READ)
Start polling on the handler with the poll interest specified in mode.
Definition: IOHandler.cc:91
#define HANDLE_POLL_INTERFACE_MODIFY
Definition: IOHandler.cc:52
Declarations for ReactorRunner.
static bool ms_epollet
Use "edge triggered" epoll.
STL namespace.
int remove_poll_interest(int mode)
Removes the poll interest specified in mode to the polling interface for this handler.
void display_event(struct pollfd *event)
Display polling event from poll() interface to stderr.
Definition: IOHandler.cc:60
Data available to read.
Definition: PollEvent.h:42
ImplementMe
Definition: IOHandler.cc:440
Logging routines and macros.
Compatibility Macros for C/C++.
Declarations for Reactor.
Hypertable definitions
#define HT_DEBUGF(msg,...)
Definition: Logger.h:260
Writing can be performed without blocking.
Definition: PollEvent.h:46
#define HANDLE_POLL_INTERFACE_ADD
Definition: IOHandler.cc:56
int add_poll_interest(int mode)
Adds the poll interest specified in mode to the polling interface for this handler.
Declarations for IOHandler.