void read_response(Connection *connection, Statistics *stats, char *buffer, int buffer_len) { int bytes_read = 0, bad_count = 0, msg_count = 0, close_count = 0; bytes_read = read(connection->sd, buffer, buffer_len - 1); if (bytes_read < 0) { error("Error reading from socket for connection %d\n", connection->index); stats->connections--; reopen_connection(connection); return; } if (bytes_read == 0) { // server disconnected us // reconnect info("Server disconnected as requested %d.\n", connection->index); stats->connections--; reopen_connection(connection); return; } stats->bytes_read += bytes_read; buffer[bytes_read] = '\0'; debug("Read %d bytes\n", bytes_read); trace("Read Message: %s\n", buffer); bad_count = count_strinstr(buffer, "HTTP/1.1 4"); bad_count += count_strinstr(buffer, "HTTP/1.1 5"); if (bad_count > 0) { info("Recevied error. Buffer is %s\n", buffer); stats->connections--; reopen_connection(connection); return; } msg_count = count_strinstr(buffer, "**MSG**"); stats->messages += msg_count; if ((close_count = count_strinstr(buffer, "**CLOSE**")) > 0) { connection->channel_count += close_count; info("%d Channel(s) has(have) been closed by server.\n", close_count); if (connection->channel_count >= (connection->channel_end - connection->channel_start + 1)) { info("Connection %d will be closed \n", connection->index); close_connection(connection); stats->connections--; } } }
void read_response(Connection *connection, Statistics *stats, char *buffer, int buffer_len) { int bytes_read = 0, bad_count = 0, ok_count = 0; bytes_read = read(connection->sd, buffer, buffer_len - 1); if (bytes_read < 0) { error("Error reading from socket for connection %d\n", connection->index); reopen_connection(connection); return; } if (bytes_read == 0) { // server disconnected us // reconnect info("Server disconnected as requested %d.\n", connection->index); close_connection(connection); return; } stats->bytes_read += bytes_read; buffer[bytes_read] = '\0'; debug("Read %d bytes\n", bytes_read); trace("Read Message: %s\n", buffer); bad_count = count_strinstr(buffer, "HTTP/1.1 4"); bad_count += count_strinstr(buffer, "HTTP/1.1 5"); if (bad_count > 0) { info("Recevied error. Buffer is %s\n", buffer); reopen_connection(connection); return; } ok_count = count_strinstr(buffer, "HTTP/1.1 200 OK"); stats->messages += ok_count; }
void subscribe_channels(Connection *connection, Statistics *stats) { char buffer[BUFFER_SIZE]; int len = 0, bytes_written = 0; long i = 0; len = sprintf(buffer, "GET /sub"); for (i = connection->channel_start; i <= connection->channel_end; i++) { len += sprintf(buffer + len, "/my_channel_%ld", i); } len += sprintf(buffer + len, "?conn=%d HTTP/1.1\r\nHost: loadtest\r\n\r\n", connection->index); if (write_connection(connection, stats, buffer, len) == EXIT_FAILURE) { stats->connections--; reopen_connection(connection); return; } }
void write_message(Connection *connection, Statistics *stats) { char buffer[BUFFER_SIZE]; int len = 0, bytes_written = 0; if ((connection->channel_id <= connection->channel_start) || (connection->channel_id > connection->channel_end)) { connection->channel_id = connection->channel_start; connection->message_count++; // gives a message payload of 140 bytes connection->content_length = sprintf(connection->content_buffer, "**MSG** msg=%06d 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", connection->message_count); connection->content_buffer[connection->content_length] = '\0'; } len = sprintf(buffer, "POST /pub?id=my_channel_%ld HTTP/1.1\r\nHost: loadtest\r\nContent-Length: %d\r\n\r\n%s", connection->channel_id, connection->content_length, connection->content_buffer); if (write_connection(connection, stats, buffer, len) == EXIT_FAILURE) { reopen_connection(connection); return; } connection->channel_id++; }
int main_program(int num_channels, int num_connections, const char *server_hostname, int server_port, int timeout) { struct sockaddr_in server_address; int main_sd = -1, num_events = 0, i, j, event_mask, channels_per_connection, num, start_time = 0, iters_to_next_summary = 0; Connection *connections = NULL, *connection; Statistics stats = {0,0,0,0,0}; int exitcode = EXIT_SUCCESS; struct epoll_event events[MAX_EVENTS]; char buffer[BIG_BUFFER_SIZE]; info("Subscriber starting up\n"); info("Subscriber: %d connections to %d channels on server: %s:%d\n", num_connections, num_channels, server_hostname, server_port); if ((fill_server_address(server_hostname, server_port, &server_address)) != 0) { error2("ERROR host name not found\n"); } if ((main_sd = epoll_create(200 /* this size is not used on Linux kernel 2.6.8+ */)) < 0) { error3("Failed %d creating main epoll socket\n", errno); } if ((connections = init_connections(num_connections, &server_address, main_sd)) == NULL) { error2("Failed to create to connections\n"); } stats.requested_connections = num_connections; for (i = 0; i < num_connections; i++) { connections[i].channel_start = 0; connections[i].channel_end = num_channels - 1; } // infinite loop debug("Entering Infinite Loop\n"); iters_to_next_summary = ITERATIONS_TILL_SUMMARY_PER_TIMEOUT/timeout; for(;;) { if ((num_events = epoll_wait(main_sd, events, MAX_EVENTS, timeout)) < 0) { error3("epoll_wait failed\n"); } for (i = 0; i < num_events; i++) { event_mask = events[i].events; connection = (Connection *)(events[i].data.ptr); if (event_mask & EPOLLHUP) { // SERVER HUNG UP debug("EPOLLHUP\n"); info("Server hung up on conncetion %d. Reconecting...\n", connection->index); sleep(1); stats.connections--; reopen_connection(connection); continue; } if (event_mask & EPOLLERR) { debug("EPOLLERR\n"); info("Server returned an error on connection %d. Reconecting...\n", connection->index); stats.connections--; reopen_connection(connection); continue; } if (event_mask & EPOLLIN) { // READ debug("----------READ AVAILABLE-------\n"); if (connection->state == CONNECTED) { read_response(connection, &stats, buffer, BIG_BUFFER_SIZE); } } if (event_mask & EPOLLOUT) { // WRITE debug("----------WRITE AVAILABLE-------\n"); if (start_time == 0) { start_time = time(NULL); } if (connection->state == CONNECTING) { connection->state = CONNECTED; stats.connections++; debug("Connection opened for index=%d\n", connection->index); subscribe_channels(connection, &stats); // remove write flag from event if (change_connection(connection, EPOLLIN | EPOLLHUP) < 0) { error2("Failed creating socket for connection = %d\n", connection->index); } } } } if ((iters_to_next_summary-- <= 0)) { iters_to_next_summary = ITERATIONS_TILL_SUMMARY_PER_TIMEOUT/timeout; summary("Connections=%ld, Messages=%ld BytesRead=%ld Msg/Sec=%0.2f\n", stats.connections, stats.messages, stats.bytes_read, calc_message_per_second(stats.messages, start_time)); } if (stats.connections == 0) { num = 0; for (j = 0; j < num_connections; j++) { if (connections[i].state != CLOSED) { num++; break; } } if (num == 0) { exitcode = EXIT_SUCCESS; goto exit; } } } exit: if (connections != NULL) free(connections); return exitcode; }