static void _manage_requests(struct gridd_client_pool_s *pool) { struct event_client_s *ec; EXTRA_ASSERT(pool != NULL); while (pool->active_count < pool->active_max) { ec = g_async_queue_try_pop(pool->pending_clients); if (NULL == ec) return; EXTRA_ASSERT(ec->client != NULL); if (!gridd_client_start(ec->client)) { GError *err = gridd_client_error(ec->client); if (NULL != err) { GRID_WARN("STARTUP Client fd=%d [%s] : (%d) %s", gridd_client_fd(ec->client), gridd_client_url(ec->client), err->code, err->message); g_clear_error(&err); } else { GRID_WARN("STARTUP Client fd=%d [%s] : already started", gridd_client_fd(ec->client), gridd_client_url(ec->client)); EXTRA_ASSERT(err != NULL); } event_client_free(ec); } else if (!event_client_monitor(pool, ec)) event_client_free(ec); } }
static void _manage_timeouts(struct gridd_client_pool_s *pool) { GTimeVal now; struct event_client_s *ec; if (pool->active_count <= 0) return; g_get_current_time(&now); if (pool->last_timeout_check == now.tv_sec) return; for (int i=0; i<pool->active_clients_size ;i++) { if (!(ec = pool->active_clients[i])) continue; EXTRA_ASSERT(ec->client != NULL); EXTRA_ASSERT(i == gridd_client_fd(ec->client)); if (gridd_client_expired(ec->client, &now)) { GRID_INFO("EXPIRED Client fd=%d [%s]", i, gridd_client_url(ec->client)); _pool_unmonitor(pool, i); event_client_free(ec); } } }
static int event_client_monitor(struct gridd_client_pool_s *pool, struct event_client_s *mc) { int fd, rc, interest; struct epoll_event ev; EXTRA_ASSERT(pool != NULL); EXTRA_ASSERT(mc != NULL); EXTRA_ASSERT(mc->client != NULL); memset(&ev, 0, sizeof(ev)); interest = gridd_client_interest(mc->client); if (interest & CLIENT_RD) ev.events |= EPOLLIN; if (interest & CLIENT_WR) ev.events |= EPOLLOUT; EXTRA_ASSERT(ev.events != 0); ev.events |= (EPOLLHUP|EPOLLERR|EPOLLONESHOT); ev.data.fd = fd = gridd_client_fd(mc->client); EXTRA_ASSERT(fd >= 0); rc = epoll_ctl(pool->fdmon, EPOLL_CTL_ADD, fd, &ev); if (rc < 0) { pool->active_clients[fd] = NULL; GRID_WARN("MONITOR error: (%d) %s", errno, strerror(errno)); return 0; } pool->active_count ++; pool->active_clients[fd] = mc; return 1; }
static void _manage_one_event(struct gridd_client_pool_s *pool, int fd, int evt) { struct event_client_s *ec = pool->active_clients[fd]; _pool_unmonitor(pool, fd); EXTRA_ASSERT(ec != NULL); EXTRA_ASSERT(ec->client != NULL); EXTRA_ASSERT(fd == gridd_client_fd(ec->client)); if ((evt & EPOLLERR) || (evt & EPOLLHUP)) { GRID_DEBUG("%s CLIENT [%s] fd=%d cnx error", __FUNCTION__, gridd_client_url(ec->client), gridd_client_fd(ec->client)); event_client_free(ec); } else { gridd_client_react(ec->client); if (gridd_client_finished(ec->client)) event_client_free(ec); else if (!event_client_monitor(pool, ec)) event_client_free(ec); } }
static inline int _client_to_pollfd(struct client_s *client, struct pollfd *pfd) { int fd = gridd_client_fd(client); int interest = gridd_client_interest(client); if (fd < 0 || !interest) return 0; pfd->fd = fd; pfd->events = 0; pfd->revents = 0; if (interest & CLIENT_WR) pfd->events = POLLOUT; if (interest & CLIENT_RD) pfd->events = POLLIN; return 1; }
void gridd_clients_start(struct client_s **clients) { if (unlikely(NULL == clients)) return; for (; *clients ;++clients) { if (gridd_client_start(*clients)) continue; GError *err = gridd_client_error(*clients); GRID_WARN("STARTUP failed fd=%d [%s] : (%d) %s", gridd_client_fd(*clients), gridd_client_url(*clients), err ? err->code : 0, err ? err->message : "?"); if (err) g_clear_error(&err); } }
GError * gridd_clients_step(struct client_s **clients) { struct client_s ** _lookup_client(int fd, struct client_s **ppc) { struct client_s *c; for (; (c = *ppc) ;ppc++) { if (gridd_client_fd(c) == fd) return ppc; } return ppc; } guint i, j; int rc; struct client_s *last, **plast; GTimeVal now; 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; /* Wait for an event to happen */ if (!(rc = poll(pfd, j, 100))) { g_get_current_time(&now); _clients_expire(clients, &now); return NULL; } if (rc < 0) 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 */ g_get_current_time(&now); _clients_expire(clients, &now); return NULL; }