static void _defer(struct gridd_client_pool_s *pool, struct event_client_s *ev) { EXTRA_ASSERT(pool != NULL); EXTRA_ASSERT(pool->vtable == &VTABLE); EXTRA_ASSERT(ev != NULL); EXTRA_ASSERT(pool->pending_clients != NULL); EXTRA_ASSERT(pool->fd_out >= 0); if (pool->closed) { GRID_INFO("Request dropped"); event_client_free(ev); } else { guint8 c = 0; g_async_queue_push(pool->pending_clients, ev); (void) metautils_syscall_write(pool->fd_out, &c, 1); } }
static GError * _client_manage_event_in_buffer(struct gridd_client_s *client, guint8 *d, gsize ds) { ssize_t rc; switch (client->step) { case CONNECTING: g_assert(client->fd >= 0); client->step = client->request ? REQ_SENDING : CONNECTED; return NULL; case REQ_SENDING: client->step = REQ_SENDING; g_get_current_time(&(client->tv_step)); if (!client->request) return NULL; _client_reset_reply(client); /* Continue to send the request */ rc = metautils_syscall_write(client->fd, client->request->data + client->sent_bytes, client->request->len - client->sent_bytes); if (rc < 0) return (errno == EINTR || errno == EAGAIN) ? NULL : NEWERROR(errno, "write error (%s)", strerror(errno)); if (rc > 0) client->sent_bytes += rc; if (client->sent_bytes < client->request->len) return NULL; client->step = REP_READING_SIZE; case REP_READING_SIZE: client->step = REP_READING_SIZE; g_get_current_time(&(client->tv_step)); if (!client->reply) client->reply = g_byte_array_new(); if (client->reply->len < 4) { /* Continue reading the size */ rc = metautils_syscall_read(client->fd, d, ds); if (rc < 0) return (errno == EINTR || errno == EAGAIN) ? NULL : NEWERROR(errno, "read error (%s)", strerror(errno)); if (rc > 0) g_byte_array_append(client->reply, d, rc); if (client->reply->len < 4) { if (!rc) return NEWERROR(errno, "EOF!"); return NULL; } } client->size = l4v_get_size(client->reply->data); case REP_READING_DATA: client->step = REP_READING_DATA; g_get_current_time(&(client->tv_step)); rc = 0; if (client->reply->len < client->size+4) { rc = metautils_syscall_read(client->fd, d, ds); if (rc < 0) return (errno == EINTR || errno == EAGAIN) ? NULL : NEWERROR(errno, "read error (%s)", strerror(errno)); if (rc > 0) g_byte_array_append(client->reply, d, rc); } if (client->reply->len >= client->size+4) { GError *err = _client_manage_reply_data(client); if (err) { client->step = STATUS_FAILED; return err; } else { if (client->step != CONNECTING && client->step != STATUS_FAILED && client->step != STATUS_OK) { client->reply = g_byte_array_remove_range(client->reply, 0, client->size+4); client->step = REP_READING_SIZE; client->size = 0; } } } else if (!rc) return NEWERROR(errno, "EOF!"); return NULL; default: g_assert_not_reached(); return NEWERROR(0, "Invalid state"); } g_assert_not_reached(); return NEWERROR(0, "BUG unreachable code"); }
static GError * _client_manage_event_in_buffer(struct gridd_client_s *client, guint8 *d, gsize ds) { guint32 s32; ssize_t rc; switch (client->step) { case CONNECTING: EXTRA_ASSERT(client->fd >= 0); EXTRA_ASSERT(client->request != NULL); client->step = REQ_SENDING; return NULL; case REQ_SENDING: client->step = REQ_SENDING; if (!client->request) return NULL; _client_reset_reply(client); /* Continue to send the request */ rc = metautils_syscall_write(client->fd, client->request->data + client->sent_bytes, client->request->len - client->sent_bytes); if (rc < 0) return (errno == EINTR || errno == EAGAIN) ? NULL : NEWERROR(errno, "write error (%s)", strerror(errno)); if (rc > 0) client->sent_bytes += rc; if (client->sent_bytes < client->request->len) return NULL; client->step = REP_READING_SIZE; case REP_READING_SIZE: client->step = REP_READING_SIZE; if (!client->reply) client->reply = g_byte_array_new(); if (client->reply->len < 4) { /* Continue reading the size */ rc = metautils_syscall_read(client->fd, d, (4 - client->reply->len)); if (rc < 0) return (errno == EINTR || errno == EAGAIN) ? NULL : NEWERROR(errno, "read error (%s)", strerror(errno)); if (rc > 0) g_byte_array_append(client->reply, d, rc); if (client->reply->len < 4) { if (!rc) return NEWERROR(errno, "EOF!"); return NULL; } } EXTRA_ASSERT (client->reply->len == 4); s32 = *((guint32*)(client->reply->data)); client->size = g_ntohl(s32); case REP_READING_DATA: client->step = REP_READING_DATA; rc = 0; EXTRA_ASSERT (client->reply->len <= client->size + 4); if (client->reply->len < client->size + 4) { gsize remaiming = client->size + 4 - client->reply->len; gsize dmax = ds; if (dmax > remaiming) dmax = remaiming; rc = metautils_syscall_read(client->fd, d, dmax); if (rc < 0) return (errno == EINTR || errno == EAGAIN) ? NULL : NEWERROR(errno, "read error (%s)", strerror(errno)); if (rc > 0) g_byte_array_append(client->reply, d, rc); } EXTRA_ASSERT (client->reply->len <= client->size + 4); if (client->reply->len == client->size + 4) { GError *err = _client_manage_reply_data(client); if (err) { client->step = STATUS_FAILED; return err; } else { if (client->step != CONNECTING && client->step != STATUS_FAILED && client->step != STATUS_OK) { client->reply = g_byte_array_set_size(client->reply, 0); client->step = REP_READING_SIZE; client->size = 0; } } } else if (!rc) return NEWERROR(errno, "EOF!"); return NULL; default: g_assert_not_reached(); return NEWERROR(0, "Invalid state"); } g_assert_not_reached(); return NEWERROR(0, "BUG unreachable code"); }