From 69afed6d6edb2319f038a68c3ea4cb48e55aaf6f Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Wed, 2 Jan 2008 09:32:58 +0000 Subject: [PATCH] move poll compat func to .c file, make fd_set runtime resizeable --- Makefile | 3 +- src/poll_compat.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++ src/poll_compat.h | 99 ++++++++++++++--------------------- 3 files changed, 167 insertions(+), 63 deletions(-) create mode 100644 src/poll_compat.c diff --git a/Makefile b/Makefile index b715a55..39cd5f5 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ BISON = bison # module setup MODULE_big = plproxy SRCS = src/cluster.c src/execute.c src/function.c src/main.c \ - src/query.c src/result.c src/type.c + src/query.c src/result.c src/type.c src/poll_compat.c OBJS = src/scanner.o src/parser.tab.o $(SRCS:.c=.o) DATA_built = plproxy.sql EXTRA_CLEAN = src/scanner.[ch] src/parser.tab.[ch] @@ -51,6 +51,7 @@ src/scanner.c: src/scanner.l # dependencies $(OBJS): src/plproxy.h src/rowstamp.h src/execute.o: src/poll_compat.h +src/poll_compat.o: src/poll_compat.h # utility rules diff --git a/src/poll_compat.c b/src/poll_compat.c new file mode 100644 index 0000000..fa180da --- /dev/null +++ b/src/poll_compat.c @@ -0,0 +1,128 @@ + +#include "postgres.h" + +#include "poll_compat.h" + +#ifdef PLPROXY_POLL_COMPAT + +/* + * Emulate poll() with select() + */ + +#include +#include + +/* + * dynamic buffer for fd_set to avoid depending on FD_SETSIZE + */ + +struct fd_buf { + fd_set *set; + int alloc_bytes; +}; + +static void fdbuf_zero(struct fd_buf *buf) +{ + if (buf->set) + memset(buf->set, 0, buf->alloc_bytes); +} + +static bool fdbuf_resize(struct fd_buf *buf, int fd) +{ + /* get some extra room for quaranteed alignment */ + int need_bytes = fd/8 + 32; + /* default - 2048 fds */ + int alloc = 256; + uint8 *ptr; + + if (buf->alloc_bytes < need_bytes) + { + while (alloc < need_bytes) + alloc *= 2; + + if (!buf->set) + ptr = malloc(alloc); + else + ptr = realloc(buf->set, alloc); + + if (!ptr) + return false; + + /* clean new area */ + memset(ptr + buf->alloc_bytes, 0, alloc - buf->alloc_bytes); + + buf->set = (fd_set *)ptr; + buf->alloc_bytes = alloc; + } + return true; +} + +int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms) +{ + static struct fd_buf readfds = { NULL, 0 }; + static struct fd_buf writefds = { NULL, 0 }; + + struct pollfd *pf; + int i, fd_max = 0; + int res; + struct timeval *tv = NULL; + struct timeval tvreal; + + fdbuf_zero(&readfds); + fdbuf_zero(&writefds); + + for (i = 0; i < nfds; i++) + { + pf = fds + i; + if (pf->fd < 0) + goto badf; + + /* sets must be equal size */ + if (!fdbuf_resize(&readfds, pf->fd)) + goto nomem; + if (!fdbuf_resize(&writefds, pf->fd)) + goto nomem; + + if (pf->events & POLLIN) + FD_SET(pf->fd, readfds.set); + if (pf->events & POLLOUT) + FD_SET(pf->fd, writefds.set); + if (pf->fd > fd_max) + fd_max = pf->fd; + } + + if (timeout_ms >= 0) + { + tvreal.tv_sec = timeout_ms / 1000; + tvreal.tv_usec = (timeout_ms % 1000) * 1000; + tv = &tvreal; + } + + res = select(fd_max + 1, readfds.set, writefds.set, NULL, tv); + if (res <= 0) + return res; + + for (i = 0; i < nfds; i++) + { + pf = fds + i; + pf->revents = 0; + if ((pf->events & POLLIN) && FD_ISSET(pf->fd, readfds.set)) + pf->revents |= POLLIN; + if ((pf->events & POLLOUT) && FD_ISSET(pf->fd, writefds.set)) + pf->revents |= POLLOUT; + } + + /* select() may count differently than poll()? */ + return res; + +nomem: + errno = ENOMEM; + return -1; + +badf: + errno = EBADF; + return -1; +} + +#endif /* PLPROXY_POLL_COMPAT */ + diff --git a/src/poll_compat.h b/src/poll_compat.h index 0a016b9..dccc97f 100644 --- a/src/poll_compat.h +++ b/src/poll_compat.h @@ -1,23 +1,43 @@ -#ifdef HAVE_POLL_H +#ifndef POLL_COMPAT_H +#define POLL_COMPAT_H -#include +#define PLPROXY_POLL_COMPAT +#include + +/* see if real poll() can be used */ +#ifndef PLPROXY_POLL_COMPAT +#ifdef HAVE_POLL_H +#include #else #ifdef HAVE_SYS_POLL_H - #include - #else - -#include - -#define POLLIN (1 << 0) -#define POLLOUT (1 << 1) -#define POLLHUP (1 << 2) - -#define pollfd compat_pollfd -#define poll compat_poll +#define PLPROXY_POLL_COMPAT +#endif +#endif +#endif + +/* + * Emulate poll() with select(), if needed. + */ +#ifdef PLPROXY_POLL_COMPAT + +/* in/out event types */ +#define POLLIN (1 << 0) +#define POLLOUT (1 << 1) + +/* rest are unused in this implementation */ +#define POLLHUP (1 << 2) +#define POLLPRI (1 << 3) +#define POLLNVAL (1 << 4) +#define POLLERR (1 << 5) + +/* avoid namespace conflicts */ +#define pollfd plproxy_compat_pollfd +#define poll plproxy_compat_poll +#define nfds_t plproxy_compat_nfds_t struct pollfd { int fd; @@ -25,56 +45,11 @@ struct pollfd { short revents; }; -static int poll(struct pollfd *fds, unsigned nfds, int timeout_ms) -{ - struct pollfd *pf; - int i, fd_max = 0; - int res; - fd_set r_set, w_set; - - FD_ZERO(&r_set); - FD_ZERO(&w_set); - for (i = 0; i < nfds; i++) { - pf = fds + i; - if (pf->fd < 0 || pf->fd >= FD_SETSIZE) - { - /* give different errno for FD_SETSIZE to allow detect it */ - errno = (pf->fd < 0) ? EBADF : EFAULT; - return -1; - } - if (pf->events & POLLIN) - FD_SET(pf->fd, &r_set); - if (pf->events & POLLOUT) - FD_SET(pf->fd, &w_set); - if (pf->fd > fd_max) - fd_max = pf->fd; - } - - if (timeout_ms >= 0) - { - struct timeval tv; - tv.tv_sec = timeout_ms / 1000; - tv.tv_usec = timeout_ms % 1000; - res = select(fd_max + 1, &r_set, &w_set, NULL, &tv); - } else - res = select(fd_max + 1, &r_set, &w_set, NULL, NULL); - - if (res <= 0) - return res; - - for (i = 0; i < nfds; i++) { - pf = fds + i; - pf->revents = 0; - if ((pf->events & POLLIN) && FD_ISSET(pf->fd, &r_set)) - pf->revents |= POLLIN; - if ((pf->events & POLLOUT) && FD_ISSET(pf->fd, &w_set)) - pf->revents |= POLLOUT; - } +typedef unsigned long nfds_t; - return res; -} +int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms); -#endif /* !HAVE_SYS_POLL_H */ -#endif /* !HAVE_POLL_H */ +#endif /* PLPROXY_POLL_COMPAT */ +#endif /* POLL_COMPAT_H */ -- 2.39.5