bool client::send_conn_setup_commands(void) { bool sent = false; if (m_config->authenticate && m_authentication != auth_done) { if (m_authentication == auth_none) { benchmark_debug_log("sending authentication command.\n"); m_protocol->authenticate(m_config->authenticate); m_pipeline.push(new client::request(rt_auth, 0, NULL, 0)); m_authentication = auth_sent; sent = true; } } if (m_config->select_db && m_db_selection != select_done) { if (m_db_selection == select_none) { benchmark_debug_log("sending db selection command.\n"); m_protocol->select_db(m_config->select_db); m_pipeline.push(new client::request(rt_select_db, 0, NULL, 0)); m_db_selection = select_sent; sent = true; } } return sent; }
void verify_client::handle_response(request *request, protocol_response *response) { unsigned int rvalue_len; const char *rvalue = response->get_value(&rvalue_len); verify_request *vr = static_cast<verify_request *>(request); assert(vr->m_type == rt_get); if (response->is_error()) { benchmark_error_log("error: request for key [%.*s] failed: %s\n", vr->m_key_len, vr->m_key, response->get_status()); m_errors++; } else { if (!rvalue || rvalue_len != vr->m_value_len || memcmp(rvalue, vr->m_value, rvalue_len) != 0) { benchmark_error_log("error: key [%.*s]: expected [%.*s], got [%.*s]\n", vr->m_key_len, vr->m_key, vr->m_value_len, vr->m_value, rvalue_len, rvalue); m_errors++; } else { benchmark_debug_log("key: [%.*s] verified successfuly.\n", vr->m_key_len, vr->m_key); m_verified_keys++; } } }
void shard_connection::send_get_command(struct timeval* sent_time, const char *key, int key_len, unsigned int offset) { int cmd_size = 0; benchmark_debug_log("GET key=[%.*s]\n", key_len, key); cmd_size = m_protocol->write_command_get(key, key_len, offset); push_req(new request(rt_get, cmd_size, sent_time, 1)); }
void shard_connection::send_wait_command(struct timeval* sent_time, unsigned int num_slaves, unsigned int timeout) { int cmd_size = 0; benchmark_debug_log("WAIT num_slaves=%u timeout=%u\n", num_slaves, timeout); cmd_size = m_protocol->write_command_wait(num_slaves, timeout); push_req(new request(rt_wait, cmd_size, sent_time, 0)); }
void shard_connection::send_verify_get_command(struct timeval* sent_time, const char *key, int key_len, const char *value, int value_len, int expiry, unsigned int offset) { int cmd_size = 0; benchmark_debug_log("GET key=[%.*s] value_len=%u expiry=%u\n", key_len, key, value_len, expiry); cmd_size = m_protocol->write_command_get(key, key_len, offset); push_req(new verify_request(rt_get, cmd_size, sent_time, 1, key, key_len, value, value_len)); }
void shard_connection::send_conn_setup_commands(struct timeval timestamp) { if (m_authentication == auth_none) { benchmark_debug_log("sending authentication command.\n"); m_protocol->authenticate(m_config->authenticate); push_req(new request(rt_auth, 0, ×tamp, 0)); m_authentication = auth_sent; } if (m_db_selection == select_none) { benchmark_debug_log("sending db selection command.\n"); m_protocol->select_db(m_config->select_db); push_req(new request(rt_select_db, 0, ×tamp, 0)); m_db_selection = select_sent; } if (m_cluster_slots == slots_none) { benchmark_debug_log("sending cluster slots command.\n"); m_protocol->write_command_cluster_slots(); push_req(new request(rt_cluster_slots, 0, ×tamp, 0)); m_cluster_slots = slots_sent; } }
void run_stats::debug_dump(void) { benchmark_debug_log("run_stats: start_time={%u,%u} end_time={%u,%u}\n", m_start_time.tv_sec, m_start_time.tv_usec, m_end_time.tv_sec, m_end_time.tv_usec); for (std::vector<one_second_stats>::iterator i = m_stats.begin(); i != m_stats.end(); i++) { benchmark_debug_log(" %u: get latency=%u.%ums, set latency=%u.%ums, wait latency=%u.%ums" "m_ops_set/get/wait=%u/%u/%u, m_bytes_set/get=%u/%u, m_get_hit/miss=%u/%u\n", i->m_second, USEC_FORMAT(AVERAGE(i->m_total_get_latency, i->m_ops_get)), USEC_FORMAT(AVERAGE(i->m_total_set_latency, i->m_ops_set)), USEC_FORMAT(AVERAGE(i->m_total_wait_latency, i->m_ops_wait)), i->m_ops_set, i->m_ops_get, i->m_ops_wait, i->m_bytes_set, i->m_bytes_get, i->m_get_hits, i->m_get_misses); } for( latency_map_itr it = m_get_latency_map.begin() ; it != m_get_latency_map.end() ; it++) { if (it->second) benchmark_debug_log(" GET <= %u msec: %u\n", it->first, it->second); } for( latency_map_itr it = m_set_latency_map.begin() ; it != m_set_latency_map.end() ; it++) { if (it->second) benchmark_debug_log(" SET <= %u msec: %u\n", it->first, it->second); } for( latency_map_itr it = m_wait_latency_map.begin() ; it != m_wait_latency_map.end() ; it++) { if (it->second) benchmark_debug_log(" WAIT <= %u msec: %u\n", it->first, it->second); } }
void shard_connection::send_mget_command(struct timeval* sent_time, const keylist* key_list) { int cmd_size = 0; const char *first_key, *last_key; unsigned int first_key_len, last_key_len; first_key = key_list->get_key(0, &first_key_len); last_key = key_list->get_key(key_list->get_keys_count()-1, &last_key_len); benchmark_debug_log("MGET %d keys [%.*s] .. [%.*s]\n", key_list->get_keys_count(), first_key_len, first_key, last_key_len, last_key); cmd_size = m_protocol->write_command_multi_get(key_list); push_req(new request(rt_get, cmd_size, sent_time, key_list->get_keys_count())); }
client::client(client_group* group) : m_sockfd(-1), m_unix_sockaddr(NULL), m_event(NULL), m_event_base(NULL), m_read_buf(NULL), m_write_buf(NULL), m_initialized(false), m_connected(false), m_authentication(auth_none), m_db_selection(select_none), m_config(NULL), m_protocol(NULL), m_obj_gen(NULL), m_reqs_processed(0), m_set_ratio_count(0), m_get_ratio_count(0) { m_event_base = group->get_event_base(); if (!setup_client(group->get_config(), group->get_protocol(), group->get_obj_gen())) { return; } benchmark_debug_log("new client %p successfully set up.\n", this); m_initialized = true; }
client::client(struct event_base *event_base, benchmark_config *config, abstract_protocol *protocol, object_generator *obj_gen) : m_sockfd(-1), m_unix_sockaddr(NULL), m_event(NULL), m_event_base(NULL), m_read_buf(NULL), m_write_buf(NULL), m_initialized(false), m_connected(false), m_authentication(auth_none), m_db_selection(select_none), m_config(NULL), m_protocol(NULL), m_obj_gen(NULL), m_reqs_processed(0), m_set_ratio_count(0), m_get_ratio_count(0), m_tot_set_ops(0), m_tot_wait_ops(0) { m_event_base = event_base; if (!setup_client(config, protocol, obj_gen)) { return; } benchmark_debug_log("new client %p successfully set up.\n", this); m_initialized = true; }
void shard_connection::handle_event(short evtype) { // connect() returning to us? normally we expect EV_WRITE, but for UNIX domain // sockets we workaround since connect() returned immediately, but we don't want // to do any I/O from the client::connect() call... if (!m_connected && (evtype == EV_WRITE || m_unix_sockaddr != NULL)) { int error = -1; socklen_t errsz = sizeof(error); if (getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, (void *) &error, &errsz) == -1) { benchmark_error_log("connect: error getting connect response (getsockopt): %s\n", strerror(errno)); return; } if (error != 0) { benchmark_error_log("connect: connection failed: %s\n", strerror(error)); return; } m_connected = true; if (!m_conns_manager->get_reqs_processed()) { process_first_request(); } else { benchmark_debug_log("reconnection complete, proceeding with test\n"); fill_pipeline(); } } assert(m_connected == true); if ((evtype & EV_WRITE) == EV_WRITE && evbuffer_get_length(m_write_buf) > 0) { if (evbuffer_write(m_write_buf, m_sockfd) < 0) { if (errno != EWOULDBLOCK) { benchmark_error_log("write error: %s\n", strerror(errno)); disconnect(); return; } } } if ((evtype & EV_READ) == EV_READ) { int ret = 1; while (ret > 0) { ret = evbuffer_read(m_read_buf, m_sockfd, -1); } if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { benchmark_error_log("read error: %s\n", strerror(errno)); disconnect(); return; } if (ret == 0) { benchmark_error_log("connection dropped.\n"); disconnect(); return; } if (evbuffer_get_length(m_read_buf) > 0) { process_response(); // process_response may have disconnected, in which case // we just abort and wait for libevent to call us back sometime if (!m_connected) { return; } } } // update event short new_evtype = 0; if (m_pending_resp) { new_evtype = EV_READ; } if (evbuffer_get_length(m_write_buf) > 0) { assert(!m_conns_manager->finished()); new_evtype |= EV_WRITE; } if (new_evtype) { int ret = event_assign(m_event, m_event_base, m_sockfd, new_evtype, cluster_client_event_handler, (void *)this); assert(ret == 0); ret = event_add(m_event, NULL); assert(ret == 0); } else if (m_conns_manager->finished()) { m_conns_manager->set_end_time(); } }
void shard_connection::process_response(void) { int ret; bool responses_handled = false; struct timeval now; gettimeofday(&now, NULL); while ((ret = m_protocol->parse_response()) > 0) { bool error = false; protocol_response *r = m_protocol->get_response(); request* req = pop_req(); if (req->m_type == rt_auth) { if (r->is_error()) { benchmark_error_log("error: authentication failed [%s]\n", r->get_status()); error = true; } else { m_authentication = auth_done; benchmark_debug_log("authentication successful.\n"); } } else if (req->m_type == rt_select_db) { if (strcmp(r->get_status(), "+OK") != 0) { benchmark_error_log("database selection failed.\n"); error = true; } else { benchmark_debug_log("database selection successful.\n"); m_db_selection = select_done; } } else if (req->m_type == rt_cluster_slots) { if (r->get_mbulk_value() == NULL || r->get_mbulk_value()->mbulk_array.size() == 0) { benchmark_error_log("cluster slot failed.\n"); error = true; } else { // parse response m_conns_manager->handle_cluster_slots(r); m_cluster_slots = slots_done; benchmark_debug_log("cluster slot command successful\n"); } } else { benchmark_debug_log("handled response (first line): %s, %d hits, %d misses\n", r->get_status(), r->get_hits(), req->m_keys - r->get_hits()); if (r->is_error()) { benchmark_error_log("error response: %s\n", r->get_status()); } m_conns_manager->handle_response(now, req, r); m_conns_manager->inc_reqs_processed(); responses_handled = true; } delete req; if (error) { return; } } if (ret == -1) { benchmark_error_log("error: response parsing failed.\n"); } if (m_config->reconnect_interval > 0 && responses_handled) { if ((m_conns_manager->get_reqs_processed() % m_config->reconnect_interval) == 0) { assert(m_pipeline->size() == 0); benchmark_debug_log("reconnecting, m_reqs_processed = %u\n", m_conns_manager->get_reqs_processed()); // client manage connection & disconnection of shard m_conns_manager->disconnect(); ret = m_conns_manager->connect(); assert(ret == 0); return; } } fill_pipeline(); }
void client::process_response(void) { int ret; bool responses_handled = false; while ((ret = m_protocol->parse_response()) > 0) { bool error = false; protocol_response *r = m_protocol->get_response(); client::request* req = m_pipeline.front(); m_pipeline.pop(); if (req->m_type == rt_auth) { if (r->is_error()) { benchmark_error_log("error: authentication failed [%s]\n", r->get_status()); error = true; } else { m_authentication = auth_done; benchmark_debug_log("authentication successful.\n"); } } else if (req->m_type == rt_select_db) { if (strcmp(r->get_status(), "+OK") != 0) { benchmark_error_log("database selection failed.\n"); error = true; } else { benchmark_debug_log("database selection successful.\n"); m_db_selection = select_done; } } else { benchmark_debug_log("handled response (first line): %s, %d hits, %d misses\n", r->get_status(), r->get_hits(), req->m_keys - r->get_hits()); if (r->is_error()) { benchmark_error_log("error response: %s\n", r->get_status()); } handle_response(req, r); m_reqs_processed++; responses_handled = true; } delete req; if (error) { return; } } if (ret == -1) { benchmark_error_log("error: response parsing failed.\n"); } if (m_config->reconnect_interval > 0 && responses_handled) { if ((m_reqs_processed % m_config->reconnect_interval) == 0) { assert(m_pipeline.size() == 0); benchmark_debug_log("reconnecting, m_reqs_processed = %u\n", m_reqs_processed); disconnect(); ret = connect(); assert(ret == 0); return; } } fill_pipeline(); }
// This function could use some urgent TLC -- but we need to do it without altering the behavior void client::create_request(void) { int cmd_size = 0; // If the Set:Wait ratio is not 0, start off with WAITs if (m_config->wait_ratio.b && (m_tot_wait_ops == 0 || (m_tot_set_ops/m_tot_wait_ops > m_config->wait_ratio.a/m_config->wait_ratio.b))) { m_tot_wait_ops++; unsigned int num_slaves = m_obj_gen->random_range(m_config->num_slaves.min, m_config->num_slaves.max); unsigned int timeout = m_obj_gen->normal_distribution(m_config->wait_timeout.min, m_config->wait_timeout.max, 0, ((m_config->wait_timeout.max - m_config->wait_timeout.min)/2.0) + m_config->wait_timeout.min); benchmark_debug_log("WAIT num_slaves=%u timeout=%u\n", num_slaves, timeout); cmd_size = m_protocol->write_command_wait(num_slaves, timeout); m_pipeline.push(new client::request(rt_wait, cmd_size, NULL, 0)); } // are we set or get? this depends on the ratio else if (m_set_ratio_count < m_config->ratio.a) { // set command data_object *obj = m_obj_gen->get_object(obj_iter_type(m_config, 0)); unsigned int key_len; const char *key = obj->get_key(&key_len); unsigned int value_len; const char *value = obj->get_value(&value_len); m_set_ratio_count++; m_tot_set_ops++; benchmark_debug_log("SET key=[%.*s] value_len=%u expiry=%u\n", key_len, key, value_len, obj->get_expiry()); cmd_size = m_protocol->write_command_set(key, key_len, value, value_len, obj->get_expiry(), m_config->data_offset); m_pipeline.push(new client::request(rt_set, cmd_size, NULL, 1)); } else if (m_get_ratio_count < m_config->ratio.b) { // get command int iter = obj_iter_type(m_config, 2); if (m_config->multi_key_get > 0) { unsigned int keys_count; keys_count = m_config->ratio.b - m_get_ratio_count; if ((int)keys_count > m_config->multi_key_get) keys_count = m_config->multi_key_get; m_keylist->clear(); while (m_keylist->get_keys_count() < keys_count) { unsigned int keylen; const char *key = m_obj_gen->get_key(iter, &keylen); assert(key != NULL); assert(keylen > 0); m_keylist->add_key(key, keylen); } const char *first_key, *last_key; unsigned int first_key_len, last_key_len; first_key = m_keylist->get_key(0, &first_key_len); last_key = m_keylist->get_key(m_keylist->get_keys_count()-1, &last_key_len); benchmark_debug_log("MGET %d keys [%.*s] .. [%.*s]\n", m_keylist->get_keys_count(), first_key_len, first_key, last_key_len, last_key); cmd_size = m_protocol->write_command_multi_get(m_keylist); m_get_ratio_count += keys_count; m_pipeline.push(new client::request(rt_get, cmd_size, NULL, m_keylist->get_keys_count())); } else { unsigned int keylen; const char *key = m_obj_gen->get_key(iter, &keylen); assert(key != NULL); assert(keylen > 0); benchmark_debug_log("GET key=[%.*s]\n", keylen, key); cmd_size = m_protocol->write_command_get(key, keylen, m_config->data_offset); m_get_ratio_count++; m_pipeline.push(new client::request(rt_get, cmd_size, NULL, 1)); } } else { // overlap counters m_get_ratio_count = m_set_ratio_count = 0; } }