static void server_can_accept(int fd, short event, void *ptr) { struct server *s = ptr; struct worker *w; struct http_client *c; int client_fd; struct sockaddr_in addr; socklen_t addr_sz = sizeof(addr); char on = 1; (void)event; /* select worker to send the client to */ w = s->w[s->next_worker]; /* accept client */ client_fd = accept(fd, (struct sockaddr*)&addr, &addr_sz); /* make non-blocking */ ioctl(client_fd, (int)FIONBIO, (char *)&on); /* create client and send to worker. */ if(client_fd > 0) { c = http_client_new(w, client_fd, addr.sin_addr.s_addr); worker_add_client(w, c); /* loop over ring of workers */ s->next_worker = (s->next_worker + 1) % s->cfg->http_threads; } else { /* too many connections */ slog(s, WEBDIS_NOTICE, "Too many connections", 0); } }
int client_change_worker (client_t *client, worker_t *dest_worker) { if (dest_worker->running == 0) return 0; client->next_on_worker = NULL; thread_spin_lock (&dest_worker->lock); worker_add_client (dest_worker, client); thread_spin_unlock (&dest_worker->lock); worker_wakeup (dest_worker); return 1; }
void client_add_incoming (client_t *client) { worker_t *handler; thread_rwlock_rlock (&workers_lock); handler = worker_incoming; thread_spin_lock (&handler->lock); thread_rwlock_unlock (&workers_lock); worker_add_client (handler, client); thread_spin_unlock (&handler->lock); worker_wakeup (handler); }
void client_add_worker (client_t *client) { worker_t *handler; thread_rwlock_rlock (&workers_lock); /* add client to the handler with the least number of clients */ handler = worker_selected(); thread_spin_lock (&handler->lock); thread_rwlock_unlock (&workers_lock); worker_add_client (handler, client); thread_spin_unlock (&handler->lock); worker_wakeup (handler); }
static void worker_relocate_clients (worker_t *worker) { if (workers == NULL) return; while (worker->count || worker->pending_count) { client_t *client = worker->clients, **prevp = &worker->clients; worker->wakeup_ms = worker->time_ms + 150; worker->current_time.tv_sec = (time_t)(worker->time_ms/1000); while (client) { if (client->flags & CLIENT_ACTIVE) { client->worker = workers; prevp = &client->next_on_worker; } else { *prevp = client->next_on_worker; worker_add_client (worker, client); worker->count--; } client = *prevp; } if (worker->clients) { thread_spin_lock (&workers->lock); *workers->pending_clients_tail = worker->clients; workers->pending_clients_tail = prevp; workers->pending_count += worker->count; thread_spin_unlock (&workers->lock); worker_wakeup (workers); worker->clients = NULL; worker->last_p = &worker->clients; worker->count = 0; } worker_wait (worker); } }