fdwatch_poll.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:5k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.   * Abstraction API/layer for the various ways PvPGN can inspect sockets state
  3.   * 2003 (C) dizzy@roedu.net
  4.   *
  5.   * Code is based on the ideas found in thttpd project.
  6.   *
  7.   * poll() based backend
  8.   *
  9.   * This program is free software; you can redistribute it and/or
  10.   * modify it under the terms of the GNU General Public License
  11.   * as published by the Free Software Foundation; either version 2
  12.   * of the License, or (at your option) any later version.
  13.   *
  14.   * This program is distributed in the hope that it will be useful,
  15.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.   * GNU General Public License for more details.
  18.   *
  19.   * You should have received a copy of the GNU General Public License
  20.   * along with this program; if not, write to the Free Software
  21.   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22.   */
  23. #include "common/setup_before.h"
  24. #ifdef STDC_HEADERS
  25. # include <stdlib.h>
  26. #else
  27. # ifdef HAVE_MALLOC_H
  28. #  include <malloc.h>
  29. # endif
  30. #endif
  31. #ifdef HAVE_STRING_H
  32. # include <string.h>
  33. #else
  34. # ifdef HAVE_STRINGS_H
  35. #  include <strings.h>
  36. # endif
  37. #endif
  38. #ifdef HAVE_POLL_H
  39. # include <poll.h>
  40. #else
  41. # ifdef HAVE_SYS_POLL_H
  42. #  include <sys/poll.h>
  43. # endif
  44. #endif
  45. #include "fdwatch.h"
  46. #include "common/eventlog.h"
  47. #include "common/setup_after.h"
  48. #ifdef HAVE_POLL
  49. static int sr;
  50. static struct pollfd *fds = NULL, /* working set */
  51.      *tfds = NULL; /* template */
  52. static int *fdw_ridx = NULL;
  53. static unsigned nofds;
  54. static int fdw_poll_init(int nfds);
  55. static int fdw_poll_close(void);
  56. static int fdw_poll_add_fd(int fd, t_fdwatch_type rw);
  57. static int fdw_poll_del_fd(int fd);
  58. static int fdw_poll_watch(long timeout_msecs);
  59. static void fdw_poll_handle(void);
  60. t_fdw_backend fdw_poll = {
  61.     fdw_poll_init,
  62.     fdw_poll_close,
  63.     fdw_poll_add_fd,
  64.     fdw_poll_del_fd,
  65.     fdw_poll_watch,
  66.     fdw_poll_handle
  67. };
  68. static int fdw_poll_init(int nfds)
  69. {
  70.     int i;
  71.     fdw_ridx = malloc(sizeof(int) * nfds);
  72.     fds = malloc(sizeof(struct pollfd) * nfds);
  73.     tfds = malloc(sizeof(struct pollfd) * nfds);
  74.     if (fdw_ridx == NULL || fds == NULL || tfds == NULL) {
  75. fdw_poll_close();
  76. return -1;
  77.     }
  78.     memset(tfds, 0, sizeof(struct pollfd) * nfds);
  79. /* I would use a memset with 255 but that is dirty and doesnt gain us anything */
  80.     for(i = 0; i < nfds; i++) fdw_ridx[i] = -1;
  81.     nofds = sr = 0;
  82.     eventlog(eventlog_level_info, __FUNCTION__, "fdwatch poll() based layer initialized (max %d sockets)", nfds);
  83.     return 0;
  84. }
  85. static int fdw_poll_close(void)
  86. {
  87.     if (tfds) { free((void *)tfds); tfds = NULL; }
  88.     if (fds) { free((void *)fds); fds = NULL; }
  89.     if (fdw_ridx) { free((void *)fdw_ridx); fdw_ridx = NULL; }
  90.     nofds = sr = 0;
  91.     return 0;
  92. }
  93. static int fdw_poll_add_fd(int fd, t_fdwatch_type rw)
  94. {
  95.     static int ridx;
  96. //    eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw);
  97.     if (fdw_ridx[fd] < 0) {
  98. ridx = nofds++;
  99. tfds[ridx].fd = fd;
  100. fdw_ridx[fd] = ridx;
  101. // eventlog(eventlog_level_trace, __FUNCTION__, "adding new fd on %d", ridx);
  102.     } else {
  103. if (tfds[fdw_ridx[fd]].fd != fd) {
  104.     return -1;
  105. }
  106. ridx = fdw_ridx[fd];
  107. // eventlog(eventlog_level_trace, __FUNCTION__, "updating fd on %d", ridx);
  108.     }
  109.     tfds[ridx].events = 0;
  110.     if (rw & fdwatch_type_read) tfds[ridx].events |= POLLIN;
  111.     if (rw & fdwatch_type_write) tfds[ridx].events |= POLLOUT;
  112.     return 0;
  113. }
  114. static int fdw_poll_del_fd(int fd)
  115. {
  116. //    eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd);
  117.     if (fdw_ridx[fd] < 0 || !nofds) return -1;
  118.     if (sr > 0) 
  119. eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets");
  120.     /* move the last entry to the deleted one and decrement nofds count */
  121.     nofds--;
  122.     if (fdw_ridx[fd] < nofds) {
  123. // eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", tfds[nofds].fd);
  124. fdw_ridx[tfds[nofds].fd] = fdw_ridx[fd];
  125. memcpy(tfds + fdw_ridx[fd], tfds + nofds, sizeof(struct pollfd));
  126.     }
  127.     fdw_ridx[fd] = -1;
  128.     return 0;
  129. }
  130. static int fdw_poll_watch(long timeout_msec)
  131. {
  132.     memcpy(fds, tfds, sizeof(struct pollfd) * nofds);
  133.     return (sr = poll(fds, nofds, timeout_msec));
  134. }
  135. static void fdw_poll_handle(void)
  136. {
  137.     register unsigned i;
  138.     int changed;
  139.     for(i = 0; i < nofds && sr; i++) {
  140. changed = 0;
  141. if (fdw_rw[fds[i].fd] & fdwatch_type_read && 
  142.     fds[i].revents & (POLLIN  | POLLERR | POLLHUP | POLLNVAL))
  143. {
  144.     if (fdw_hnd[fds[i].fd](fdw_data[fds[i].fd], fdwatch_type_read) == -2) {
  145. sr--;
  146. continue;
  147.     }
  148.     changed = 1;
  149. }
  150. if (fdw_rw[fds[i].fd] & fdwatch_type_write && 
  151.     fds[i].revents & (POLLOUT  | POLLERR | POLLHUP | POLLNVAL))
  152. {
  153.     fdw_hnd[fds[i].fd](fdw_data[fds[i].fd], fdwatch_type_write);
  154.     changed = 1;
  155. }
  156. if (changed) sr--;
  157.     }
  158. }
  159. #endif /* HAVE_POLL */