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, &timestamp, 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, &timestamp, 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, &timestamp, 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;
}
Exemple #10
0
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();
}
Exemple #13
0
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();
}
Exemple #14
0
// 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;
    }        
}