/*
* Copyright (C) 2011-2017 Redis Labs Ltd.
*
* This file is part of memtier_benchmark.
*
* memtier_benchmark is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* memtier_benchmark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with memtier_benchmark. If not, see .
*/
#ifndef _CLIENT_H
#define _CLIENT_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "protocol.h"
#include "config_types.h"
#include "shard_connection.h"
#include "connections_manager.h"
#include "obj_gen.h"
#include "memtier_benchmark.h"
#include "run_stats.h"
#define MAIN_CONNECTION m_connections[0]
// forward declarations
class client;
class client_group;
struct benchmark_config;
class object_generator;
class data_object;
class client : public connections_manager {
protected:
std::vector m_connections;
struct event_base* m_event_base;
bool m_initialized;
bool m_end_set;
// test related
benchmark_config* m_config;
object_generator* m_obj_gen;
run_stats m_stats;
unsigned long long m_reqs_processed; // requests processed (responses received)
unsigned long long m_reqs_generated; // requests generated (wait for responses)
unsigned int m_set_ratio_count; // number of sets counter (overlaps on ratio)
unsigned int m_get_ratio_count; // number of gets counter (overlaps on ratio)
unsigned int m_arbitrary_command_ratio_count; // number of arbitrary commands counter (overlaps on ratio)
unsigned int m_executed_command_index; // current arbitrary command executed
unsigned long long m_tot_set_ops; // Total number of SET ops
unsigned long long m_tot_wait_ops; // Total number of WAIT ops
keylist *m_keylist; // used to construct multi commands
public:
client(client_group* group);
client(struct event_base *event_base, benchmark_config *config, abstract_protocol *protocol, object_generator *obj_gen);
virtual ~client();
virtual bool setup_client(benchmark_config *config, abstract_protocol *protocol, object_generator *obj_gen);
virtual int prepare(void);
bool initialized(void);
run_stats* get_stats(void) { return &m_stats; }
// client manager api's
unsigned long long get_reqs_processed() {
return m_reqs_processed;
}
void inc_reqs_processed() {
m_reqs_processed++;
}
unsigned long long get_reqs_generated() {
return m_reqs_generated;
}
void inc_reqs_generated() {
m_reqs_generated++;
}
virtual void handle_cluster_slots(protocol_response *r) {
assert(false && "handle_cluster_slots not supported");
}
virtual void handle_response(unsigned int conn_id, struct timeval timestamp,
request *request, protocol_response *response);
virtual bool finished(void);
virtual void set_start_time();
virtual void set_end_time();
virtual void create_arbitrary_request(const arbitrary_command* cmd, struct timeval& timestamp, unsigned int conn_id);
virtual void create_request(struct timeval timestamp, unsigned int conn_id);
virtual bool hold_pipeline(unsigned int conn_id);
virtual int connect(void);
virtual void disconnect(void);
//
// Utility function to get the object iterator type based on the config
inline int obj_iter_type(benchmark_config *cfg, unsigned char index)
{
if (cfg->key_pattern[index] == 'R') {
return OBJECT_GENERATOR_KEY_RANDOM;
} else if (cfg->key_pattern[index] == 'G') {
return OBJECT_GENERATOR_KEY_GAUSSIAN;
} else {
if (index == key_pattern_set)
return OBJECT_GENERATOR_KEY_SET_ITER;
else
return OBJECT_GENERATOR_KEY_GET_ITER;
}
}
inline int get_arbitrary_obj_iter_type(const arbitrary_command* cmd, unsigned int index) {
if (cmd->key_pattern == 'R') {
return OBJECT_GENERATOR_KEY_RANDOM;
} else if (cmd->key_pattern == 'G') {
return OBJECT_GENERATOR_KEY_GAUSSIAN;
} else {
return index;
}
}
};
class verify_client : public client {
protected:
bool m_finished;
unsigned long long int m_verified_keys;
unsigned long long int m_errors;
virtual bool finished(void);
virtual void create_request(struct timeval timestamp, unsigned int conn_id);
virtual void handle_response(unsigned int conn_id, struct timeval timestamp,
request *request, protocol_response *response);
public:
verify_client(struct event_base *event_base, benchmark_config *config, abstract_protocol *protocol, object_generator *obj_gen);
unsigned long long int get_verified_keys(void);
unsigned long long int get_errors(void);
};
class client_group {
protected:
struct event_base* m_base;
benchmark_config *m_config;
abstract_protocol* m_protocol;
object_generator* m_obj_gen;
std::vector m_clients;
public:
client_group(benchmark_config *cfg, abstract_protocol *protocol, object_generator* obj_gen);
~client_group();
int create_clients(int count);
int prepare(void);
void run(void);
void write_client_stats(const char *prefix);
struct event_base *get_event_base(void) { return m_base; }
benchmark_config *get_config(void) { return m_config; }
abstract_protocol* get_protocol(void) { return m_protocol; }
object_generator* get_obj_gen(void) { return m_obj_gen; }
unsigned long int get_total_bytes(void);
unsigned long int get_total_ops(void);
unsigned long int get_total_latency(void);
unsigned long int get_duration_usec(void);
void merge_run_stats(run_stats* target);
};
#endif /* _CLIENT_H */