diff --git a/TODO b/TODO index ced926e..f009e84 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,4 @@ - ssl support - better error reporting - ipv6 support +- progress output diff --git a/src/client.c b/src/client.c index c58f650..098cca4 100644 --- a/src/client.c +++ b/src/client.c @@ -83,19 +83,18 @@ void client_free(Client *client) { static void client_reset(Client *client) { //printf("keep alive: %d\n", client->keepalive); if (!client->keepalive) { - ev_io_stop(client->worker->loop, &client->sock_watcher); - if (client->sock_watcher.fd != -1) { + ev_io_stop(client->worker->loop, &client->sock_watcher); shutdown(client->sock_watcher.fd, SHUT_WR); close(client->sock_watcher.fd); + client->sock_watcher.fd = -1; } - client->sock_watcher.fd = -1; client->state = CLIENT_START; } else { client_set_events(client, EV_WRITE); - client->worker->stats.req_started++; client->state = CLIENT_WRITING; + client->worker->stats.req_started++; } client->parser_state = PARSER_START; @@ -158,12 +157,16 @@ void client_state_machine(Client *client) { //printf("state: %d\n", client->state); switch (client->state) { case CLIENT_START: + client->worker->stats.req_started++; + do { r = socket(config->saddr->ai_family, config->saddr->ai_socktype, config->saddr->ai_protocol); } while (-1 == r && errno == EINTR); if (-1 == r) { client->state = CLIENT_ERROR; + strerror_r(errno, client->buffer, sizeof(client->buffer)); + W_ERROR("socket() failed: %s (%d)", client->buffer, errno); goto start; } @@ -174,8 +177,6 @@ void client_state_machine(Client *client) { ev_io_set(&client->sock_watcher, r, EV_WRITE); ev_io_start(client->worker->loop, &client->sock_watcher); - client->worker->stats.req_started++; - if (!client_connect(client)) { client->state = CLIENT_ERROR; goto start; @@ -257,7 +258,6 @@ void client_state_machine(Client *client) { } } - break; case CLIENT_ERROR: //printf("client error\n"); client->worker->stats.req_error++; @@ -275,9 +275,15 @@ void client_state_machine(Client *client) { client->worker->stats.req_failed++; } + /*if (client->worker->id == 1 && (client->worker->stats.req_started % 10) == 0) + printf("thread: %d, requests done: %"PRIu64", %"PRIu64" todo, %"PRIu64" started\n", + client->worker->id, client->worker->stats.req_done, client->worker->stats.req_todo, + client->worker->stats.req_started);*/ + if (client->worker->stats.req_started == client->worker->stats.req_todo) { /* this worker has started all requests */ - ev_io_stop(client->worker->loop, &client->sock_watcher); + client->keepalive = 0; + client_reset(client); if (client->worker->stats.req_done == client->worker->stats.req_todo) { /* this worker has finished all requests */ diff --git a/src/weighttp.c b/src/weighttp.c index e492045..565564c 100644 --- a/src/weighttp.c +++ b/src/weighttp.c @@ -139,6 +139,20 @@ static char *forge_request(char *url, char keep_alive, char **host, uint16_t *po return req; } +static uint64_t str_to_uint64(char *str) { + uint64_t i; + + for (i = 0; *str; str++) { + if (*str < '0' || *str > '9') + return UINT64_MAX; + + i *= 10; + i += *str - '0'; + } + + return i; +} + int main(int argc, char *argv[]) { Worker **workers; pthread_t *threads; @@ -179,7 +193,7 @@ int main(int argc, char *argv[]) { config.keep_alive = 1; break; case 'n': - config.req_count = atoi(optarg); + config.req_count = str_to_uint64(optarg); break; case 't': config.thread_count = atoi(optarg); @@ -220,7 +234,7 @@ int main(int argc, char *argv[]) { show_help(); return 1; } - if (config.thread_count > config.req_count || config.thread_count > config.concur_count || config.concur_count > config.req_count) { + if (config.req_count == UINT64_MAX || config.thread_count > config.req_count || config.thread_count > config.concur_count || config.concur_count > config.req_count) { W_ERROR("%s", "insane arguments\n"); show_help(); return 1; @@ -259,9 +273,9 @@ int main(int argc, char *argv[]) { stats.ts_start = ev_time(); for (i = 0; i < config.thread_count; i++) { - uint16_t reqs = config.req_count / config.thread_count; + uint64_t reqs = config.req_count / config.thread_count; uint16_t concur = config.concur_count / config.thread_count; - uint16_t diff; + uint64_t diff; if (rest_concur) { diff = (i == config.thread_count) ? rest_concur : (rest_concur / config.thread_count); @@ -276,15 +290,15 @@ int main(int argc, char *argv[]) { reqs += diff; rest_req -= diff; } + printf("spawning thread #%d: %"PRIu16" concurrent requests, %"PRIu64" total requests\n", i+1, concur, reqs); + workers[i] = worker_new(i+1, &config, concur, reqs); - workers[i] = worker = worker_new(i+1, &config, concur, reqs); - - if (!worker) { + if (!(workers[i])) { W_ERROR("%s", "failed to allocate worker or client"); return 1; } - err = pthread_create(&threads[i], NULL, worker_thread, (void*)worker); + err = pthread_create(&threads[i], NULL, worker_thread, (void*)workers[i]); if (err != 0) { W_ERROR("failed spawning thread (%d)", err);