Skip to content
13 changes: 11 additions & 2 deletions client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@

#include <math.h>
#include <algorithm>
#include <sstream>
#include <arpa/inet.h>

#include "client.h"
#include "cluster_client.h"
#include "config_types.h"


bool client::setup_client(benchmark_config *config, abstract_protocol *protocol, object_generator *objgen)
Expand Down Expand Up @@ -256,8 +258,15 @@ void client::create_arbitrary_request(const arbitrary_command* cmd, struct timev

assert(key != NULL);
assert(key_len > 0);

cmd_size += m_connections[conn_id]->send_arbitrary_command(arg, key, key_len);
//when we have static data mixed with the key placeholder
if (arg->data.length() != strlen(KEY_PLACEHOLDER)) {
std::string str (arg->data);
std::ostringstream key_stream;
key_stream << arg->data_prefix << key << arg->data_suffix;
cmd_size += m_connections[conn_id]->send_arbitrary_command(arg, key_stream.str().c_str(), key_stream.str().length());
} else{
cmd_size += m_connections[conn_id]->send_arbitrary_command(arg, key, key_len);
}
} else if (arg->type == data_type) {
unsigned int value_len;
const char *value = m_obj_gen->get_value(0, &value_len);
Expand Down
3 changes: 3 additions & 0 deletions config_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ struct command_arg {
command_arg(const char* arg, unsigned int arg_len) : type(undefined_type), data(arg, arg_len) {;}
command_arg_type type;
std::string data;
// the prefix and suffix strings are used for mixed key placeholder storing of substrings
std::string data_prefix;
std::string data_suffix;
};

struct arbitrary_command {
Expand Down
19 changes: 13 additions & 6 deletions protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,13 +630,20 @@ bool redis_protocol::format_arbitrary_command(arbitrary_command &cmd) {
current_arg->type = const_type;

// check arg type
if (current_arg->data.find(KEY_PLACEHOLDER) != std::string::npos) {
if (current_arg->data.length() != strlen(KEY_PLACEHOLDER)) {
benchmark_error_log("error: key placeholder can't combined with other data\n");
return false;
}

const std::size_t key_placeholder_start = current_arg->data.find(KEY_PLACEHOLDER);
if (key_placeholder_start != std::string::npos) {
current_arg->type = key_type;
current_arg->data_prefix = "";
current_arg->data_suffix = "";
// check for prefix
if (key_placeholder_start > 0) {
current_arg->data_prefix = current_arg->data.substr(0,key_placeholder_start);
}
// check for sufix
const std::size_t suffix_start = strlen(KEY_PLACEHOLDER)+key_placeholder_start;
if (current_arg->data.length() > suffix_start) {
current_arg->data_suffix = current_arg->data.substr(suffix_start,current_arg->data.length());
}
} else if (current_arg->data.find(DATA_PLACEHOLDER) != std::string::npos) {
if (current_arg->data.length() != strlen(DATA_PLACEHOLDER)) {
benchmark_error_log("error: data placeholder can't combined with other data\n");
Expand Down
2 changes: 0 additions & 2 deletions tests/test_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
redis>=3.0.0
git+https://github.com/Grokzen/redis-py-cluster.git@master
git+https://github.com/RedisLabsModules/RLTest.git@master
git+https://github.com/RedisLabs/mbdirector.git@master
61 changes: 61 additions & 0 deletions tests/tests_oss_simple_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,64 @@ def test_default_set_get_3_runs(env):
overall_request_count = agg_info_commandstats(master_nodes_connections, merged_command_stats)
assert_minimum_memtier_outcomes(config, env, memtier_ok, merged_command_stats, overall_expected_request_count,
overall_request_count)


def test_key_placeholder(env):
env.skipOnCluster()
run_count = 1
benchmark_specs = {"name": env.testName, "args": ['--command=HSET __key__ f __data__']}
addTLSArgs(benchmark_specs, env)
config = get_default_memtier_config()
master_nodes_list = env.getMasterNodesList()
overall_expected_request_count = get_expected_request_count(config) * run_count

add_required_env_arguments(benchmark_specs, config, env, master_nodes_list)

# Create a temporary directory
test_dir = tempfile.mkdtemp()

config = RunConfig(test_dir, env.testName, config, {})
ensure_clean_benchmark_folder(config.results_dir)

benchmark = Benchmark.from_json(config, benchmark_specs)

# benchmark.run() returns True if the return code of memtier_benchmark was 0
memtier_ok = benchmark.run()
debugPrintMemtierOnError(config, env, memtier_ok)

master_nodes_connections = env.getOSSMasterNodesConnectionList()
merged_command_stats = {'cmdstat_hset': {'calls': 0}}
overall_request_count = agg_info_commandstats(master_nodes_connections, merged_command_stats)
assert_minimum_memtier_outcomes(config, env, memtier_ok, merged_command_stats, overall_expected_request_count,
overall_request_count)


# key placeholder combined with other data
def test_key_placeholder_togetherwithdata(env):
env.skipOnCluster()
run_count = 1
benchmark_specs = {"name": env.testName, "args": ['--command=HSET prefix:__key__:suffix f __data__']}
addTLSArgs(benchmark_specs, env)
config = get_default_memtier_config()
master_nodes_list = env.getMasterNodesList()
overall_expected_request_count = get_expected_request_count(config) * run_count

add_required_env_arguments(benchmark_specs, config, env, master_nodes_list)

# Create a temporary directory
test_dir = tempfile.mkdtemp()

config = RunConfig(test_dir, env.testName, config, {})
ensure_clean_benchmark_folder(config.results_dir)

benchmark = Benchmark.from_json(config, benchmark_specs)

# benchmark.run() returns True if the return code of memtier_benchmark was 0
memtier_ok = benchmark.run()
debugPrintMemtierOnError(config, env, memtier_ok)

master_nodes_connections = env.getOSSMasterNodesConnectionList()
merged_command_stats = {'cmdstat_hset': {'calls': 0}}
overall_request_count = agg_info_commandstats(master_nodes_connections, merged_command_stats)
assert_minimum_memtier_outcomes(config, env, memtier_ok, merged_command_stats, overall_expected_request_count,
overall_request_count)