GError* gridd_client_step(struct client_s *client) { struct pollfd pfd = {-1, 0, 0}; if (!_client_to_pollfd(client, &pfd)) { return NULL; } int rc = metautils_syscall_poll(&pfd, 1, 1000); if (rc == 0) { GTimeVal now; g_get_current_time(&now); gridd_client_expire(client, &now); return NULL; } if (rc < 0) return NEWERROR(errno, "poll errno=%d %s", errno, strerror(errno)); if (pfd.revents & POLLERR) { GError *err = socket_get_error(pfd.fd); g_prefix_error(&err, "%s: ", gridd_client_url(client)); gridd_client_fail(client, err); g_clear_error(&err); } else gridd_client_react(client); return NULL; }
GError* gridd_client_step(struct gridd_client_s *client) { int rc; struct pollfd pfd = {-1, 0, 0}; if (!_client_to_pollfd(client, &pfd)) return NULL; retry: rc = metautils_syscall_poll(&pfd, 1, 1000); if (rc == 0) { gridd_client_expire(client, oio_ext_monotonic_time ()); return NULL; } if (rc < 0) { if (errno == EINTR) goto retry; return NEWERROR(errno, "poll errno=%d %s", errno, strerror(errno)); } if (pfd.revents & POLLERR) { GError *err = socket_get_error(pfd.fd); g_prefix_error(&err, "%s: ", gridd_client_url(client)); gridd_client_fail(client, err); g_clear_error(&err); } else if (pfd.revents & (POLLIN|POLLOUT)) { gridd_client_react(client); } return NULL; }
static int _send (int fd, struct iovec *iov, unsigned int iovcount) { int w; retry: w = writev (fd, iov, iovcount); if (w < 0) { if (errno == EINTR) goto retry; if (errno == EAGAIN || errno == EWOULDBLOCK) { struct pollfd pfd = {0}; pfd.fd = fd; pfd.events = POLLOUT; metautils_syscall_poll (&pfd, 1, 1000); goto retry; } GRID_WARN("BEANSTALKD failed to put: [errno=%d] %s", errno, strerror(errno)); return 0; } while (w > 0 && iovcount > 0) { if (iov[0].iov_len <= (size_t)w) { w -= iov[0].iov_len; iov[0].iov_len = 0; iov ++; iovcount --; } else { iov[0].iov_len -= w; w = 0; } } if (iovcount > 0) goto retry; GRID_TRACE("BEANSTALKD put sent!"); return 1; }
gint sock_to_read(int fd, gint ms, void *buf, gsize bufSize, GError ** err) { if (VTABLE.to_read) return VTABLE.to_read(fd, ms, buf, bufSize, err); #define READ() do { \ rc = metautils_syscall_read(fd, buf, bufSize); \ if (rc > 0) \ return rc; \ if (rc == 0) { \ GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket %d closed", fd); \ return 0; \ } \ if (errno != EAGAIN && errno != EINTR) { \ GSETCODE(err, errno_to_errcode(errno), "Read error (%s)", strerror(errno)); \ return -1; \ } \ } while (0) gint rc; if (fd < 0 || !buf || bufSize <= 0) { GSETERROR(err, "invalid parameter"); return -1; } /* on tente un premier READ, qui s'il reussit, nous epargne un appel a POLL */ READ(); /* pas de data en attente, donc attente protegee par le poll */ for (;;) { struct pollfd p; p.fd = fd; p.events = POLLIN; p.revents = 0; /*wait for something to happen */ rc = metautils_syscall_poll(&p, 1, ms); if (rc == 0) { /*timeout */ GSETCODE(err, ERRCODE_CONN_TIMEOUT, "Socket timeout"); return -1; } if (rc < 0 && errno != EINTR) { /*error */ GSETCODE(err, errno_to_errcode(errno), "Socket error (%s)", strerror(errno)); return -1; } if (rc == 1) { if (p.revents & POLLHUP && !(p.revents & POLLIN)) { GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket %d closed", fd); return 0; } if (p.revents & POLLERR) { int sock_err = socket_get_errcode(fd); GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket %d error : (%d) %s", fd, sock_err, strerror(sock_err)); return 0; } READ(); } } }
gint sock_to_write(int fd, gint ms, void *buf, gsize bufSize, GError ** err) { if (VTABLE.to_write) return VTABLE.to_write(fd, ms, buf, bufSize, err); #define WRITE() do { \ written = metautils_syscall_write(fd, ((guint8 *)buf) + nbSent, bufSize - nbSent); \ if (written > 0) { \ ui_written = written; \ nbSent += ui_written; \ } \ if (written < 0) { \ if (errno != EAGAIN && errno != EINTR) { \ GSETERROR(err, "Write error (%s)", strerror(errno)); \ return -1; \ } \ } \ } while (0) gsize ui_written; ssize_t written; gsize nbSent = 0; if (fd < 0 || !buf || bufSize <= 0) { GSETERROR(err, "invalid parameter"); return -1; } WRITE(); while (nbSent < bufSize) { int rc_poll; struct pollfd p; p.fd = fd; p.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL; p.revents = 0; errno = 0; rc_poll = metautils_syscall_poll(&p, 1, ms); if (rc_poll == 0) { /*timeout */ GSETCODE(err, ERRCODE_CONN_TIMEOUT, "Socket timeout"); return (-1); } if (rc_poll == -1) { /*poll error */ if (errno != EINTR) { GSETERROR(err, "Socket error (%s) after %"G_GSIZE_FORMAT" bytes written", strerror(errno), nbSent); return (-1); } else { TRACE("poll interrupted (%s)", strerror(errno)); continue; } } /*poll success */ if (p.revents & POLLNVAL) { GSETERROR(err, "Socket (%d) is invalid after %"G_GSIZE_FORMAT" bytes sent", fd, nbSent); return -1; } if (p.revents & POLLERR) { int sock_err = socket_get_errcode(fd); GSETERROR(err, "Socket (%d) error after %"G_GSIZE_FORMAT" bytes written : (%d) %s", fd, nbSent, sock_err, strerror(sock_err)); return -1; } if ((p.revents & POLLHUP)) { GSETCODE(err, ERRCODE_CONN_CLOSED, "Socket (%d) closed after %"G_GSIZE_FORMAT" bytes written", fd, nbSent); return -1; } WRITE(); } return nbSent; }
GError * gridd_clients_step(struct gridd_client_s **clients) { struct gridd_client_s ** _lookup_client(int fd, struct gridd_client_s **ppc) { struct gridd_client_s *c; for (; (c = *ppc) ;ppc++) { if (gridd_client_fd(c) == fd) return ppc; } return ppc; } guint i, j; int rc; struct gridd_client_s *last, **plast; guint nbclients; EXTRA_ASSERT(clients != NULL); nbclients = g_strv_length((gchar**)clients); EXTRA_ASSERT(nbclients > 0); struct pollfd pfd[nbclients]; for (j=0,plast=clients; NULL != (last = *plast) ;plast++) { if (_client_to_pollfd(last, pfd+j)) j++; } if (!j) return NULL; retry: /* Wait for an event to happen */ rc = metautils_syscall_poll (pfd, j, 100); if (rc == 0) { _clients_expire(clients, oio_ext_monotonic_time ()); return NULL; } if (rc < 0) { if (errno == EINTR) goto retry; return NEWERROR(errno, "poll error (%s)", strerror(errno)); } /* Then manage each event */ for (plast=clients,i=0; i<j ;i++) { if (!pfd[i].revents) continue; /* Find the client for this pollfd */ plast = _lookup_client(pfd[i].fd, plast); EXTRA_ASSERT(plast != NULL); last = *plast; /* Manage the poll() event */ if (pfd[i].revents & POLLERR) { GError *err = socket_get_error(pfd[i].fd); g_prefix_error(&err, "%s: ", gridd_client_url(last)); gridd_client_fail(last, err); g_clear_error(&err); } else gridd_client_react(last); } /* Now check for expired clients */ _clients_expire(clients, oio_ext_monotonic_time ()); return NULL; }