Changeset c346b2


Ignore:
Timestamp:
10/05/08 13:49:56 (4 years ago)
Author:
Tomash Brechko <tomash.brechko@…>
Branches:
master
Children:
e61b4e
Parents:
46fd4a
git-author:
Tomash Brechko <tomash.brechko@…> (10/04/08 15:44:14)
git-committer:
Tomash Brechko <tomash.brechko@…> (10/05/08 13:49:56)
Message:

Use poll() instead of select(). Implement it where not available.

Possible select()'able descriptor shortage reported by
Vladimir Timofeev.

Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • Changes

    r46fd4a rc346b2  
    330.13  ??? 
    44        - introduce Win32 support (based on the patch by Yasuhiro 
    5           Matsumoto---arigatou!). 
     5          Matsumoto---arigatou!), and use poll() instead of select() 
     6          (suggested by Vladimir Timofeev). 
    67 
    78        Changes since 0.12: 
     
    1011        compiler, so I can't even test the build.  Win32 port is 
    1112        expected to be supported by community. 
     13 
     14        Use poll() system call instead of select().  The latter has 
     15        the limit on the file descriptor value.  I.e. even when the 
     16        number of memcached servers is low, if your application opens 
     17        lots of other files, then after some point socket() returns 
     18        fd value larger that select() can handle.  poll() doesn't have 
     19        this limitation.  On a side note, we don't have to use 
     20        advanced calls like epoll()/kqueue(), because number of 
     21        memcached servers is normally not very large (and single 
     22        request touches even a smaller subset). 
    1223 
    1324 
  • MANIFEST

    r46fd4a rc346b2  
    3838src/socket_win32.c 
    3939src/socket_win32.h 
     40src/poll_select.c 
     41src/poll_select.h 
  • src/Makefile.PL

    r46fd4a rc346b2  
    55 
    66 
     7my $includes = '/usr/include'; 
     8my @define; 
    79my @c = ('parse_keyword.c', 'compute_crc32.c', <*.c>); 
    8 my $exclude; 
     10my %exclude; 
    911if ($^O eq 'MSWin32') { 
    10     $exclude = 'socket_posix.c'; 
     12    ++$exclude{'socket_posix.c'}; 
    1113} else { 
    12     $exclude = 'socket_win32.c'; 
     14    ++$exclude{'socket_win32.c'}; 
     15 
     16    if (-f "$includes/poll.h") { 
     17        push @define, '-DHAVE_POLL_H'; 
     18        ++$exclude{'poll_select.c'}; 
     19    } elsif (-f "$includes/sys/poll.h") { 
     20        push @define, '-DHAVE_SYS_POLL_H'; 
     21        ++$exclude{'poll_select.c'}; 
     22    } 
    1323} 
    1424 
    15 my @object = grep { $_ ne $exclude } @c; 
     25my @object = grep { not exists $exclude{$_} } @c; 
    1626map { s/\.c$/\$(OBJ_EXT)/ } @object; 
    1727 
     
    2434    AUTHOR            => 'Tomash Brechko <tomash.brechko@gmail.com>', 
    2535    LIBS              => [''], # e.g., '-lm' 
    26     DEFINE            => '', # e.g., '-DHAVE_SOMETHING' 
     36    DEFINE            => "@define", # e.g., '-DHAVE_SOMETHING' 
    2737    INC               => '-I.', # e.g., '-I. -I/usr/include/other' 
    2838    OBJECT            => "@object", 
  • src/client.c

    r46fd4a rc346b2  
    105105  struct client *client; 
    106106  int fd; 
     107  struct pollfd *pollfd; 
    107108  enum socket_mode_e socket_mode; 
    108109  int noreply; 
     
    249250struct client 
    250251{ 
     252  struct array pollfds; 
    251253  struct array servers; 
    252254 
     
    350352    return NULL; 
    351353 
     354  array_init(&c->pollfds); 
    352355  array_init(&c->servers); 
    353356  array_init(&c->index_list); 
     
    394397 
    395398  array_destroy(&c->servers); 
     399  array_destroy(&c->pollfds); 
    396400  array_destroy(&c->index_list); 
    397401  array_destroy(&c->str_buf); 
     
    423427client_set_connect_timeout(struct client *c, int to) 
    424428{ 
    425   c->connect_timeout = to; 
     429  c->connect_timeout = (to > 0 ? to : -1); 
    426430} 
    427431 
     
    430434client_set_io_timeout(struct client *c, int to) 
    431435{ 
    432   c->io_timeout = to; 
     436  c->io_timeout = (to > 0 ? to : -1); 
    433437} 
    434438 
     
    477481 
    478482  if (weight <= 0.0) 
     483    return MEMCACHED_FAILURE; 
     484 
     485  if (array_extend(c->pollfds, struct pollfd, 1, ARRAY_EXTEND_EXACT) == -1) 
    479486    return MEMCACHED_FAILURE; 
    480487 
     
    492499    return MEMCACHED_FAILURE; 
    493500 
     501  array_push(c->pollfds); 
    494502  array_push(c->servers); 
    495503 
     
    13801388client_execute(struct client *c) 
    13811389{ 
    1382   struct timeval to, *pto = c->io_timeout > 0 ? &to : NULL; 
    1383   fd_set write_set, read_set; 
    13841390  int first_iter = 1; 
    13851391 
     
    13991405    { 
    14001406      struct server *s; 
    1401       int max_fd, res; 
    1402  
    1403       max_fd = -1; 
     1407      struct pollfd *pollfd_beg, *pollfd; 
     1408      int nfds, res; 
     1409 
     1410      nfds = 0; 
    14041411      for (array_each(c->servers, struct server, s)) 
    14051412        { 
     
    14201427          else 
    14211428            { 
    1422               may_write = FD_ISSET(state->fd, &write_set); 
    1423               may_read = FD_ISSET(state->fd, &read_set); 
     1429              const short revents = state->pollfd->revents; 
     1430 
     1431              may_write = revents & (POLLOUT | POLLERR | POLLHUP); 
     1432              may_read = revents & (POLLIN | POLLERR | POLLHUP); 
    14241433            } 
    14251434 
     
    14461455 
    14471456              if (is_active(state)) 
    1448                 { 
    1449                   if (max_fd < state->fd) 
    1450                     max_fd = state->fd; 
    1451                 } 
     1457                ++nfds; 
    14521458            } 
    14531459          else 
    14541460            { 
    1455               if (max_fd < state->fd) 
    1456                 max_fd = state->fd; 
     1461              ++nfds; 
    14571462            } 
    14581463        } 
    14591464 
    1460       if (max_fd == -1) 
     1465      if (nfds == 0) 
    14611466        break; 
    14621467 
    1463       FD_ZERO(&write_set); 
    1464       FD_ZERO(&read_set); 
     1468      pollfd_beg = array_beg(c->pollfds, struct pollfd); 
     1469      pollfd = pollfd_beg; 
     1470 
    14651471      for (array_each(c->servers, struct server, s)) 
    14661472        { 
     
    14691475          if (is_active(state)) 
    14701476            { 
     1477              pollfd->events = 0; 
     1478 
    14711479              if (state->iov_count > 0) 
    1472                 FD_SET(state->fd, &write_set); 
     1480                pollfd->events |= POLLOUT; 
    14731481              if (state->reply_count > 0 || state->nowait_count > 0) 
    1474                 FD_SET(state->fd, &read_set); 
     1482                pollfd->events |= POLLIN; 
     1483 
     1484              if (pollfd->events != 0) 
     1485                { 
     1486                  pollfd->fd = state->fd; 
     1487                  state->pollfd = pollfd; 
     1488                  ++pollfd; 
     1489                } 
    14751490            } 
    14761491        } 
    14771492 
    14781493      do 
    1479         { 
    1480           /* 
    1481             For maximum portability across systems that may or may not 
    1482             modify the timeout argument we treat it as undefined after 
    1483             the call, and reinitialize on every iteration. 
    1484           */ 
    1485           if (pto) 
    1486             { 
    1487               pto->tv_sec = c->io_timeout / 1000; 
    1488               pto->tv_usec = (c->io_timeout % 1000) * 1000; 
    1489             } 
    1490           res = select(max_fd + 1, &read_set, &write_set, NULL, pto); 
    1491         } 
     1494        res = poll(pollfd_beg, pollfd - pollfd_beg, c->io_timeout); 
    14921495      while (res == -1 && errno == EINTR); 
    14931496 
  • src/connect.c

    r46fd4a rc346b2  
    3636                    int timeout) 
    3737{ 
    38   struct timeval to, *pto; 
    3938  struct addrinfo hint, *addr, *a; 
    4039  int fd = -1, res; 
    41  
    42   pto = timeout > 0 ? &to : NULL; 
    4340 
    4441  memset(&hint, 0, sizeof(hint)); 
     
    6259  for (a = addr; a != NULL; a = a->ai_next) 
    6360    { 
    64       fd_set write_set; 
     61      struct pollfd pollfd; 
    6562      int socket_error; 
    6663      socklen_t socket_error_len; 
     
    6966      if (fd == -1) 
    7067        break; 
     68 
     69      if (! can_poll_fd(fd)) 
     70        { 
     71          close(fd); 
     72          fd = -1; 
     73          break; 
     74        } 
    7175 
    7276      res = set_nonblock(fd); 
     
    8892        } 
    8993 
    90       FD_ZERO(&write_set); 
    91       FD_SET(fd, &write_set); 
     94      pollfd.fd = fd; 
     95      pollfd.events = POLLOUT; 
    9296      do 
    93         { 
    94           if (pto) 
    95             { 
    96               pto->tv_sec = timeout / 1000; 
    97               pto->tv_usec = (timeout % 1000) * 1000; 
    98             } 
    99           res = select(fd + 1, NULL, &write_set, NULL, pto); 
    100         } 
     97        res = poll(&pollfd, 1, timeout); 
    10198      while (res == -1 && errno == EINTR); 
    10299      if (res <= 0) 
  • src/socket_posix.c

    r11df21 rc346b2  
    5858    return -1; 
    5959 
     60  if (! can_poll_fd(fd)) 
     61    { 
     62      close(fd); 
     63 
     64      return -1; 
     65    } 
     66 
    6067  s_unix.sun_family = AF_UNIX; 
    6168  memcpy(s_unix.sun_path, path, path_len); 
  • src/socket_posix.h

    r11df21 rc346b2  
    3131#include <errno.h> 
    3232 
     33#if defined(HAVE_POLL_H) 
     34 
     35#include <poll.h> 
     36 
     37#define can_poll_fd(fd)  1 
     38 
     39#elif defined(HAVE_SYS_POLL_H) 
     40 
     41#include <sys/poll.h> 
     42 
     43#define can_poll_fd(fd)  1 
     44 
     45#else  /* ! defined(HAVE_POLL_H) && ! defined(HAVE_SYS_POLL_H) */ 
     46 
     47#include "poll_select.h" 
     48 
     49#define poll(fds, nfds, timeout)  poll_select(fds, nfds, timeout) 
     50 
     51#endif  /* ! defined(HAVE_POLL_H) && ! defined(HAVE_SYS_POLL_H) */ 
     52 
    3353 
    3454extern 
  • src/socket_win32.h

    r46fd4a rc346b2  
    3131#include <ws2tcpip.h> 
    3232#include <sys/types.h> 
     33 
     34#if _WIN32_WINNT >= 0x0600 
     35 
     36#define poll(fds, nfds, timeout)  WSAPoll(fds, nfds, timeout) 
     37 
     38#define can_poll_fd(fd)  1 
     39 
     40#else  /* ! (_WIN32_WINNT >= 0x0600) */ 
     41 
     42#include "poll_select.h" 
     43 
     44#define poll(fds, nfds, timeout)  poll_select(fds, nfds, timeout) 
     45 
     46#endif  /* ! (_WIN32_WINNT >= 0x0600) */ 
    3347 
    3448 
Note: See TracChangeset for help on using the changeset viewer.