From a7a011c2ea4a63368b3a96a332da00820ed402cb Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Mon, 30 Nov 2009 10:43:20 -0600 Subject: [PATCH] Uncrustify --- clients/memslap.c | 1227 +++++----- clients/ms_conn.c | 4424 +++++++++++++++++++++---------------- clients/ms_conn.h | 280 +-- clients/ms_memslap.h | 127 +- clients/ms_setting.c | 1432 ++++++------ clients/ms_setting.h | 223 +- clients/ms_sigsegv.c | 282 +-- clients/ms_sigsegv.h | 3 + clients/ms_stats.c | 374 ++-- clients/ms_stats.h | 45 +- clients/ms_task.c | 1268 ++++++----- clients/ms_task.h | 78 +- clients/ms_thread.c | 331 +-- clients/ms_thread.h | 36 +- clients/protocol_binary.h | 650 +++--- 15 files changed, 6003 insertions(+), 4777 deletions(-) diff --git a/clients/memslap.c b/clients/memslap.c index 92f26e79..3ed6a2b5 100644 --- a/clients/memslap.c +++ b/clients/memslap.c @@ -1,5 +1,5 @@ /* - * memslap - memslap + * memslap * * (c) Copyright 2009, Schooner Information Technology, Inc. * All rights reserved. @@ -19,36 +19,60 @@ #include "ms_setting.h" #include "ms_thread.h" -#define PROGRAM_NAME "memslap" -#define PROGRAM_DESCRIPTION "Generates workload against memcached servers." +#define PROGRAM_NAME "memslap" +#define PROGRAM_DESCRIPTION \ + "Generates workload against memcached servers." /* options */ -static struct option long_options[] = +static struct option long_options[]= { - {"servers", required_argument, NULL, OPT_SERVERS}, - {"threads", required_argument, NULL, OPT_THREAD_NUMBER}, - {"concurrency", required_argument, NULL, OPT_CONCURRENCY}, - {"conn_sock", required_argument, NULL, OPT_SOCK_PER_CONN}, - {"execute_number", required_argument, NULL, OPT_EXECUTE_NUMBER}, - {"time", required_argument, NULL, OPT_TIME}, - {"cfg_cmd", required_argument, NULL, OPT_CONFIG_CMD}, - {"win_size", required_argument, NULL, OPT_WINDOW_SIZE}, - {"fixed_size", required_argument, NULL, OPT_FIXED_LTH}, - {"verify", required_argument, NULL, OPT_VERIFY}, - {"division", required_argument, NULL, OPT_GETS_DIVISION}, - {"stat_freq", required_argument, NULL, OPT_STAT_FREQ}, - {"exp_verify", required_argument, NULL, OPT_EXPIRE}, - {"overwrite", required_argument, NULL, OPT_OVERWRITE}, - {"reconnect", no_argument, NULL, OPT_RECONNECT}, - {"udp", no_argument, NULL, OPT_UDP}, - {"facebook", no_argument, NULL, OPT_FACEBOOK_TEST}, - {"binary", no_argument, NULL, OPT_BINARY_PROTOCOL}, - {"tps", required_argument, NULL, OPT_TPS}, - {"rep_write", required_argument, NULL, OPT_REP_WRITE_SRV}, - {"verbose", no_argument, NULL, OPT_VERBOSE}, - {"help", no_argument, NULL, OPT_HELP}, - {"version", no_argument, NULL, OPT_VERSION}, - {0, 0, 0, 0}, + { "servers", required_argument, NULL, + OPT_SERVERS }, + { "threads", required_argument, NULL, + OPT_THREAD_NUMBER }, + { "concurrency", required_argument, NULL, + OPT_CONCURRENCY }, + { "conn_sock", required_argument, NULL, + OPT_SOCK_PER_CONN }, + { "execute_number", required_argument, NULL, + OPT_EXECUTE_NUMBER }, + { "time", required_argument, NULL, + OPT_TIME }, + { "cfg_cmd", required_argument, NULL, + OPT_CONFIG_CMD }, + { "win_size", required_argument, NULL, + OPT_WINDOW_SIZE }, + { "fixed_size", required_argument, NULL, + OPT_FIXED_LTH }, + { "verify", required_argument, NULL, + OPT_VERIFY }, + { "division", required_argument, NULL, + OPT_GETS_DIVISION }, + { "stat_freq", required_argument, NULL, + OPT_STAT_FREQ }, + { "exp_verify", required_argument, NULL, + OPT_EXPIRE }, + { "overwrite", required_argument, NULL, + OPT_OVERWRITE }, + { "reconnect", no_argument, NULL, + OPT_RECONNECT }, + { "udp", no_argument, NULL, + OPT_UDP }, + { "facebook", no_argument, NULL, + OPT_FACEBOOK_TEST }, + { "binary", no_argument, NULL, + OPT_BINARY_PROTOCOL }, + { "tps", required_argument, NULL, + OPT_TPS }, + { "rep_write", required_argument, NULL, + OPT_REP_WRITE_SRV }, + { "verbose", no_argument, NULL, + OPT_VERBOSE }, + { "help", no_argument, NULL, + OPT_HELP }, + { "version", no_argument, NULL, + OPT_VERSION }, + { 0, 0, 0, 0 }, }; /* Prototypes */ @@ -57,7 +81,7 @@ static void ms_sync_lock_destroy(void); static void ms_global_struct_init(void); static void ms_global_struct_destroy(void); static void ms_version_command(const char *command_name); -static const char * ms_lookup_help(ms_options_t option); +static const char *ms_lookup_help(ms_options_t option); static int64_t ms_parse_time(void); static int64_t ms_parse_size(void); static void ms_options_parse(int argc, char *argv[]); @@ -65,7 +89,8 @@ static int ms_check_para(void); static void ms_statistic_init(void); static void ms_stats_init(void); static void ms_print_statistics(int time); -static void ms_print_memslap_stats(struct timeval *start_time, struct timeval *end_time); +static void ms_print_memslap_stats(struct timeval *start_time, + struct timeval *end_time); static void ms_monitor_slap_mode(void); void ms_help_command(const char *command_name, const char *description); @@ -73,49 +98,54 @@ void ms_help_command(const char *command_name, const char *description); /* initialize the global locks */ static void ms_sync_lock_init() { - ms_global.init_lock.count = 0; - pthread_mutex_init(&ms_global.init_lock.lock, NULL); - pthread_cond_init(&ms_global.init_lock.cond, NULL); + ms_global.init_lock.count= 0; + pthread_mutex_init(&ms_global.init_lock.lock, NULL); + pthread_cond_init(&ms_global.init_lock.cond, NULL); - ms_global.run_lock.count = 0; - pthread_mutex_init(&ms_global.run_lock.lock, NULL); - pthread_cond_init(&ms_global.run_lock.cond, NULL); + ms_global.run_lock.count= 0; + pthread_mutex_init(&ms_global.run_lock.lock, NULL); + pthread_cond_init(&ms_global.run_lock.cond, NULL); + + pthread_mutex_init(&ms_global.quit_mutex, NULL); + pthread_mutex_init(&ms_global.seq_mutex, NULL); +} /* ms_sync_lock_init */ - pthread_mutex_init(&ms_global.quit_mutex, NULL); - pthread_mutex_init(&ms_global.seq_mutex, NULL); -} /* destroy the global locks */ static void ms_sync_lock_destroy() { - pthread_mutex_destroy(&ms_global.init_lock.lock); - pthread_cond_destroy(&ms_global.init_lock.cond); + pthread_mutex_destroy(&ms_global.init_lock.lock); + pthread_cond_destroy(&ms_global.init_lock.cond); - pthread_mutex_destroy(&ms_global.run_lock.lock); - pthread_cond_destroy(&ms_global.run_lock.cond); + pthread_mutex_destroy(&ms_global.run_lock.lock); + pthread_cond_destroy(&ms_global.run_lock.cond); - pthread_mutex_destroy(&ms_global.quit_mutex); - pthread_mutex_destroy(&ms_global.seq_mutex); + pthread_mutex_destroy(&ms_global.quit_mutex); + pthread_mutex_destroy(&ms_global.seq_mutex); + + if (ms_setting.stat_freq > 0) + { + pthread_mutex_destroy(&ms_statistic.stat_mutex); + } +} /* ms_sync_lock_destroy */ - if (ms_setting.stat_freq > 0) { - pthread_mutex_destroy(&ms_statistic.stat_mutex); - } -} /* initialize the global structure */ static void ms_global_struct_init() { - ms_sync_lock_init(); - ms_global.finish_warmup = false; - ms_global.time_out = false; + ms_sync_lock_init(); + ms_global.finish_warmup= false; + ms_global.time_out= false; } + /* destroy the global structure */ static void ms_global_struct_destroy() { - ms_sync_lock_destroy(); + ms_sync_lock_destroy(); } + /** * output the version information * @@ -123,10 +153,11 @@ static void ms_global_struct_destroy() */ static void ms_version_command(const char *command_name) { - printf("%s v%u.%u\n", command_name, 1, 0); - exit(0); + printf("%s v%u.%u\n", command_name, 1, 0); + exit(0); } + /** * get the description of the option * @@ -134,67 +165,105 @@ static void ms_version_command(const char *command_name) * * @return char*, description of the command option */ -static const char * ms_lookup_help(ms_options_t option) +static const char *ms_lookup_help(ms_options_t option) { - switch (option) { - case OPT_SERVERS: - return("List one or more servers to connect. Servers count must be less than\n" - " threads count. e.g.: --servers=localhost:1234,localhost:11211"); - case OPT_VERSION: - return("Display the version of the application and then exit."); - case OPT_HELP: - return("Display this message and then exit."); - case OPT_EXECUTE_NUMBER: - return("Number of operations(get and set) to execute for the\n" - " given test. Default 1000000."); - case OPT_THREAD_NUMBER: - return("Number of threads to startup, better equal to CPU numbers. Default 8."); - case OPT_CONCURRENCY: - return("Number of concurrency to simulate with load. Default 128."); - case OPT_FIXED_LTH : - return("Fixed length of value."); - case OPT_VERIFY : - return("The proportion of date verification, e.g.: --verify=0.01"); - case OPT_GETS_DIVISION : - return("Number of keys to multi-get once. Default 1, means single get."); - case OPT_TIME : - return("How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n" - " d-days e.g.: --time=2h."); - case OPT_CONFIG_CMD: - return("Load the configure file to get command,key and value distribution list."); - case OPT_WINDOW_SIZE: - return("Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n" - " Default 10k."); - case OPT_UDP: - return("UDP support, default memslap uses TCP, TCP port and UDP port of\n" - " server must be same."); - case OPT_EXPIRE: - return("The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n" - " Default no object with expire time"); - case OPT_OVERWRITE: - return("The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n" - " Default never overwrite object."); - case OPT_STAT_FREQ: - return("Frequency of dumping statistic information. suffix: s-seconds,\n" - " m-minutes, e.g.: --resp_freq=10s."); - case OPT_SOCK_PER_CONN: - return("Number of TCP socks per concurrency. Default 1."); - case OPT_RECONNECT: - return("Reconnect support, when connection is closed it will be reconnected."); - case OPT_VERBOSE: - return("Whether it outputs detailed information when verification fails."); - case OPT_FACEBOOK_TEST: - return("Whether it enables facebook test feature, set with TCP and multi-get with UDP."); - case OPT_BINARY_PROTOCOL: - return("Whether it enables binary protocol. Default with ASCII protocol."); - case OPT_TPS: - return("Expected throughput, suffix: K, e.g.: --tps=10k."); - case OPT_REP_WRITE_SRV: - return("The first nth servers can write data, e.g.: --rep_write=2."); - default: - return "Forgot to document this option :)"; - }; -} + switch (option) + { + case OPT_SERVERS: + return + "List one or more servers to connect. Servers count must be less than\n" + " threads count. e.g.: --servers=localhost:1234,localhost:11211"; + + case OPT_VERSION: + return "Display the version of the application and then exit."; + + case OPT_HELP: + return "Display this message and then exit."; + + case OPT_EXECUTE_NUMBER: + return "Number of operations(get and set) to execute for the\n" + " given test. Default 1000000."; + + case OPT_THREAD_NUMBER: + return + "Number of threads to startup, better equal to CPU numbers. Default 8."; + + case OPT_CONCURRENCY: + return "Number of concurrency to simulate with load. Default 128."; + + case OPT_FIXED_LTH: + return "Fixed length of value."; + + case OPT_VERIFY: + return "The proportion of date verification, e.g.: --verify=0.01"; + + case OPT_GETS_DIVISION: + return "Number of keys to multi-get once. Default 1, means single get."; + + case OPT_TIME: + return + "How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n" + " d-days e.g.: --time=2h."; + + case OPT_CONFIG_CMD: + return + "Load the configure file to get command,key and value distribution list."; + + case OPT_WINDOW_SIZE: + return + "Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n" + " Default 10k."; + + case OPT_UDP: + return + "UDP support, default memslap uses TCP, TCP port and UDP port of\n" + " server must be same."; + + case OPT_EXPIRE: + return + "The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n" + " Default no object with expire time"; + + case OPT_OVERWRITE: + return + "The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n" + " Default never overwrite object."; + + case OPT_STAT_FREQ: + return + "Frequency of dumping statistic information. suffix: s-seconds,\n" + " m-minutes, e.g.: --resp_freq=10s."; + + case OPT_SOCK_PER_CONN: + return "Number of TCP socks per concurrency. Default 1."; + + case OPT_RECONNECT: + return + "Reconnect support, when connection is closed it will be reconnected."; + + case OPT_VERBOSE: + return + "Whether it outputs detailed information when verification fails."; + + case OPT_FACEBOOK_TEST: + return + "Whether it enables facebook test feature, set with TCP and multi-get with UDP."; + + case OPT_BINARY_PROTOCOL: + return + "Whether it enables binary protocol. Default with ASCII protocol."; + + case OPT_TPS: + return "Expected throughput, suffix: K, e.g.: --tps=10k."; + + case OPT_REP_WRITE_SRV: + return "The first nth servers can write data, e.g.: --rep_write=2."; + + default: + return "Forgot to document this option :)"; + } /* switch */ +} /* ms_lookup_help */ + /** * output the help information @@ -205,477 +274,569 @@ static const char * ms_lookup_help(ms_options_t option) */ void ms_help_command(const char *command_name, const char *description) { - char *help_message = NULL; - - printf("%s v%u.%u\n", command_name, 1, 0); - printf(" %s\n\n", description); - printf("Usage:\n" - " memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n" - "Options:\n"); - - for (int x = 0; long_options[x].name; x++) { - printf(" -%c, --%s%c\n", long_options[x].val, long_options[x].name, - long_options[x].has_arg ? '=' : ' '); - if ((help_message = (char *)ms_lookup_help(long_options[x].val)) != NULL) { - printf(" %s\n", help_message); - } + char *help_message= NULL; + + printf("%s v%u.%u\n", command_name, 1, 0); + printf(" %s\n\n", description); + printf( + "Usage:\n" + " memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n" + "Options:\n"); + + for (int x= 0; long_options[x].name; x++) + { + printf(" -%c, --%s%c\n", long_options[x].val, long_options[x].name, + long_options[x].has_arg ? '=' : ' '); + if ((help_message= (char *)ms_lookup_help(long_options[x].val)) != NULL) + { + printf(" %s\n", help_message); } + } - printf("\nExamples:\n" - " memslap -s 127.0.0.1:11211 -S 5s\n" - " memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n" - " memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n" - " memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n" - " memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n" - " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n" - " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n"); + printf( + "\nExamples:\n" + " memslap -s 127.0.0.1:11211 -S 5s\n" + " memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n" + " memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n" + " memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n" + " memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n" + " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n" + " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n"); + + exit(0); +} /* ms_help_command */ - exit(0); -} /* used to parse the time string */ static int64_t ms_parse_time() { - int64_t ret = 0; - char unit = optarg[strlen(optarg) - 1]; - optarg[strlen(optarg) - 1] = '\0'; - ret = atoi(optarg); - - switch (unit) { - case 'd': - case 'D': - ret *= 24; - case 'h': - case 'H': - ret *= 60; - case 'm': - case 'M': - ret *= 60; - case 's': - case 'S': - break; - default: - ret = -1; - break; - } + int64_t ret= 0; + char unit= optarg[strlen(optarg) - 1]; + + optarg[strlen(optarg) - 1]= '\0'; + ret= atoi(optarg); + + switch (unit) + { + case 'd': + case 'D': + ret*= 24; + + case 'h': + case 'H': + ret*= 60; + + case 'm': + case 'M': + ret*= 60; + + case 's': + case 'S': + break; + + default: + ret= -1; + break; + } /* switch */ + + return ret; +} /* ms_parse_time */ - return ret; -} /* used to parse the size string */ static int64_t ms_parse_size() { - int64_t ret = -1; - char unit = optarg[strlen(optarg) - 1]; - optarg[strlen(optarg) - 1] = '\0'; - ret = strtoll(optarg, (char **)NULL, 10); - - switch (unit) { - case 'k': - case 'K': - ret *= 1024; - break; - case 'm': - case 'M': - ret *= 1024 * 1024; - break; - case 'g': - case 'G': - ret *= 1024 * 1024 * 1024; - break; - default: - ret = -1; - break; - } + int64_t ret= -1; + char unit= optarg[strlen(optarg) - 1]; + + optarg[strlen(optarg) - 1]= '\0'; + ret= strtoll(optarg, (char **)NULL, 10); + + switch (unit) + { + case 'k': + case 'K': + ret*= 1024; + break; + + case 'm': + case 'M': + ret*= 1024 * 1024; + break; + + case 'g': + case 'G': + ret*= 1024 * 1024 * 1024; + break; + + default: + ret= -1; + break; + } /* switch */ + + return ret; +} /* ms_parse_size */ - return ret; -} /* used to parse the options of command line */ static void ms_options_parse(int argc, char *argv[]) { - int option_index= 0; - int option_rv; - - while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:" - "t:S:F:w:e:o:n:P:p:", - long_options, &option_index)) != -1) { - - switch (option_rv) { - case 0: - break; - - case OPT_VERSION: /* --version or -V */ - ms_version_command(PROGRAM_NAME); - break; - - case OPT_HELP: /* --help or -h */ - ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION); - break; - - case OPT_SERVERS: /* --servers or -s */ - ms_setting.srv_str= strdup(optarg); - break; - - case OPT_CONCURRENCY: /* --concurrency or -c */ - ms_setting.nconns = atoi(optarg); - if (ms_setting.nconns <= 0) { - fprintf(stderr, "Concurrency must be greater than 0.:-)\n"); - exit(1); - } - break; - - case OPT_EXECUTE_NUMBER: /* --execute_number or -x */ - ms_setting.exec_num = atoll(optarg); - if (ms_setting.exec_num <= 0) { - fprintf(stderr, "Execute number must be greater than 0.:-)\n"); - exit(1); - } - break; - - case OPT_THREAD_NUMBER: /* --threads or -T */ - ms_setting.nthreads = atoi(optarg); - if (ms_setting.nthreads <= 0) { - fprintf(stderr, "Threads number must be greater than 0.:-)\n"); - exit(1); - } - break; - - case OPT_FIXED_LTH: /* --fixed_size or -X */ - ms_setting.fixed_value_size = (size_t)atoi(optarg); - if (ms_setting.fixed_value_size <= 0 - || ms_setting.fixed_value_size > MAX_VALUE_SIZE) { - fprintf(stderr, "Value size must be between 0 and 1M.:-)\n"); - exit(1); - } - break; - - case OPT_VERIFY: /* --verify or -v */ - ms_setting.verify_percent = atof(optarg); - if (ms_setting.verify_percent <= 0 || ms_setting.verify_percent > 1.0) { - fprintf(stderr, "Data verification rate must be " + int option_index= 0; + int option_rv; + + while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:" + "t:S:F:w:e:o:n:P:p:", + long_options, &option_index)) != -1) + { + switch (option_rv) + { + case 0: + break; + + case OPT_VERSION: /* --version or -V */ + ms_version_command(PROGRAM_NAME); + break; + + case OPT_HELP: /* --help or -h */ + ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION); + break; + + case OPT_SERVERS: /* --servers or -s */ + ms_setting.srv_str= strdup(optarg); + break; + + case OPT_CONCURRENCY: /* --concurrency or -c */ + ms_setting.nconns= atoi(optarg); + if (ms_setting.nconns <= 0) + { + fprintf(stderr, "Concurrency must be greater than 0.:-)\n"); + exit(1); + } + break; + + case OPT_EXECUTE_NUMBER: /* --execute_number or -x */ + ms_setting.exec_num= atoll(optarg); + if (ms_setting.exec_num <= 0) + { + fprintf(stderr, "Execute number must be greater than 0.:-)\n"); + exit(1); + } + break; + + case OPT_THREAD_NUMBER: /* --threads or -T */ + ms_setting.nthreads= atoi(optarg); + if (ms_setting.nthreads <= 0) + { + fprintf(stderr, "Threads number must be greater than 0.:-)\n"); + exit(1); + } + break; + + case OPT_FIXED_LTH: /* --fixed_size or -X */ + ms_setting.fixed_value_size= (size_t)atoi(optarg); + if ((ms_setting.fixed_value_size <= 0) + || (ms_setting.fixed_value_size > MAX_VALUE_SIZE)) + { + fprintf(stderr, "Value size must be between 0 and 1M.:-)\n"); + exit(1); + } + break; + + case OPT_VERIFY: /* --verify or -v */ + ms_setting.verify_percent= atof(optarg); + if ((ms_setting.verify_percent <= 0) + || (ms_setting.verify_percent > 1.0)) + { + fprintf(stderr, "Data verification rate must be " "greater than 0 and less than 1.0. :-)\n"); - exit(1); - } - break; - - case OPT_GETS_DIVISION: /* --division or -d */ - ms_setting.mult_key_num = atoi(optarg); - if (ms_setting.mult_key_num <= 0) { - fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n"); - exit(1); - } - break; - - case OPT_TIME: /* --time or -t */ - ms_setting.run_time = (int)ms_parse_time(); - if (ms_setting.run_time == -1) { - fprintf(stderr, "Please specify the run time. :-)\n" + exit(1); + } + break; + + case OPT_GETS_DIVISION: /* --division or -d */ + ms_setting.mult_key_num= atoi(optarg); + if (ms_setting.mult_key_num <= 0) + { + fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n"); + exit(1); + } + break; + + case OPT_TIME: /* --time or -t */ + ms_setting.run_time= (int)ms_parse_time(); + if (ms_setting.run_time == -1) + { + fprintf(stderr, "Please specify the run time. :-)\n" "'s' for second, 'm' for minute, 'h' for hour, " "'d' for day. e.g.: --time=24h (means 24 hours).\n"); - exit(1); - } - - if (ms_setting.run_time == 0) { - fprintf(stderr, "Running time can not be 0. :-)\n"); - exit(1); - } - break; - - case OPT_CONFIG_CMD: /* --cfg_cmd or -F */ - ms_setting.cfg_file = strdup(optarg); - break; - - case OPT_WINDOW_SIZE: /* --win_size or -w */ - ms_setting.win_size = (size_t)ms_parse_size(); - if (ms_setting.win_size == (size_t)-1) { - fprintf(stderr, "Please specify the item window size. :-)\n" - "e.g.: --win_size=10k (means 10k task window size).\n"); - exit(1); - } - break; - - case OPT_UDP: /* --udp or -U*/ - ms_setting.udp = true; - break; - - case OPT_EXPIRE: /* --exp_verify or -e */ - ms_setting.exp_ver_per = atof(optarg); - if (ms_setting.exp_ver_per <= 0 || ms_setting.exp_ver_per > 1.0) { - fprintf(stderr, "Expire time verification rate must be " + exit(1); + } + + if (ms_setting.run_time == 0) + { + fprintf(stderr, "Running time can not be 0. :-)\n"); + exit(1); + } + break; + + case OPT_CONFIG_CMD: /* --cfg_cmd or -F */ + ms_setting.cfg_file= strdup(optarg); + break; + + case OPT_WINDOW_SIZE: /* --win_size or -w */ + ms_setting.win_size= (size_t)ms_parse_size(); + if (ms_setting.win_size == (size_t)-1) + { + fprintf( + stderr, + "Please specify the item window size. :-)\n" + "e.g.: --win_size=10k (means 10k task window size).\n"); + exit(1); + } + break; + + case OPT_UDP: /* --udp or -U*/ + ms_setting.udp= true; + break; + + case OPT_EXPIRE: /* --exp_verify or -e */ + ms_setting.exp_ver_per= atof(optarg); + if ((ms_setting.exp_ver_per <= 0) || (ms_setting.exp_ver_per > 1.0)) + { + fprintf(stderr, "Expire time verification rate must be " "greater than 0 and less than 1.0. :-)\n"); - exit(1); - } - break; - - case OPT_OVERWRITE: /* --overwrite or -o */ - ms_setting.overwrite_percent = atof(optarg); - if (ms_setting.overwrite_percent <= 0 || ms_setting.overwrite_percent > 1.0) { - fprintf(stderr, "Objects overwrite rate must be " + exit(1); + } + break; + + case OPT_OVERWRITE: /* --overwrite or -o */ + ms_setting.overwrite_percent= atof(optarg); + if ((ms_setting.overwrite_percent <= 0) + || (ms_setting.overwrite_percent > 1.0)) + { + fprintf(stderr, "Objects overwrite rate must be " "greater than 0 and less than 1.0. :-)\n"); - exit(1); - } - break; - - case OPT_STAT_FREQ: /* --stat_freq or -S */ - ms_setting.stat_freq = (int)ms_parse_time(); - if (ms_setting.stat_freq == -1) { - fprintf(stderr, "Please specify the frequency of dumping " - "statistic information. :-)\n" - "'s' for second, 'm' for minute, 'h' for hour, " - "'d' for day. e.g.: --time=24h (means 24 hours).\n"); - exit(1); - } - - if (ms_setting.stat_freq == 0) { - fprintf(stderr, "The frequency of dumping statistic information " - "can not be 0. :-)\n"); - exit(1); - } - break; - - case OPT_SOCK_PER_CONN: /* --conn_sock or -n */ - ms_setting.sock_per_conn = atoi(optarg); - if (ms_setting.sock_per_conn <= 0) { - fprintf(stderr, "Number of socks of each concurrency " - "must be greater than 0.:-)\n"); - exit(1); - } - break; - - case OPT_RECONNECT: /* --reconnect or -R */ - ms_setting.reconnect = true; - break; - - case OPT_VERBOSE: /* --verbose or -b */ - ms_setting.verbose = true; - break; - - case OPT_FACEBOOK_TEST: /* --facebook or -a */ - ms_setting.facebook_test = true; - break; - - case OPT_BINARY_PROTOCOL: /* --binary or -B */ - ms_setting.binary_prot = true; - break; - - case OPT_TPS: /* --tps or -P */ - ms_setting.expected_tps = (int)ms_parse_size(); - if (ms_setting.expected_tps == -1) { - fprintf(stderr, "Please specify the item expected throughput. :-)\n" - "e.g.: --tps=10k (means 10k throughput).\n"); - exit(1); - } - break; - - case OPT_REP_WRITE_SRV: /* --rep_write or -p */ - ms_setting.rep_write_srv = atoi(optarg); - if (ms_setting.rep_write_srv <= 0) { - fprintf(stderr, "Number of replication writing server must be greater " - "than 0.:-)\n"); - exit(1); - } - break; - - case '?': - /* getopt_long already printed an error message. */ - exit(1); - - default: - abort(); - } - } -} + exit(1); + } + break; + + case OPT_STAT_FREQ: /* --stat_freq or -S */ + ms_setting.stat_freq= (int)ms_parse_time(); + if (ms_setting.stat_freq == -1) + { + fprintf(stderr, "Please specify the frequency of dumping " + "statistic information. :-)\n" + "'s' for second, 'm' for minute, 'h' for hour, " + "'d' for day. e.g.: --time=24h (means 24 hours).\n"); + exit(1); + } + + if (ms_setting.stat_freq == 0) + { + fprintf(stderr, "The frequency of dumping statistic information " + "can not be 0. :-)\n"); + exit(1); + } + break; + + case OPT_SOCK_PER_CONN: /* --conn_sock or -n */ + ms_setting.sock_per_conn= atoi(optarg); + if (ms_setting.sock_per_conn <= 0) + { + fprintf(stderr, "Number of socks of each concurrency " + "must be greater than 0.:-)\n"); + exit(1); + } + break; + + case OPT_RECONNECT: /* --reconnect or -R */ + ms_setting.reconnect= true; + break; + + case OPT_VERBOSE: /* --verbose or -b */ + ms_setting.verbose= true; + break; + + case OPT_FACEBOOK_TEST: /* --facebook or -a */ + ms_setting.facebook_test= true; + break; + + case OPT_BINARY_PROTOCOL: /* --binary or -B */ + ms_setting.binary_prot= true; + break; + + case OPT_TPS: /* --tps or -P */ + ms_setting.expected_tps= (int)ms_parse_size(); + if (ms_setting.expected_tps == -1) + { + fprintf(stderr, + "Please specify the item expected throughput. :-)\n" + "e.g.: --tps=10k (means 10k throughput).\n"); + exit(1); + } + break; + + case OPT_REP_WRITE_SRV: /* --rep_write or -p */ + ms_setting.rep_write_srv= atoi(optarg); + if (ms_setting.rep_write_srv <= 0) + { + fprintf(stderr, + "Number of replication writing server must be greater " + "than 0.:-)\n"); + exit(1); + } + break; + + case '?': + /* getopt_long already printed an error message. */ + exit(1); + + default: + abort(); + } /* switch */ + } +} /* ms_options_parse */ + static int ms_check_para() { - if (ms_setting.srv_str == NULL) { - fprintf(stderr, "No Servers provided.\n\n"); - return -1; - } + if (ms_setting.srv_str == NULL) + { + fprintf(stderr, "No Servers provided.\n\n"); + return -1; + } - if (ms_setting.nconns % ms_setting.nthreads != 0) { - fprintf(stderr, "Concurrency must be the multiples of threads count.\n"); - return -1; - } + if (ms_setting.nconns % ms_setting.nthreads != 0) + { + fprintf(stderr, "Concurrency must be the multiples of threads count.\n"); + return -1; + } - if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0) { - fprintf(stderr, "Window size must be the multiples of 1024.\n\n"); - return -1; - } + if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0) + { + fprintf(stderr, "Window size must be the multiples of 1024.\n\n"); + return -1; + } + + return 0; +} /* ms_check_para */ - return 0; -} /* initialize the statistic structure */ static void ms_statistic_init() { - pthread_mutex_init(&ms_statistic.stat_mutex, NULL); - ms_init_stats(&ms_statistic.get_stat, "Get"); - ms_init_stats(&ms_statistic.set_stat, "Set"); - ms_init_stats(&ms_statistic.total_stat, "Total"); -} + pthread_mutex_init(&ms_statistic.stat_mutex, NULL); + ms_init_stats(&ms_statistic.get_stat, "Get"); + ms_init_stats(&ms_statistic.set_stat, "Set"); + ms_init_stats(&ms_statistic.total_stat, "Total"); +} /* ms_statistic_init */ + /* initialize the global state structure */ static void ms_stats_init() { - memset(&ms_stats, 0, sizeof(ms_stats_t)); - if (ms_setting.stat_freq > 0) { - ms_statistic_init(); - } -} + memset(&ms_stats, 0, sizeof(ms_stats_t)); + if (ms_setting.stat_freq > 0) + { + ms_statistic_init(); + } +} /* ms_stats_init */ + /* use to output the statistic */ static void ms_print_statistics(int in_time) { - int obj_size = (int)(ms_setting.avg_key_size + ms_setting.avg_val_size); - - printf("\033[1;1H\033[2J\n"); - ms_dump_format_stats(&ms_statistic.get_stat, in_time, - ms_setting.stat_freq, obj_size); - ms_dump_format_stats(&ms_statistic.set_stat, in_time, - ms_setting.stat_freq, obj_size); - ms_dump_format_stats(&ms_statistic.total_stat, in_time, - ms_setting.stat_freq, obj_size); -} + int obj_size= (int)(ms_setting.avg_key_size + ms_setting.avg_val_size); -/* used to print the states of memslap */ -static void ms_print_memslap_stats(struct timeval *start_time, struct timeval *end_time) -{ - char buf[1024]; - char *pos = buf; - - pos += sprintf(pos, "cmd_get: %llu\n", (unsigned long long)ms_stats.cmd_get); - pos += sprintf(pos, "cmd_set: %llu\n", (unsigned long long)ms_stats.cmd_set); - pos += sprintf(pos, "get_misses: %llu\n", (unsigned long long)ms_stats.get_misses); - - if (ms_setting.verify_percent > 0) { - pos += sprintf(pos, "verify_misses: %llu\n", - (unsigned long long)ms_stats.vef_miss); - pos += sprintf(pos, "verify_failed: %llu\n", - (unsigned long long)ms_stats.vef_failed); - } - - if (ms_setting.exp_ver_per > 0) { - pos += sprintf(pos, "expired_get: %llu\n", - (unsigned long long)ms_stats.exp_get); - pos += sprintf(pos, "unexpired_unget: %llu\n", - (unsigned long long)ms_stats.unexp_unget); - } - - pos += sprintf(pos, "written_bytes: %llu\n", (unsigned long long)ms_stats.bytes_written); - pos += sprintf(pos, "read_bytes: %llu\n", (unsigned long long)ms_stats.bytes_read); - pos += sprintf(pos, "object_bytes: %llu\n", (unsigned long long)ms_stats.obj_bytes); + printf("\033[1;1H\033[2J\n"); + ms_dump_format_stats(&ms_statistic.get_stat, in_time, + ms_setting.stat_freq, obj_size); + ms_dump_format_stats(&ms_statistic.set_stat, in_time, + ms_setting.stat_freq, obj_size); + ms_dump_format_stats(&ms_statistic.total_stat, in_time, + ms_setting.stat_freq, obj_size); +} /* ms_print_statistics */ - if (ms_setting.udp || ms_setting.facebook_test) { - pos += sprintf(pos, "packet_disorder: %llu\n", (unsigned long long)ms_stats.pkt_disorder); - pos += sprintf(pos, "packet_drop: %llu\n", (unsigned long long)ms_stats.pkt_drop); - pos += sprintf(pos, "udp_timeout: %llu\n", (unsigned long long)ms_stats.udp_timeout); - } - - if (ms_setting.stat_freq > 0) { - ms_dump_stats(&ms_statistic.get_stat); - ms_dump_stats(&ms_statistic.set_stat); - ms_dump_stats(&ms_statistic.total_stat); - } - int64_t time_diff = ms_time_diff(start_time, end_time); - pos += sprintf(pos, "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n", - (double)time_diff / 1000000, - (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set), - (ms_stats.cmd_get + ms_stats.cmd_set) / ((long double)time_diff / 1000000), - (double)(ms_stats.bytes_written + ms_stats.bytes_read) / 1024 / 1024 - / ((double)time_diff / 1000000)); +/* used to print the states of memslap */ +static void ms_print_memslap_stats(struct timeval *start_time, + struct timeval *end_time) +{ + char buf[1024]; + char *pos= buf; + + pos+= sprintf(pos, + "cmd_get: %llu\n", + (unsigned long long)ms_stats.cmd_get); + pos+= sprintf(pos, + "cmd_set: %llu\n", + (unsigned long long)ms_stats.cmd_set); + pos+= sprintf(pos, + "get_misses: %llu\n", + (unsigned long long)ms_stats.get_misses); + + if (ms_setting.verify_percent > 0) + { + pos+= sprintf(pos, "verify_misses: %llu\n", + (unsigned long long)ms_stats.vef_miss); + pos+= sprintf(pos, "verify_failed: %llu\n", + (unsigned long long)ms_stats.vef_failed); + } + + if (ms_setting.exp_ver_per > 0) + { + pos+= sprintf(pos, "expired_get: %llu\n", + (unsigned long long)ms_stats.exp_get); + pos+= sprintf(pos, "unexpired_unget: %llu\n", + (unsigned long long)ms_stats.unexp_unget); + } + + pos+= sprintf(pos, + "written_bytes: %llu\n", + (unsigned long long)ms_stats.bytes_written); + pos+= sprintf(pos, + "read_bytes: %llu\n", + (unsigned long long)ms_stats.bytes_read); + pos+= sprintf(pos, + "object_bytes: %llu\n", + (unsigned long long)ms_stats.obj_bytes); + + if (ms_setting.udp || ms_setting.facebook_test) + { + pos+= sprintf(pos, + "packet_disorder: %llu\n", + (unsigned long long)ms_stats.pkt_disorder); + pos+= sprintf(pos, + "packet_drop: %llu\n", + (unsigned long long)ms_stats.pkt_drop); + pos+= sprintf(pos, + "udp_timeout: %llu\n", + (unsigned long long)ms_stats.udp_timeout); + } + + if (ms_setting.stat_freq > 0) + { + ms_dump_stats(&ms_statistic.get_stat); + ms_dump_stats(&ms_statistic.set_stat); + ms_dump_stats(&ms_statistic.total_stat); + } + + int64_t time_diff= ms_time_diff(start_time, end_time); + pos+= sprintf( + pos, + "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n", + (double)time_diff / 1000000, + (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set), + (ms_stats.cmd_get + + ms_stats.cmd_set) / ((long double)time_diff / 1000000), + (double)( + ms_stats.bytes_written + + ms_stats.bytes_read) / 1024 / 1024 + / ((double)time_diff / 1000000)); + + fprintf(stdout, "%s", buf); + fflush(stdout); +} /* ms_print_memslap_stats */ - fprintf(stdout, "%s", buf); - fflush(stdout); -} /* the loop of the main thread, wait the work threads to complete */ static void ms_monitor_slap_mode() { - int second = 0; - struct timeval start_time, end_time; - - /* only when there is no set operation it need warm up */ - if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR) { - /* Wait all the connects complete warm up. */ - pthread_mutex_lock(&ms_global.init_lock.lock); - while (ms_global.init_lock.count < ms_setting.nconns) { - pthread_cond_wait(&ms_global.init_lock.cond, &ms_global.init_lock.lock); - } - pthread_mutex_unlock(&ms_global.init_lock.lock); + int second= 0; + struct timeval start_time, end_time; + + /* only when there is no set operation it need warm up */ + if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR) + { + /* Wait all the connects complete warm up. */ + pthread_mutex_lock(&ms_global.init_lock.lock); + while (ms_global.init_lock.count < ms_setting.nconns) + { + pthread_cond_wait(&ms_global.init_lock.cond, + &ms_global.init_lock.lock); } + pthread_mutex_unlock(&ms_global.init_lock.lock); + } + + ms_global.finish_warmup= true; + + /* running in "run time" mode, user specify run time */ + if (ms_setting.run_time > 0) + { + gettimeofday(&start_time, NULL); + while (1) + { + sleep(1); + second++; + + if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0) + && (ms_stats.active_conns >= ms_setting.nconns)) + { + ms_print_statistics(second); + } + + if (ms_setting.run_time <= second) + { + ms_global.time_out= true; + break; + } - ms_global.finish_warmup = true; - - /* running in "run time" mode, user specify run time */ - if (ms_setting.run_time > 0) { - gettimeofday(&start_time, NULL); - while (1) { - sleep(1); - second++; - - if (ms_setting.stat_freq > 0 && second % ms_setting.stat_freq == 0 - && ms_stats.active_conns >= ms_setting.nconns) { - ms_print_statistics(second); - } - - if (ms_setting.run_time <= second) { - ms_global.time_out = true; - break; - } - - /* all connections disconnect */ - if (second > 5 && ms_stats.active_conns == 0) { - break; - } - } - gettimeofday(&end_time, NULL); - sleep(1); /* wait all threads clean up */ - } else { - /* running in "execute number" mode, user specify execute number */ - gettimeofday(&start_time, NULL); - - /* - * We loop until we know that all connects have cleaned up. - */ - pthread_mutex_lock(&ms_global.run_lock.lock); - while (ms_global.run_lock.count < ms_setting.nconns) { - pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock); - } - pthread_mutex_unlock(&ms_global.run_lock.lock); - - gettimeofday(&end_time, NULL); + /* all connections disconnect */ + if ((second > 5) && (ms_stats.active_conns == 0)) + { + break; + } + } + gettimeofday(&end_time, NULL); + sleep(1); /* wait all threads clean up */ + } + else + { + /* running in "execute number" mode, user specify execute number */ + gettimeofday(&start_time, NULL); + + /* + * We loop until we know that all connects have cleaned up. + */ + pthread_mutex_lock(&ms_global.run_lock.lock); + while (ms_global.run_lock.count < ms_setting.nconns) + { + pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock); } + pthread_mutex_unlock(&ms_global.run_lock.lock); + + gettimeofday(&end_time, NULL); + } + + ms_print_memslap_stats(&start_time, &end_time); +} /* ms_monitor_slap_mode */ - ms_print_memslap_stats(&start_time, &end_time); -} /* the main function */ int main(int argc, char *argv[]) { - srandom((unsigned int)time(NULL)); - ms_global_struct_init(); - - /* initialization */ - ms_setting_init_pre(); - ms_options_parse(argc, argv); - if (ms_check_para()) { - ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION); - exit(1); - } - ms_setting_init_post(); - ms_stats_init(); - ms_thread_init(); - - /* waiting work thread complete its task */ - ms_monitor_slap_mode(); - - /* clean up */ - ms_thread_cleanup(); - ms_global_struct_destroy(); - ms_setting_cleanup(); - - return 0; -} + srandom((unsigned int)time(NULL)); + ms_global_struct_init(); + + /* initialization */ + ms_setting_init_pre(); + ms_options_parse(argc, argv); + if (ms_check_para()) + { + ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION); + exit(1); + } + ms_setting_init_post(); + ms_stats_init(); + ms_thread_init(); + + /* waiting work thread complete its task */ + ms_monitor_slap_mode(); + + /* clean up */ + ms_thread_cleanup(); + ms_global_struct_destroy(); + ms_setting_cleanup(); + + return 0; +} /* main */ diff --git a/clients/ms_conn.c b/clients/ms_conn.c index 69bfaaa9..f4c7347d 100644 --- a/clients/ms_conn.c +++ b/clients/ms_conn.c @@ -19,64 +19,78 @@ #include "ms_thread.h" /* for network write */ -#define TRANSMIT_COMPLETE 0 -#define TRANSMIT_INCOMPLETE 1 -#define TRANSMIT_SOFT_ERROR 2 -#define TRANSMIT_HARD_ERROR 3 +#define TRANSMIT_COMPLETE 0 +#define TRANSMIT_INCOMPLETE 1 +#define TRANSMIT_SOFT_ERROR 2 +#define TRANSMIT_HARD_ERROR 3 /* for generating key */ -#define KEY_PREFIX_BASE 0x1010101010101010 /* not include ' ' '\r' '\n' '\0' */ -#define KEY_PREFIX_MASK 0x1010101010101010 +#define KEY_PREFIX_BASE 0x1010101010101010 /* not include ' ' '\r' '\n' '\0' */ +#define KEY_PREFIX_MASK 0x1010101010101010 /* For parse the value length return by server */ -#define KEY_TOKEN 1 -#define VALUELEN_TOKEN 3 +#define KEY_TOKEN 1 +#define VALUELEN_TOKEN 3 /* global increasing counter, to ensure the key prefix unique */ -static uint64_t key_prefix_seq = KEY_PREFIX_BASE; +static uint64_t key_prefix_seq= KEY_PREFIX_BASE; /* global increasing counter, generating request id for UDP */ -static int udp_request_id = 0; +static int udp_request_id= 0; extern __thread ms_thread_t ms_thread; /* generate upd request id */ static int ms_get_udp_request_id(void); + /* connect initialize */ static void ms_task_init(ms_conn_t *c); static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp); static int ms_conn_sock_init(ms_conn_t *c); static int ms_conn_event_init(ms_conn_t *c); -static int ms_conn_init(ms_conn_t *c, const int init_state, - const int read_buffer_size, const bool is_udp); +static int ms_conn_init(ms_conn_t *c, + const int init_state, + const int read_buffer_size, + const bool is_udp); static void ms_warmup_num_init(ms_conn_t *c); static int ms_item_win_init(ms_conn_t *c); + /* connection close */ void ms_conn_free(ms_conn_t *c); static void ms_conn_close(ms_conn_t *c); + /* create network connection */ static int ms_new_socket(struct addrinfo *ai); static void ms_maximize_sndbuf(const int sfd); -static int ms_network_connect(ms_conn_t *c, char * srv_host_name, - const int srv_port, const bool is_udp, int *ret_sfd); +static int ms_network_connect(ms_conn_t *c, + char *srv_host_name, + const int srv_port, + const bool is_udp, + int *ret_sfd); static int ms_reconn(ms_conn_t *c); + /* read and parse */ -static int ms_tokenize_command(char *command, token_t *tokens, const int max_tokens); +static int ms_tokenize_command(char *command, + token_t *tokens, + const int max_tokens); static int ms_ascii_process_line(ms_conn_t *c, char *command); static int ms_try_read_line(ms_conn_t *c); static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes); static int ms_udp_read(ms_conn_t *c, char *buf, int len); static int ms_try_read_network(ms_conn_t *c); -static void ms_verify_value(ms_conn_t *c, ms_mlget_task_item_t *mlget_item, - char *value, int vlen); +static void ms_verify_value(ms_conn_t *c, + ms_mlget_task_item_t *mlget_item, + char *value, + int vlen); static void ms_ascii_complete_nread(ms_conn_t *c); static void ms_bin_complete_nread(ms_conn_t *c); static void ms_complete_nread(ms_conn_t *c); + /* send functions */ static int ms_add_msghdr(ms_conn_t *c); static int ms_ensure_iov_space(ms_conn_t *c); @@ -84,6 +98,7 @@ static int ms_add_iov(ms_conn_t *c, const void *buf, int len); static int ms_build_udp_headers(ms_conn_t *c); static int ms_transmit(ms_conn_t *c); + /* status adjustment */ static void ms_conn_shrink(ms_conn_t *c); static void ms_conn_set_state(ms_conn_t *c, int state); @@ -94,24 +109,31 @@ static int ms_update_conn_sock_event(ms_conn_t *c); static bool ms_need_yield(ms_conn_t *c); static void ms_update_start_time(ms_conn_t *c); + /* main loop */ static void ms_drive_machine(ms_conn_t *c); void ms_event_handler(const int fd, const short which, void *arg); + /* ascii protocol */ static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item); static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item); static int ms_build_ascii_write_buf_mlget(ms_conn_t *c); + /* binary protocol */ static int ms_bin_process_response(ms_conn_t *c); -static void ms_add_bin_header(ms_conn_t *c, uint8_t opcode, uint8_t hdr_len, - uint16_t key_len, uint32_t body_len); +static void ms_add_bin_header(ms_conn_t *c, + uint8_t opcode, + uint8_t hdr_len, + uint16_t key_len, + uint32_t body_len); static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item); static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item); static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item); static int ms_build_bin_write_buf_mlget(ms_conn_t *c); + /** * each key has two parts, prefix and suffix. The suffix is a * string random get form the character table. The prefix is a @@ -123,16 +145,17 @@ static int ms_build_bin_write_buf_mlget(ms_conn_t *c); */ uint64_t ms_get_key_prefix(void) { - uint64_t key_prefix; + uint64_t key_prefix; - pthread_mutex_lock(&ms_global.seq_mutex); - key_prefix_seq |= KEY_PREFIX_MASK; - key_prefix = key_prefix_seq; - key_prefix_seq++; - pthread_mutex_unlock(&ms_global.seq_mutex); + pthread_mutex_lock(&ms_global.seq_mutex); + key_prefix_seq|= KEY_PREFIX_MASK; + key_prefix= key_prefix_seq; + key_prefix_seq++; + pthread_mutex_unlock(&ms_global.seq_mutex); + + return key_prefix; +} /* ms_get_key_prefix */ - return key_prefix; -} /** * get an unique udp request id @@ -141,9 +164,10 @@ uint64_t ms_get_key_prefix(void) */ static int ms_get_udp_request_id(void) { - return(__sync_fetch_and_add(&udp_request_id, 1)); + return __sync_fetch_and_add(&udp_request_id, 1); } + /** * initialize current task structure * @@ -151,19 +175,20 @@ static int ms_get_udp_request_id(void) */ static void ms_task_init(ms_conn_t *c) { - c->curr_task.cmd = CMD_NULL; - c->curr_task.item = 0; - c->curr_task.verify = false; - c->curr_task.finish_verify = true; - c->curr_task.get_miss = true; - - c->curr_task.get_opt = 0; - c->curr_task.set_opt = 0; - c->curr_task.cycle_undo_get = 0; - c->curr_task.cycle_undo_set = 0; - c->curr_task.verified_get = 0; - c->curr_task.overwrite_set = 0; -} + c->curr_task.cmd= CMD_NULL; + c->curr_task.item= 0; + c->curr_task.verify= false; + c->curr_task.finish_verify= true; + c->curr_task.get_miss= true; + + c->curr_task.get_opt= 0; + c->curr_task.set_opt= 0; + c->curr_task.cycle_undo_get= 0; + c->curr_task.cycle_undo_set= 0; + c->curr_task.verified_get= 0; + c->curr_task.overwrite_set= 0; +} /* ms_task_init */ + /** * initialize udp for the connection structure @@ -175,36 +200,41 @@ static void ms_task_init(ms_conn_t *c) */ static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp) { - c->hdrbuf = 0; - c->rudpbuf = 0; - c->udppkt = 0; - - c->rudpsize = UDP_DATA_BUFFER_SIZE; - c->hdrsize = 0; - - c->rudpbytes = 0; - c->packets = 0; - c->recvpkt = 0; - c->pktcurr = 0; - c->ordcurr = 0; - - c->udp = is_udp; - - if (c->udp || (!c->udp && ms_setting.facebook_test)) { - c->rudpbuf = (char *)malloc((size_t)c->rudpsize); - c->udppkt = (ms_udppkt_t *)malloc(MAX_UDP_PACKET * sizeof(ms_udppkt_t)); - - if (c->rudpbuf == NULL || c->udppkt == NULL) { - if (c->rudpbuf != NULL) free(c->rudpbuf); - if (c->udppkt != NULL) free(c->udppkt); - fprintf(stderr, "malloc()\n"); - return -1; - } - memset(c->udppkt, 0, MAX_UDP_PACKET * sizeof(ms_udppkt_t)); + c->hdrbuf= 0; + c->rudpbuf= 0; + c->udppkt= 0; + + c->rudpsize= UDP_DATA_BUFFER_SIZE; + c->hdrsize= 0; + + c->rudpbytes= 0; + c->packets= 0; + c->recvpkt= 0; + c->pktcurr= 0; + c->ordcurr= 0; + + c->udp= is_udp; + + if (c->udp || (! c->udp && ms_setting.facebook_test)) + { + c->rudpbuf= (char *)malloc((size_t)c->rudpsize); + c->udppkt= (ms_udppkt_t *)malloc(MAX_UDP_PACKET * sizeof(ms_udppkt_t)); + + if ((c->rudpbuf == NULL) || (c->udppkt == NULL)) + { + if (c->rudpbuf != NULL) + free(c->rudpbuf); + if (c->udppkt != NULL) + free(c->udppkt); + fprintf(stderr, "malloc()\n"); + return -1; } + memset(c->udppkt, 0, MAX_UDP_PACKET * sizeof(ms_udppkt_t)); + } + + return 0; +} /* ms_conn_udp_init */ - return 0; -} /** * initialize the connection structure @@ -216,97 +246,120 @@ static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp) * * @return int, if success, return 0, else return -1 */ -static int ms_conn_init(ms_conn_t *c, const int init_state, - const int read_buffer_size, const bool is_udp) +static int ms_conn_init(ms_conn_t *c, + const int init_state, + const int read_buffer_size, + const bool is_udp) { - assert(c != NULL); - - c->rbuf = c->wbuf = 0; - c->iov = 0; - c->msglist = 0; - - c->rsize = read_buffer_size; - c->wsize = WRITE_BUFFER_SIZE; - c->iovsize = IOV_LIST_INITIAL; - c->msgsize = MSG_LIST_INITIAL; - - /* for replication, each connection need connect all the server */ - if (ms_setting.rep_write_srv > 0) { - c->total_sfds = ms_setting.srv_cnt; - } else { - c->total_sfds = ms_setting.sock_per_conn; - } - c->alive_sfds = 0; - - c->rbuf = (char *)malloc((size_t)c->rsize); - c->wbuf = (char *)malloc((size_t)c->wsize); - c->iov = (struct iovec *)malloc(sizeof(struct iovec) * (size_t)c->iovsize); - c->msglist = (struct msghdr *)malloc(sizeof(struct msghdr) * (size_t)c->msgsize); - if (ms_setting.mult_key_num > 1) { - c->mlget_task.mlget_item = (ms_mlget_task_item_t *) - malloc(sizeof(ms_mlget_task_item_t) * (size_t)ms_setting.mult_key_num); - } - c->tcpsfd = (int *)malloc((size_t)c->total_sfds * sizeof(int)); - - if (c->rbuf == NULL || c->wbuf == NULL || c->iov == NULL - || c->msglist == NULL || c->tcpsfd == NULL - || (ms_setting.mult_key_num > 1 && c->mlget_task.mlget_item == NULL)) { - - if (c->rbuf != NULL) free(c->rbuf); - if (c->wbuf != NULL) free(c->wbuf); - if (c->iov != NULL) free(c->iov); - if (c->msglist != NULL) free(c->msglist); - if (c->mlget_task.mlget_item != NULL) free(c->mlget_task.mlget_item); - if (c->tcpsfd != NULL) free(c->tcpsfd); - fprintf(stderr, "malloc()\n"); - return -1; - } - - c->state = init_state; - c->rvbytes = 0; - c->rbytes = 0; - c->rcurr = c->rbuf; - c->wcurr = c->wbuf; - c->iovused = 0; - c->msgcurr = 0; - c->msgused = 0; - c->cur_idx = c->total_sfds; /* default index is a invalid value */ - - c->ctnwrite = false; - c->readval = false; - c->change_sfd = false; - - c->precmd.cmd = c->currcmd.cmd = CMD_NULL; - c->precmd.isfinish = true; /* default the previous command finished */ - c->currcmd.isfinish = false; - c->precmd.retstat = c->currcmd.retstat = MCD_FAILURE; - c->precmd.key_prefix = c->currcmd.key_prefix = 0; - - c->mlget_task.mlget_num = 0; - c->mlget_task.value_index = -1; /* default invalid value */ - - if (ms_setting.binary_prot) { - c->protocol = binary_prot; - } else if (is_udp) { - c->protocol = ascii_udp_prot; - } else { - c->protocol = ascii_prot; - } + assert(c != NULL); + + c->rbuf= c->wbuf= 0; + c->iov= 0; + c->msglist= 0; + + c->rsize= read_buffer_size; + c->wsize= WRITE_BUFFER_SIZE; + c->iovsize= IOV_LIST_INITIAL; + c->msgsize= MSG_LIST_INITIAL; + + /* for replication, each connection need connect all the server */ + if (ms_setting.rep_write_srv > 0) + { + c->total_sfds= ms_setting.srv_cnt; + } + else + { + c->total_sfds= ms_setting.sock_per_conn; + } + c->alive_sfds= 0; + + c->rbuf= (char *)malloc((size_t)c->rsize); + c->wbuf= (char *)malloc((size_t)c->wsize); + c->iov= (struct iovec *)malloc(sizeof(struct iovec) * (size_t)c->iovsize); + c->msglist= (struct msghdr *)malloc( + sizeof(struct msghdr) * (size_t)c->msgsize); + if (ms_setting.mult_key_num > 1) + { + c->mlget_task.mlget_item= (ms_mlget_task_item_t *) + malloc( + sizeof(ms_mlget_task_item_t) * (size_t)ms_setting.mult_key_num); + } + c->tcpsfd= (int *)malloc((size_t)c->total_sfds * sizeof(int)); + + if ((c->rbuf == NULL) || (c->wbuf == NULL) || (c->iov == NULL) + || (c->msglist == NULL) || (c->tcpsfd == NULL) + || ((ms_setting.mult_key_num > 1) + && (c->mlget_task.mlget_item == NULL))) + { + if (c->rbuf != NULL) + free(c->rbuf); + if (c->wbuf != NULL) + free(c->wbuf); + if (c->iov != NULL) + free(c->iov); + if (c->msglist != NULL) + free(c->msglist); + if (c->mlget_task.mlget_item != NULL) + free(c->mlget_task.mlget_item); + if (c->tcpsfd != NULL) + free(c->tcpsfd); + fprintf(stderr, "malloc()\n"); + return -1; + } + + c->state= init_state; + c->rvbytes= 0; + c->rbytes= 0; + c->rcurr= c->rbuf; + c->wcurr= c->wbuf; + c->iovused= 0; + c->msgcurr= 0; + c->msgused= 0; + c->cur_idx= c->total_sfds; /* default index is a invalid value */ + + c->ctnwrite= false; + c->readval= false; + c->change_sfd= false; + + c->precmd.cmd= c->currcmd.cmd= CMD_NULL; + c->precmd.isfinish= true; /* default the previous command finished */ + c->currcmd.isfinish= false; + c->precmd.retstat= c->currcmd.retstat= MCD_FAILURE; + c->precmd.key_prefix= c->currcmd.key_prefix= 0; + + c->mlget_task.mlget_num= 0; + c->mlget_task.value_index= -1; /* default invalid value */ + + if (ms_setting.binary_prot) + { + c->protocol= binary_prot; + } + else if (is_udp) + { + c->protocol= ascii_udp_prot; + } + else + { + c->protocol= ascii_prot; + } + + /* initialize udp */ + if (ms_conn_udp_init(c, is_udp) != 0) + { + return -1; + } - /* initialize udp */ - if (ms_conn_udp_init(c, is_udp) != 0) { - return -1; - } + /* initialize task */ + ms_task_init(c); - /* initialize task */ - ms_task_init(c); + if (! (ms_setting.facebook_test && is_udp)) + { + __sync_fetch_and_add(&ms_stats.active_conns, 1); + } - if (!(ms_setting.facebook_test && is_udp)) { - __sync_fetch_and_add(&ms_stats.active_conns, 1); - } + return 0; +} /* ms_conn_init */ - return 0; -} /** * when doing 100% get operation, it could preset some objects @@ -317,15 +370,19 @@ static int ms_conn_init(ms_conn_t *c, const int init_state, */ static void ms_warmup_num_init(ms_conn_t *c) { - /* no set operation, preset all the items in the window */ - if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR) { - c->warmup_num = c->win_size; - c->remain_warmup_num = c->warmup_num; - } else { - c->warmup_num = 0; - c->remain_warmup_num = c->warmup_num; - } -} + /* no set operation, preset all the items in the window */ + if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR) + { + c->warmup_num= c->win_size; + c->remain_warmup_num= c->warmup_num; + } + else + { + c->warmup_num= 0; + c->remain_warmup_num= c->warmup_num; + } +} /* ms_warmup_num_init */ + /** * each connection has an item window, this function initialize @@ -337,41 +394,48 @@ static void ms_warmup_num_init(ms_conn_t *c) */ static int ms_item_win_init(ms_conn_t *c) { - int exp_cnt = 0; + int exp_cnt= 0; + + c->win_size= (int)ms_setting.win_size; + c->set_cursor= 0; + c->exec_num= ms_thread.thread_ctx->exec_num_perconn; + c->remain_exec_num= c->exec_num; + + c->item_win= (ms_task_item_t *)malloc( + sizeof(ms_task_item_t) * (size_t)c->win_size); + if (c->item_win == NULL) + { + fprintf(stderr, "Can't allocate task item array for conn.\n"); + return -1; + } + memset(c->item_win, 0, sizeof(ms_task_item_t) * (size_t)c->win_size); - c->win_size = (int)ms_setting.win_size; - c->set_cursor = 0; - c->exec_num = ms_thread.thread_ctx->exec_num_perconn; - c->remain_exec_num = c->exec_num; + for (int i= 0; i < c->win_size; i++) + { + c->item_win[i].key_size= (int)ms_setting.distr[i].key_size; + c->item_win[i].key_prefix= ms_get_key_prefix(); + c->item_win[i].key_suffix_offset= ms_setting.distr[i].key_offset; + c->item_win[i].value_size= (int)ms_setting.distr[i].value_size; + c->item_win[i].value_offset= INVALID_OFFSET; /* default in invalid offset */ + c->item_win[i].client_time= 0; - c->item_win = (ms_task_item_t *)malloc(sizeof(ms_task_item_t) * (size_t)c->win_size); - if (c->item_win == NULL) { - fprintf(stderr, "Can't allocate task item array for conn.\n"); - return -1; + /* set expire time base on the proportion */ + if (exp_cnt < ms_setting.exp_ver_per * i) + { + c->item_win[i].exp_time= FIXED_EXPIRE_TIME; + exp_cnt++; } - memset(c->item_win, 0, sizeof(ms_task_item_t) * (size_t)c->win_size); - - for (int i = 0; i < c->win_size; i++) { - c->item_win[i].key_size = (int)ms_setting.distr[i].key_size; - c->item_win[i].key_prefix = ms_get_key_prefix(); - c->item_win[i].key_suffix_offset = ms_setting.distr[i].key_offset; - c->item_win[i].value_size = (int)ms_setting.distr[i].value_size; - c->item_win[i].value_offset = INVALID_OFFSET; /* default in invalid offset */ - c->item_win[i].client_time = 0; - - /* set expire time base on the proportion */ - if (exp_cnt < ms_setting.exp_ver_per * i) { - c->item_win[i].exp_time = FIXED_EXPIRE_TIME; - exp_cnt++; - } else { - c->item_win[i].exp_time = 0; - } + else + { + c->item_win[i].exp_time= 0; } + } - ms_warmup_num_init(c); + ms_warmup_num_init(c); + + return 0; +} /* ms_item_win_init */ - return 0; -} /** * each connection structure can include one or more sock @@ -384,70 +448,88 @@ static int ms_item_win_init(ms_conn_t *c) */ static int ms_conn_sock_init(ms_conn_t *c) { - int i; - int ret_sfd; - int srv_idx = 0; - - assert(c != NULL); - assert(c->tcpsfd != NULL); - - for (i = 0; i < c->total_sfds; i++) { - ret_sfd = 0; - if (ms_setting.rep_write_srv > 0) { - /* for replication, each connection need connect all the server */ - srv_idx = i; - } else { - /* all the connections in a thread connects the same server */ - srv_idx = ms_thread.thread_ctx->srv_idx; - } + int i; + int ret_sfd; + int srv_idx= 0; - if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port, - ms_setting.udp, &ret_sfd) != 0) { - break; - } + assert(c != NULL); + assert(c->tcpsfd != NULL); - if (i == 0) { - c->sfd = ret_sfd; - } + for (i= 0; i < c->total_sfds; i++) + { + ret_sfd= 0; + if (ms_setting.rep_write_srv > 0) + { + /* for replication, each connection need connect all the server */ + srv_idx= i; + } + else + { + /* all the connections in a thread connects the same server */ + srv_idx= ms_thread.thread_ctx->srv_idx; + } - if (!ms_setting.udp) { - c->tcpsfd[i] = ret_sfd; - } + if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port, + ms_setting.udp, &ret_sfd) != 0) + { + break; + } - c->alive_sfds++; + if (i == 0) + { + c->sfd= ret_sfd; } - /* initialize udp sock handler if necessary */ - if (ms_setting.facebook_test) { - ret_sfd = 0; - if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port, - true, &ret_sfd) != 0) { - c->udpsfd = 0; - } else { - c->udpsfd = ret_sfd; - } + if (! ms_setting.udp) + { + c->tcpsfd[i]= ret_sfd; } - if (i != c->total_sfds || (ms_setting.facebook_test && c->udpsfd == 0)) { - if (ms_setting.udp) { - close(c->sfd); - } else { - for (int j = 0; j < i; j++) { - close(c->tcpsfd[j]); - } - } + c->alive_sfds++; + } - if (c->udpsfd != 0) { - close(c->udpsfd); - } + /* initialize udp sock handler if necessary */ + if (ms_setting.facebook_test) + { + ret_sfd= 0; + if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port, + true, &ret_sfd) != 0) + { + c->udpsfd= 0; + } + else + { + c->udpsfd= ret_sfd; + } + } - return -1; + if ((i != c->total_sfds) || (ms_setting.facebook_test && (c->udpsfd == 0))) + { + if (ms_setting.udp) + { + close(c->sfd); + } + else + { + for (int j= 0; j < i; j++) + { + close(c->tcpsfd[j]); + } } - return 0; -} + if (c->udpsfd != 0) + { + close(c->udpsfd); + } + + return -1; + } + + return 0; +} /* ms_conn_sock_init */ + /** * each connection is managed by libevent, this function @@ -459,26 +541,35 @@ static int ms_conn_sock_init(ms_conn_t *c) */ static int ms_conn_event_init(ms_conn_t *c) { - /* default event timeout 10 seconds */ - struct timeval t = {.tv_sec = EVENT_TIMEOUT, .tv_usec = 0}; - short event_flags = EV_WRITE | EV_PERSIST; + /* default event timeout 10 seconds */ + struct timeval t= + { + .tv_sec= EVENT_TIMEOUT, .tv_usec= 0 + }; + short event_flags= EV_WRITE | EV_PERSIST; - event_set(&c->event, c->sfd, event_flags, ms_event_handler, (void *)c); - event_base_set(ms_thread.base, &c->event); - c->ev_flags = event_flags; + event_set(&c->event, c->sfd, event_flags, ms_event_handler, (void *)c); + event_base_set(ms_thread.base, &c->event); + c->ev_flags= event_flags; - if (c->total_sfds == 1) { - if (event_add(&c->event, NULL) == -1) { - return -1; - } - } else { - if (event_add(&c->event, &t) == -1) { - return -1; - } + if (c->total_sfds == 1) + { + if (event_add(&c->event, NULL) == -1) + { + return -1; } + } + else + { + if (event_add(&c->event, &t) == -1) + { + return -1; + } + } + + return 0; +} /* ms_conn_event_init */ - return 0; -} /** * setup a connection, each connection structure of each @@ -490,24 +581,29 @@ static int ms_conn_event_init(ms_conn_t *c) */ int ms_setup_conn(ms_conn_t *c) { - if (ms_item_win_init(c) != 0) { - return -1; - } + if (ms_item_win_init(c) != 0) + { + return -1; + } - if (ms_conn_init(c, conn_write, DATA_BUFFER_SIZE, ms_setting.udp) != 0) { - return -1; - } + if (ms_conn_init(c, conn_write, DATA_BUFFER_SIZE, ms_setting.udp) != 0) + { + return -1; + } - if (ms_conn_sock_init(c) != 0) { - return -1; - } + if (ms_conn_sock_init(c) != 0) + { + return -1; + } - if (ms_conn_event_init(c) != 0) { - return -1; - } + if (ms_conn_event_init(c) != 0) + { + return -1; + } + + return 0; +} /* ms_setup_conn */ - return 0; -} /** * Frees a connection. @@ -516,33 +612,36 @@ int ms_setup_conn(ms_conn_t *c) */ void ms_conn_free(ms_conn_t *c) { - if (c != NULL) { - if (c->hdrbuf != NULL) - free(c->hdrbuf); - if (c->msglist != NULL) - free(c->msglist); - if (c->rbuf != NULL) - free(c->rbuf); - if (c->wbuf != NULL) - free(c->wbuf); - if (c->iov != NULL) - free(c->iov); - if (c->mlget_task.mlget_item != NULL) - free(c->mlget_task.mlget_item); - if (c->rudpbuf != NULL) - free(c->rudpbuf); - if (c->udppkt != NULL) - free(c->udppkt); - if (c->item_win != NULL) - free(c->item_win); - if (c->tcpsfd != NULL) - free(c->tcpsfd); - - if (--ms_thread.nactive_conn == 0) { - free(ms_thread.conn); - } - } -} + if (c != NULL) + { + if (c->hdrbuf != NULL) + free(c->hdrbuf); + if (c->msglist != NULL) + free(c->msglist); + if (c->rbuf != NULL) + free(c->rbuf); + if (c->wbuf != NULL) + free(c->wbuf); + if (c->iov != NULL) + free(c->iov); + if (c->mlget_task.mlget_item != NULL) + free(c->mlget_task.mlget_item); + if (c->rudpbuf != NULL) + free(c->rudpbuf); + if (c->udppkt != NULL) + free(c->udppkt); + if (c->item_win != NULL) + free(c->item_win); + if (c->tcpsfd != NULL) + free(c->tcpsfd); + + if (--ms_thread.nactive_conn == 0) + { + free(ms_thread.conn); + } + } +} /* ms_conn_free */ + /** * close a connection @@ -551,37 +650,43 @@ void ms_conn_free(ms_conn_t *c) */ static void ms_conn_close(ms_conn_t *c) { - assert(c != NULL); + assert(c != NULL); - /* delete the event, the socket and the connection */ - event_del(&c->event); + /* delete the event, the socket and the connection */ + event_del(&c->event); - for (int i = 0; i < c->total_sfds; i++) { - if (c->tcpsfd[i] > 0) { - close(c->tcpsfd[i]); - } + for (int i= 0; i < c->total_sfds; i++) + { + if (c->tcpsfd[i] > 0) + { + close(c->tcpsfd[i]); } - c->sfd = 0; + } + c->sfd= 0; - if (ms_setting.facebook_test) { - close(c->udpsfd); - } + if (ms_setting.facebook_test) + { + close(c->udpsfd); + } - __sync_fetch_and_sub(&ms_stats.active_conns, 1); + __sync_fetch_and_sub(&ms_stats.active_conns, 1); - ms_conn_free(c); + ms_conn_free(c); - if (ms_setting.run_time == 0) { - pthread_mutex_lock(&ms_global.run_lock.lock); - ms_global.run_lock.count++; - pthread_cond_signal(&ms_global.run_lock.cond); - pthread_mutex_unlock(&ms_global.run_lock.lock); - } + if (ms_setting.run_time == 0) + { + pthread_mutex_lock(&ms_global.run_lock.lock); + ms_global.run_lock.count++; + pthread_cond_signal(&ms_global.run_lock.cond); + pthread_mutex_unlock(&ms_global.run_lock.lock); + } + + if (ms_thread.nactive_conn == 0) + { + pthread_exit(NULL); + } +} /* ms_conn_close */ - if (ms_thread.nactive_conn == 0) { - pthread_exit(NULL); - } -} /** * create a new sock @@ -592,15 +697,17 @@ static void ms_conn_close(ms_conn_t *c) */ static int ms_new_socket(struct addrinfo *ai) { - int sfd; + int sfd; - if ((sfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) { - fprintf(stderr, "socket() error: %s.\n", strerror(errno)); - return -1; - } + if ((sfd= socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) + { + fprintf(stderr, "socket() error: %s.\n", strerror(errno)); + return -1; + } + + return sfd; +} /* ms_new_socket */ - return sfd; -} /** * Sets a socket's send buffer size to the maximum allowed by the system. @@ -609,31 +716,37 @@ static int ms_new_socket(struct addrinfo *ai) */ static void ms_maximize_sndbuf(const int sfd) { - socklen_t intsize = sizeof(int); - unsigned int last_good = 0; - unsigned int min, max, avg; - unsigned int old_size; - - /* Start with the default size. */ - if (getsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &old_size, &intsize) != 0) { - fprintf(stderr, "getsockopt(SO_SNDBUF)\n"); - return; - } - - /* Binary-search for the real maximum. */ - min = old_size; - max = MAX_SENDBUF_SIZE; - - while (min <= max) { - avg = ((unsigned int)(min + max)) / 2; - if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void *)&avg, intsize) == 0) { - last_good = avg; - min = avg + 1; - } else { - max = avg - 1; - } + socklen_t intsize= sizeof(int); + unsigned int last_good= 0; + unsigned int min, max, avg; + unsigned int old_size; + + /* Start with the default size. */ + if (getsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &old_size, &intsize) != 0) + { + fprintf(stderr, "getsockopt(SO_SNDBUF)\n"); + return; + } + + /* Binary-search for the real maximum. */ + min= old_size; + max= MAX_SENDBUF_SIZE; + + while (min <= max) + { + avg= ((unsigned int)(min + max)) / 2; + if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void *)&avg, intsize) == 0) + { + last_good= avg; + min= avg + 1; } -} + else + { + max= avg - 1; + } + } +} /* ms_maximize_sndbuf */ + /** * socket connects the server @@ -646,93 +759,117 @@ static void ms_maximize_sndbuf(const int sfd) * * @return int, if success, return 0, else return -1 */ -static int ms_network_connect(ms_conn_t *c, char * srv_host_name, - const int srv_port, const bool is_udp, int *ret_sfd) +static int ms_network_connect(ms_conn_t *c, + char *srv_host_name, + const int srv_port, + const bool is_udp, + int *ret_sfd) { - int sfd; - struct linger ling = {0, 0}; - struct addrinfo *ai; - struct addrinfo *next; - struct addrinfo hints; - char port_buf[NI_MAXSERV]; - int error; - int success = 0; - - int flags = 1; - - /* - * the memset call clears nonstandard fields in some impementations - * that otherwise mess things up. - */ - memset(&hints, 0, sizeof (hints)); - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - if (is_udp) { - hints.ai_protocol = IPPROTO_UDP; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_family = AF_INET; /* This left here because of issues with OSX 10.5 */ - } else { - hints.ai_family = AF_UNSPEC; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_socktype = SOCK_STREAM; - } - - snprintf(port_buf, NI_MAXSERV, "%d", srv_port); - error= getaddrinfo(srv_host_name, port_buf, &hints, &ai); - if (error != 0) { - if (error != EAI_SYSTEM) - fprintf(stderr, "getaddrinfo(): %s.\n", gai_strerror(error)); - else - perror("getaddrinfo()\n"); + int sfd; + struct linger ling= + { + 0, 0 + }; + struct addrinfo *ai; + struct addrinfo *next; + struct addrinfo hints; + char port_buf[NI_MAXSERV]; + int error; + int success= 0; + + int flags= 1; + + /* + * the memset call clears nonstandard fields in some impementations + * that otherwise mess things up. + */ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags= AI_PASSIVE | AI_ADDRCONFIG; + if (is_udp) + { + hints.ai_protocol= IPPROTO_UDP; + hints.ai_socktype= SOCK_DGRAM; + hints.ai_family= AF_INET; /* This left here because of issues with OSX 10.5 */ + } + else + { + hints.ai_family= AF_UNSPEC; + hints.ai_protocol= IPPROTO_TCP; + hints.ai_socktype= SOCK_STREAM; + } + + snprintf(port_buf, NI_MAXSERV, "%d", srv_port); + error= getaddrinfo(srv_host_name, port_buf, &hints, &ai); + if (error != 0) + { + if (error != EAI_SYSTEM) + fprintf(stderr, "getaddrinfo(): %s.\n", gai_strerror(error)); + else + perror("getaddrinfo()\n"); + return -1; + } + + for (next= ai; next; next= next->ai_next) + { + if ((sfd= ms_new_socket(next)) == -1) + { + freeaddrinfo(ai); + return -1; + } + + setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); + if (is_udp) + { + ms_maximize_sndbuf(sfd); + } + else + { + setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, + sizeof(flags)); + setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); + setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, + sizeof(flags)); + } + + if (is_udp) + { + c->srv_recv_addr_size= sizeof(struct sockaddr); + memcpy(&c->srv_recv_addr, next->ai_addr, c->srv_recv_addr_size); + } + else + { + if (connect(sfd, next->ai_addr, next->ai_addrlen) == -1) + { + close(sfd); + freeaddrinfo(ai); return -1; + } } - for (next = ai; next; next = next->ai_next) { - if ((sfd = ms_new_socket(next)) == -1) { - freeaddrinfo(ai); - return -1; - } - - setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); - if (is_udp) { - ms_maximize_sndbuf(sfd); - } else { - setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)); - setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); - setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); - } - - if (is_udp) { - c->srv_recv_addr_size = sizeof(struct sockaddr); - memcpy(&c->srv_recv_addr, next->ai_addr, c->srv_recv_addr_size); - } else { - if (connect(sfd, next->ai_addr, next->ai_addrlen) == -1) { - close(sfd); - freeaddrinfo(ai); - return -1; - } - } + if (((flags= fcntl(sfd, F_GETFL, 0)) < 0) + || (fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0)) + { + fprintf(stderr, "setting O_NONBLOCK\n"); + close(sfd); + freeaddrinfo(ai); + return -1; + } - if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 || - fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) { - fprintf(stderr, "setting O_NONBLOCK\n"); - close(sfd); - freeaddrinfo(ai); - return -1; - } + if (ret_sfd != NULL) + { + *ret_sfd= sfd; + } - if (ret_sfd != NULL) { - *ret_sfd = sfd; - } + success++; + } - success++; - } + freeaddrinfo(ai); - freeaddrinfo(ai); + /* Return zero if we detected no errors in starting up connections */ + return success == 0; +} /* ms_network_connect */ - /* Return zero if we detected no errors in starting up connections */ - return success == 0; -} /** * reconnect a disconnected sock @@ -743,77 +880,93 @@ static int ms_network_connect(ms_conn_t *c, char * srv_host_name, */ static int ms_reconn(ms_conn_t *c) { - int srv_idx = 0; - int srv_conn_cnt = 0; - - if (ms_setting.rep_write_srv > 0) { - srv_idx = c->cur_idx; - srv_conn_cnt = ms_setting.nconns; - } else { - srv_idx = ms_thread.thread_ctx->srv_idx; - srv_conn_cnt = ms_setting.nconns / ms_setting.srv_cnt; - } - - /* close the old socket handler */ - close(c->sfd); - c->tcpsfd[c->cur_idx] = 0; - - if (__sync_fetch_and_add(&ms_setting.servers[srv_idx].disconn_cnt, 1) - % srv_conn_cnt == 0) { + int srv_idx= 0; + int srv_conn_cnt= 0; + + if (ms_setting.rep_write_srv > 0) + { + srv_idx= c->cur_idx; + srv_conn_cnt= ms_setting.nconns; + } + else + { + srv_idx= ms_thread.thread_ctx->srv_idx; + srv_conn_cnt= ms_setting.nconns / ms_setting.srv_cnt; + } + + /* close the old socket handler */ + close(c->sfd); + c->tcpsfd[c->cur_idx]= 0; + + if (__sync_fetch_and_add(&ms_setting.servers[srv_idx].disconn_cnt, 1) + % srv_conn_cnt == 0) + { + gettimeofday(&ms_setting.servers[srv_idx].disconn_time, NULL); + fprintf(stderr, "Server %s:%d disconnect\n", + ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port); + } + + if (ms_setting.rep_write_srv > 0) + { + int i= 0; + for (i= 0; i < c->total_sfds; i++) + { + if (c->tcpsfd[i] != 0) + { + break; + } + } + + /* all socks disconnect */ + if (i == c->total_sfds) + { + return -1; + } + } + else + { + do + { + /* reconnect success, break the loop */ + if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port, + ms_setting.udp, &c->sfd) == 0) + { + c->tcpsfd[c->cur_idx]= c->sfd; + if (__sync_fetch_and_add(&ms_setting.servers[srv_idx].reconn_cnt, 1) + % srv_conn_cnt == 0) + { + gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL); + int reconn_time= + (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec + - ms_setting.servers[srv_idx].disconn_time + .tv_sec); + fprintf(stderr, "Server %s:%d reconnect after %ds\n", + ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port, reconn_time); + } + break; + } - gettimeofday(&ms_setting.servers[srv_idx].disconn_time, NULL); - fprintf(stderr, "Server %s:%d disconnect\n", - ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port); + if (c->total_sfds == 1) + { + /* wait a second and reconnect */ + sleep(1); + } } + while (c->total_sfds == 1); + } - if (ms_setting.rep_write_srv > 0) { - int i = 0; - for (i = 0; i < c->total_sfds; i++) { - if (c->tcpsfd[i] != 0) { - break; - } - } + if ((c->total_sfds > 1) && (c->tcpsfd[c->cur_idx] == 0)) + { + c->sfd= 0; + c->alive_sfds--; + } - /* all socks disconnect */ - if (i == c->total_sfds) { - return -1; - } - } else { - do { - /* reconnect success, break the loop */ - if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port, - ms_setting.udp, &c->sfd) == 0) { - - c->tcpsfd[c->cur_idx] = c->sfd; - if (__sync_fetch_and_add(&ms_setting.servers[srv_idx].reconn_cnt, 1) - % srv_conn_cnt == 0) { - - gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL); - int reconn_time = (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec - - ms_setting.servers[srv_idx].disconn_time.tv_sec); - fprintf(stderr, "Server %s:%d reconnect after %ds\n", - ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port, reconn_time); - } - break; - } - - if (c->total_sfds == 1) { - /* wait a second and reconnect */ - sleep(1); - } - } while (c->total_sfds == 1); - } - - if (c->total_sfds > 1 && c->tcpsfd[c->cur_idx] == 0) { - c->sfd = 0; - c->alive_sfds--; - } + return 0; +} /* ms_reconn */ - return 0; -} /** * reconnect several disconnected socks in the connection @@ -827,62 +980,73 @@ static int ms_reconn(ms_conn_t *c) */ int ms_reconn_socks(ms_conn_t *c) { - int srv_idx = 0; - int ret_sfd = 0; - int srv_conn_cnt = 0; - struct timeval cur_time; + int srv_idx= 0; + int ret_sfd= 0; + int srv_conn_cnt= 0; + struct timeval cur_time; - assert(c != NULL); + assert(c != NULL); - if (c->total_sfds == 1 || c->total_sfds == c->alive_sfds) { - return 0; - } + if ((c->total_sfds == 1) || (c->total_sfds == c->alive_sfds)) + { + return 0; + } + + for (int i= 0; i < c->total_sfds; i++) + { + if (c->tcpsfd[i] == 0) + { + gettimeofday(&cur_time, NULL); + + /** + * For failover test of replication, reconnect the socks after + * it disconnects more than 5 seconds, Otherwise memslap will + * block at connect() function and the work threads can't work + * in this interval. + */ + if (cur_time.tv_sec + - ms_setting.servers[srv_idx].disconn_time.tv_sec < 5) + { + break; + } + + if (ms_setting.rep_write_srv > 0) + { + srv_idx= i; + srv_conn_cnt= ms_setting.nconns; + } + else + { + srv_idx= ms_thread.thread_ctx->srv_idx; + srv_conn_cnt= ms_setting.nconns / ms_setting.srv_cnt; + } + + if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port, + ms_setting.udp, &ret_sfd) == 0) + { + c->tcpsfd[i]= ret_sfd; + c->alive_sfds++; - for (int i = 0; i < c->total_sfds; i++) { - if (c->tcpsfd[i] == 0) { - gettimeofday(&cur_time, NULL); - - /** - * For failover test of replication, reconnect the socks after - * it disconnects more than 5 seconds, Otherwise memslap will - * block at connect() function and the work threads can't work - * in this interval. - */ - if (cur_time.tv_sec - ms_setting.servers[srv_idx].disconn_time.tv_sec < 5) { - break; - } - - if (ms_setting.rep_write_srv > 0) { - srv_idx = i; - srv_conn_cnt = ms_setting.nconns; - } else { - srv_idx = ms_thread.thread_ctx->srv_idx; - srv_conn_cnt = ms_setting.nconns / ms_setting.srv_cnt; - } - - if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port, - ms_setting.udp, &ret_sfd) == 0) { - - c->tcpsfd[i] = ret_sfd; - c->alive_sfds++; - - if (__sync_fetch_and_add(&ms_setting.servers[srv_idx].reconn_cnt, 1) - % srv_conn_cnt == 0) { - - gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL); - int reconn_time = (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec - - ms_setting.servers[srv_idx].disconn_time.tv_sec); - fprintf(stderr, "Server %s:%d reconnect after %ds\n", - ms_setting.servers[srv_idx].srv_host_name, - ms_setting.servers[srv_idx].srv_port, reconn_time); - } - } + if (__sync_fetch_and_add(&ms_setting.servers[srv_idx].reconn_cnt, 1) + % srv_conn_cnt == 0) + { + gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL); + int reconn_time= + (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec + - ms_setting.servers[srv_idx].disconn_time + .tv_sec); + fprintf(stderr, "Server %s:%d reconnect after %ds\n", + ms_setting.servers[srv_idx].srv_host_name, + ms_setting.servers[srv_idx].srv_port, reconn_time); } + } } + } + + return 0; +} /* ms_reconn_socks */ - return 0; -} /** * Tokenize the command string by replacing whitespace with '\0' and update @@ -907,35 +1071,44 @@ int ms_reconn_socks(ms_conn_t *c) * * @return int, the number of tokens */ -static int ms_tokenize_command(char *command, token_t *tokens, const int max_tokens) +static int ms_tokenize_command(char *command, + token_t *tokens, + const int max_tokens) { - char *s, *e; - int ntokens = 0; - - assert(command != NULL && tokens != NULL && max_tokens > 1); - - for (s = e = command; ntokens < max_tokens - 1; ++e) { - if (*e == ' ') { - if (s != e) { - tokens[ntokens].value = s; - tokens[ntokens].length = (size_t)(e - s); - ntokens++; - *e = '\0'; - } - s = e + 1; - } else if (*e == '\0') { - if (s != e) { - tokens[ntokens].value = s; - tokens[ntokens].length = (size_t)(e - s); - ntokens++; - } - - break; /* string end */ - } + char *s, *e; + int ntokens= 0; + + assert(command != NULL && tokens != NULL && max_tokens > 1); + + for (s= e= command; ntokens < max_tokens - 1; ++e) + { + if (*e == ' ') + { + if (s != e) + { + tokens[ntokens].value= s; + tokens[ntokens].length= (size_t)(e - s); + ntokens++; + *e= '\0'; + } + s= e + 1; } + else if (*e == '\0') + { + if (s != e) + { + tokens[ntokens].value= s; + tokens[ntokens].length= (size_t)(e - s); + ntokens++; + } + + break; /* string end */ + } + } + + return ntokens; +} /* ms_tokenize_command */ - return ntokens; -} /** * parse the response of server. @@ -948,106 +1121,130 @@ static int ms_tokenize_command(char *command, token_t *tokens, const int max_tok */ static int ms_ascii_process_line(ms_conn_t *c, char *command) { - int ret = 0; - int64_t value_len; - char *buffer = command; + int ret= 0; + int64_t value_len; + char *buffer= command; + + assert(c != NULL); + + /** + * for command get, we store the returned value into local buffer + * then continue in ms_complete_nread(). + */ - assert(c != NULL); + switch (buffer[0]) + { + case 'V': /* VALUE || VERSION */ + if (buffer[1] == 'A') /* VALUE */ + { + token_t tokens[MAX_TOKENS]; + ms_tokenize_command(command, tokens, MAX_TOKENS); + value_len= strtol(tokens[VALUELEN_TOKEN].value, NULL, 10); + c->currcmd.key_prefix= *(uint64_t *)tokens[KEY_TOKEN].value; + + /* + * We read the \r\n into the string since not doing so is more + * cycles then the waster of memory to do so. + * + * We are null terminating through, which will most likely make + * some people lazy about using the return length. + */ + c->rvbytes= (int)(value_len + 2); + c->readval= true; + ret= -1; + } - /** - * for command get, we store the returned value into local buffer - * then continue in ms_complete_nread(). - */ + break; - switch (buffer[0]) { - case 'V': /* VALUE || VERSION */ - if (buffer[1] == 'A') { /* VALUE */ - token_t tokens[MAX_TOKENS]; - ms_tokenize_command(command, tokens, MAX_TOKENS); - value_len = strtol(tokens[VALUELEN_TOKEN].value, NULL, 10); - c->currcmd.key_prefix = *(uint64_t *)tokens[KEY_TOKEN].value; - - /* - We read the \r\n into the string since not doing so is more - cycles then the waster of memory to do so. - - We are null terminating through, which will most likely make - some people lazy about using the return length. - */ - c->rvbytes = (int)(value_len + 2); - c->readval = true; - ret = -1; - } + case 'O': /* OK */ + c->currcmd.retstat= MCD_SUCCESS; - break; + case 'S': /* STORED STATS SERVER_ERROR */ + if (buffer[2] == 'A') /* STORED STATS */ + { /* STATS*/ + c->currcmd.retstat= MCD_STAT; + } + else if (buffer[1] == 'E') + { + /* SERVER_ERROR */ + printf("<%d %s\n", c->sfd, buffer); - case 'O': /* OK */ - c->currcmd.retstat = MCD_SUCCESS; - - case 'S': /* STORED STATS SERVER_ERROR */ - if (buffer[2] == 'A') {/* STORED STATS */ - /* STATS*/ - c->currcmd.retstat = MCD_STAT; - } else if (buffer[1] == 'E') { - /* SERVER_ERROR */ - printf("<%d %s\n", c->sfd, buffer); - - c->currcmd.retstat = MCD_SERVER_ERROR; - } else if (buffer[1] == 'T') { - /* STORED */ - c->currcmd.retstat = MCD_STORED; - } else { - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - } - break; + c->currcmd.retstat= MCD_SERVER_ERROR; + } + else if (buffer[1] == 'T') + { + /* STORED */ + c->currcmd.retstat= MCD_STORED; + } + else + { + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + } + break; - case 'D': /* DELETED DATA */ - if (buffer[1] == 'E') { - c->currcmd.retstat = MCD_DELETED; - } else { - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - } + case 'D': /* DELETED DATA */ + if (buffer[1] == 'E') + { + c->currcmd.retstat= MCD_DELETED; + } + else + { + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + } - break; + break; - case 'N': /* NOT_FOUND NOT_STORED*/ - if (buffer[4] == 'F') { - c->currcmd.retstat = MCD_NOTFOUND; - } else if (buffer[4] == 'S') { - printf("<%d %s\n", c->sfd, buffer); - c->currcmd.retstat = MCD_NOTSTORED; - } else { - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - } - break; + case 'N': /* NOT_FOUND NOT_STORED*/ + if (buffer[4] == 'F') + { + c->currcmd.retstat= MCD_NOTFOUND; + } + else if (buffer[4] == 'S') + { + printf("<%d %s\n", c->sfd, buffer); + c->currcmd.retstat= MCD_NOTSTORED; + } + else + { + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + } + break; - case 'E': /* PROTOCOL ERROR or END */ - if (buffer[1] == 'N') { - /* END */ - c->currcmd.retstat = MCD_END; - } else if (buffer[1] == 'R') { - printf("<%d ERROR\n", c->sfd); - c->currcmd.retstat = MCD_PROTOCOL_ERROR; - } else if (buffer[1] == 'X') { - c->currcmd.retstat = MCD_DATA_EXISTS; - printf("<%d %s\n", c->sfd, buffer); - } else { - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - } - break; + case 'E': /* PROTOCOL ERROR or END */ + if (buffer[1] == 'N') + { + /* END */ + c->currcmd.retstat= MCD_END; + } + else if (buffer[1] == 'R') + { + printf("<%d ERROR\n", c->sfd); + c->currcmd.retstat= MCD_PROTOCOL_ERROR; + } + else if (buffer[1] == 'X') + { + c->currcmd.retstat= MCD_DATA_EXISTS; + printf("<%d %s\n", c->sfd, buffer); + } + else + { + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + } + break; - case 'C': /* CLIENT ERROR */ - printf("<%d %s\n", c->sfd, buffer); - c->currcmd.retstat = MCD_CLIENT_ERROR; - break; + case 'C': /* CLIENT ERROR */ + printf("<%d %s\n", c->sfd, buffer); + c->currcmd.retstat= MCD_CLIENT_ERROR; + break; - default: - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - break; - } + default: + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + break; + } /* switch */ + + return ret; +} /* ms_ascii_process_line */ - return ret; -} /** * after one operation completes, reset the concurrency @@ -1057,30 +1254,34 @@ static int ms_ascii_process_line(ms_conn_t *c, char *command) */ void ms_reset_conn(ms_conn_t *c, bool timeout) { - assert(c != NULL); - - if (c->udp) { - if (c->packets > 0 && c->packets < MAX_UDP_PACKET) { - memset(c->udppkt, 0, sizeof(ms_udppkt_t) * (uint64_t)c->packets); - } - - c->packets = 0; - c->recvpkt = 0; - c->pktcurr = 0; - c->ordcurr = 0; - c->rudpbytes = 0; - } - c->currcmd.isfinish = true; - c->ctnwrite = false; - c->rbytes = 0; - c->rcurr = c->rbuf; - ms_conn_set_state(c, conn_write); - memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t)); /* replicate command state */ + assert(c != NULL); + + if (c->udp) + { + if ((c->packets > 0) && (c->packets < MAX_UDP_PACKET)) + { + memset(c->udppkt, 0, sizeof(ms_udppkt_t) * (uint64_t)c->packets); + } + + c->packets= 0; + c->recvpkt= 0; + c->pktcurr= 0; + c->ordcurr= 0; + c->rudpbytes= 0; + } + c->currcmd.isfinish= true; + c->ctnwrite= false; + c->rbytes= 0; + c->rcurr= c->rbuf; + ms_conn_set_state(c, conn_write); + memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t)); /* replicate command state */ + + if (timeout) + { + ms_drive_machine(c); + } +} /* ms_reset_conn */ - if (timeout) { - ms_drive_machine(c); - } -} /** * if we have a complete line in the buffer, process it. @@ -1091,83 +1292,102 @@ void ms_reset_conn(ms_conn_t *c, bool timeout) */ static int ms_try_read_line(ms_conn_t *c) { - if (c->protocol == binary_prot) { - /* Do we have the complete packet header? */ - if ((uint64_t)c->rbytes < sizeof(c->binary_header)) { - /* need more data! */ - return 0; - } else { + if (c->protocol == binary_prot) + { + /* Do we have the complete packet header? */ + if ((uint64_t)c->rbytes < sizeof(c->binary_header)) + { + /* need more data! */ + return 0; + } + else + { #ifdef NEED_ALIGN - if (((long)(c->rcurr)) % 8 != 0) { - /* must realign input buffer */ - memmove(c->rbuf, c->rcurr, c->rbytes); - c->rcurr = c->rbuf; - if (settings.verbose) { - fprintf(stderr, "%d: Realign input buffer.\n", c->sfd); - } - } + if (((long)(c->rcurr)) % 8 != 0) + { + /* must realign input buffer */ + memmove(c->rbuf, c->rcurr, c->rbytes); + c->rcurr= c->rbuf; + if (settings.verbose) + { + fprintf(stderr, "%d: Realign input buffer.\n", c->sfd); + } + } #endif - protocol_binary_response_header* rsp; - rsp = (protocol_binary_response_header*)c->rcurr; - - c->binary_header = *rsp; - c->binary_header.response.extlen = rsp->response.extlen; - c->binary_header.response.keylen = ntohl(rsp->response.keylen); - c->binary_header.response.bodylen = ntohl(rsp->response.bodylen); - c->binary_header.response.status = ntohl(rsp->response.status); - - if (c->binary_header.response.magic != PROTOCOL_BINARY_RES) { - fprintf(stderr, "Invalid magic: %x\n", - c->binary_header.response.magic); - ms_conn_set_state(c, conn_closing); - return 0; - } - - /* process this complete response */ - if (ms_bin_process_response(c) == 0) { - /* current operation completed */ - ms_reset_conn(c, false); - return -1; - } else { - c->rbytes -= (int32_t)sizeof(c->binary_header); - c->rcurr += sizeof(c->binary_header); - } - } - } else { - char *el, *cont; - - assert(c != NULL); - assert(c->rcurr <= (c->rbuf + c->rsize)); - - if (c->rbytes == 0) - return 0; - el = memchr(c->rcurr, '\n', (size_t)c->rbytes); - if (!el) - return 0; - cont = el + 1; - if ((el - c->rcurr) > 1 && *(el - 1) == '\r') { - el--; - } - *el = '\0'; - - assert(cont <= (c->rcurr + c->rbytes)); - - /* process this complete line */ - if (ms_ascii_process_line(c, c->rcurr) == 0) { - /* current operation completed */ - ms_reset_conn(c, false); - return -1; - } else { - /* current operation didn't complete */ - c->rbytes -= (int32_t)(cont - c->rcurr); - c->rcurr = cont; - } + protocol_binary_response_header *rsp; + rsp= (protocol_binary_response_header *)c->rcurr; + + c->binary_header= *rsp; + c->binary_header.response.extlen= rsp->response.extlen; + c->binary_header.response.keylen= ntohl(rsp->response.keylen); + c->binary_header.response.bodylen= ntohl(rsp->response.bodylen); + c->binary_header.response.status= ntohl(rsp->response.status); + + if (c->binary_header.response.magic != PROTOCOL_BINARY_RES) + { + fprintf(stderr, "Invalid magic: %x\n", + c->binary_header.response.magic); + ms_conn_set_state(c, conn_closing); + return 0; + } + + /* process this complete response */ + if (ms_bin_process_response(c) == 0) + { + /* current operation completed */ + ms_reset_conn(c, false); + return -1; + } + else + { + c->rbytes-= (int32_t)sizeof(c->binary_header); + c->rcurr+= sizeof(c->binary_header); + } + } + } + else + { + char *el, *cont; + + assert(c != NULL); + assert(c->rcurr <= (c->rbuf + c->rsize)); + + if (c->rbytes == 0) + return 0; - assert(c->rcurr <= (c->rbuf + c->rsize)); + el= memchr(c->rcurr, '\n', (size_t)c->rbytes); + if (! el) + return 0; + + cont= el + 1; + if (((el - c->rcurr) > 1) && (*(el - 1) == '\r')) + { + el--; } + *el= '\0'; + + assert(cont <= (c->rcurr + c->rbytes)); + + /* process this complete line */ + if (ms_ascii_process_line(c, c->rcurr) == 0) + { + /* current operation completed */ + ms_reset_conn(c, false); + return -1; + } + else + { + /* current operation didn't complete */ + c->rbytes-= (int32_t)(cont - c->rcurr); + c->rcurr= cont; + } + + assert(c->rcurr <= (c->rbuf + c->rsize)); + } + + return -1; +} /* ms_try_read_line */ - return -1; -} /** * because the packet of UDP can't ensure the order, the @@ -1182,104 +1402,128 @@ static int ms_try_read_line(ms_conn_t *c) */ static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes) { - int len = 0; - int wbytes = 0; - uint16_t req_id = 0; - uint16_t seq_num = 0; - uint16_t packets = 0; - unsigned char *header = NULL; - - /* no enough data */ - assert(c != NULL); - assert(buf != NULL); - assert(c->rudpbytes >= UDP_HEADER_SIZE); - - /* calculate received packets count */ - if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE >= UDP_HEADER_SIZE) { - /* the last packet has some data */ - c->recvpkt = c->rudpbytes / UDP_MAX_PAYLOAD_SIZE + 1; - } else { - c->recvpkt = c->rudpbytes / UDP_MAX_PAYLOAD_SIZE; - } - - /* get the total packets count if necessary */ - if (c->packets == 0) { - c->packets = HEADER_TO_PACKETS((unsigned char *)c->rudpbuf); - } - - /* build the ordered packet array */ - for (int i = c->pktcurr; i < c->recvpkt; i++) { - header = (unsigned char *)c->rudpbuf + i * UDP_MAX_PAYLOAD_SIZE; - req_id = (uint16_t)HEADER_TO_REQID(header); - assert(req_id == c->request_id % (1 << 16)); - - packets = (uint16_t)HEADER_TO_PACKETS(header); - assert(c->packets == HEADER_TO_PACKETS(header)); - - seq_num = (uint16_t)HEADER_TO_SEQNUM(header); - c->udppkt[seq_num].header = header; - c->udppkt[seq_num].data = (char *)header + UDP_HEADER_SIZE; - - if (i == c->recvpkt - 1) { - /* last received packet */ - if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE == 0) { - c->udppkt[seq_num].rbytes = UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE; - c->pktcurr++; - } else { - c->udppkt[seq_num].rbytes = c->rudpbytes % UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE; - } - } else { - c->udppkt[seq_num].rbytes = UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE; - c->pktcurr++; - } - } + int len= 0; + int wbytes= 0; + uint16_t req_id= 0; + uint16_t seq_num= 0; + uint16_t packets= 0; + unsigned char *header= NULL; + + /* no enough data */ + assert(c != NULL); + assert(buf != NULL); + assert(c->rudpbytes >= UDP_HEADER_SIZE); + + /* calculate received packets count */ + if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE >= UDP_HEADER_SIZE) + { + /* the last packet has some data */ + c->recvpkt= c->rudpbytes / UDP_MAX_PAYLOAD_SIZE + 1; + } + else + { + c->recvpkt= c->rudpbytes / UDP_MAX_PAYLOAD_SIZE; + } + + /* get the total packets count if necessary */ + if (c->packets == 0) + { + c->packets= HEADER_TO_PACKETS((unsigned char *)c->rudpbuf); + } + + /* build the ordered packet array */ + for (int i= c->pktcurr; i < c->recvpkt; i++) + { + header= (unsigned char *)c->rudpbuf + i * UDP_MAX_PAYLOAD_SIZE; + req_id= (uint16_t)HEADER_TO_REQID(header); + assert(req_id == c->request_id % (1 << 16)); + + packets= (uint16_t)HEADER_TO_PACKETS(header); + assert(c->packets == HEADER_TO_PACKETS(header)); + + seq_num= (uint16_t)HEADER_TO_SEQNUM(header); + c->udppkt[seq_num].header= header; + c->udppkt[seq_num].data= (char *)header + UDP_HEADER_SIZE; + + if (i == c->recvpkt - 1) + { + /* last received packet */ + if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE == 0) + { + c->udppkt[seq_num].rbytes= UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE; + c->pktcurr++; + } + else + { + c->udppkt[seq_num].rbytes= c->rudpbytes % UDP_MAX_PAYLOAD_SIZE + - UDP_HEADER_SIZE; + } + } + else + { + c->udppkt[seq_num].rbytes= UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE; + c->pktcurr++; + } + } + + for (int i= c->ordcurr; i < c->recvpkt; i++) + { + /* there is some data to copy */ + if ((c->udppkt[i].data != NULL) + && (c->udppkt[i].copybytes < c->udppkt[i].rbytes)) + { + header= c->udppkt[i].header; + len= c->udppkt[i].rbytes - c->udppkt[i].copybytes; + if (len > rbytes - wbytes) + { + len= rbytes - wbytes; + } + + assert(len <= rbytes - wbytes); + assert(i == HEADER_TO_SEQNUM(header)); + + memcpy(buf + wbytes, c->udppkt[i].data + c->udppkt[i].copybytes, + (size_t)len); + wbytes+= len; + c->udppkt[i].copybytes+= len; + + if ((c->udppkt[i].copybytes == c->udppkt[i].rbytes) + && (c->udppkt[i].rbytes == UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE)) + { + /* finish copying all the data of this packet, next */ + c->ordcurr++; + } + + /* last received packet, and finish copying all the data */ + if ((c->recvpkt == c->packets) && (i == c->recvpkt - 1) + && (c->udppkt[i].copybytes == c->udppkt[i].rbytes)) + { + break; + } - for (int i = c->ordcurr; i < c->recvpkt; i++) { - /* there is some data to copy */ - if (c->udppkt[i].data != NULL && c->udppkt[i].copybytes < c->udppkt[i].rbytes) { - header = c->udppkt[i].header; - len = c->udppkt[i].rbytes - c->udppkt[i].copybytes; - if (len > rbytes - wbytes) { - len = rbytes - wbytes; - } - - assert(len <= rbytes - wbytes); - assert(i == HEADER_TO_SEQNUM(header)); - - memcpy(buf + wbytes, c->udppkt[i].data + c->udppkt[i].copybytes, (size_t)len); - wbytes += len; - c->udppkt[i].copybytes += len; - - if (c->udppkt[i].copybytes == c->udppkt[i].rbytes - && c->udppkt[i].rbytes == UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE) { - /* finish copying all the data of this packet, next */ - c->ordcurr++; - } - - /* last received packet, and finish copying all the data */ - if (c->recvpkt == c->packets && i == c->recvpkt - 1 - && c->udppkt[i].copybytes == c->udppkt[i].rbytes) { - break; - } - - /* no space to copy data */ - if (wbytes >= rbytes) { - break; - } - - /* it doesn't finish reading all the data of the packet from network */ - if (i != c->recvpkt - 1 - && c->udppkt[i].rbytes < UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE) { - break; - } - } else { - /* no data to copy */ - break; - } + /* no space to copy data */ + if (wbytes >= rbytes) + { + break; + } + + /* it doesn't finish reading all the data of the packet from network */ + if ((i != c->recvpkt - 1) + && (c->udppkt[i].rbytes < UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE)) + { + break; + } + } + else + { + /* no data to copy */ + break; } + } + + return wbytes == 0 ? -1 : wbytes; +} /* ms_sort_udp_packet */ - return(wbytes == 0 ? -1 : wbytes); -} /** * encapsulate upd read like tcp read @@ -1293,62 +1537,74 @@ static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes) */ static int ms_udp_read(ms_conn_t *c, char *buf, int len) { - int res = 0; - int avail = 0; - int rbytes = 0; - int copybytes = 0; - - assert(c->udp); - - while (1) { - if (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE > c->rudpsize) { - char *new_rbuf = realloc(c->rudpbuf, (size_t)c->rudpsize * 2); - if (!new_rbuf) { - fprintf(stderr, "Couldn't realloc input buffer.\n"); - c->rudpbytes = 0; /* ignore what we read */ - return -1; - } - c->rudpbuf = new_rbuf; - c->rudpsize *= 2; - } - - avail = c->rudpsize - c->rudpbytes; - /* UDP each time read a packet, 1400 bytes */ - res = (int)read(c->sfd, c->rudpbuf + c->rudpbytes, (size_t)avail); - - if (res > 0) { - __sync_fetch_and_add(&ms_stats.bytes_read, res); - c->rudpbytes += res; - rbytes += res; - if (res == avail) { - continue; - } else { - break; - } - } - - if (res == 0) { - /* "connection" closed */ - return res; - } - - if (res == -1) { - /* no data to read */ - return res; - } + int res= 0; + int avail= 0; + int rbytes= 0; + int copybytes= 0; + + assert(c->udp); + + while (1) + { + if (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE > c->rudpsize) + { + char *new_rbuf= realloc(c->rudpbuf, (size_t)c->rudpsize * 2); + if (! new_rbuf) + { + fprintf(stderr, "Couldn't realloc input buffer.\n"); + c->rudpbytes= 0; /* ignore what we read */ + return -1; + } + c->rudpbuf= new_rbuf; + c->rudpsize*= 2; + } + + avail= c->rudpsize - c->rudpbytes; + /* UDP each time read a packet, 1400 bytes */ + res= (int)read(c->sfd, c->rudpbuf + c->rudpbytes, (size_t)avail); + + if (res > 0) + { + __sync_fetch_and_add(&ms_stats.bytes_read, res); + c->rudpbytes+= res; + rbytes+= res; + if (res == avail) + { + continue; + } + else + { + break; + } } - /* copy data to read buffer */ - if (rbytes > 0) { - copybytes = ms_sort_udp_packet(c, buf, len); + if (res == 0) + { + /* "connection" closed */ + return res; } - if (copybytes == -1) { - __sync_fetch_and_add(&ms_stats.pkt_disorder, 1); + if (res == -1) + { + /* no data to read */ + return res; } + } + + /* copy data to read buffer */ + if (rbytes > 0) + { + copybytes= ms_sort_udp_packet(c, buf, len); + } + + if (copybytes == -1) + { + __sync_fetch_and_add(&ms_stats.pkt_disorder, 1); + } + + return copybytes; +} /* ms_udp_read */ - return copybytes; -} /* * read from network as much as we can, handle buffer overflow and connection @@ -1357,6 +1613,7 @@ static int ms_udp_read(ms_conn_t *c, char *buf, int len) * (if any) to the beginning of the buffer. * return 0 if there's nothing to read on the first read. */ + /** * read from network as much as we can, handle buffer overflow and connection * close. before reading, move the remaining incomplete fragment of a command @@ -1371,70 +1628,87 @@ static int ms_udp_read(ms_conn_t *c, char *buf, int len) */ static int ms_try_read_network(ms_conn_t *c) { - int gotdata = 0; - int res; - int64_t avail; + int gotdata= 0; + int res; + int64_t avail; + + assert(c != NULL); + + if ((c->rcurr != c->rbuf) + && (! c->readval || (c->rvbytes > c->rsize - (c->rcurr - c->rbuf)) + || (c->readval && (c->rcurr - c->rbuf > c->rbytes)))) + { + if (c->rbytes != 0) /* otherwise there's nothing to copy */ + memmove(c->rbuf, c->rcurr, (size_t)c->rbytes); + c->rcurr= c->rbuf; + } + + while (1) + { + if (c->rbytes >= c->rsize) + { + char *new_rbuf= realloc(c->rbuf, (size_t)c->rsize * 2); + if (! new_rbuf) + { + fprintf(stderr, "Couldn't realloc input buffer.\n"); + c->rbytes= 0; /* ignore what we read */ + return -1; + } + c->rcurr= c->rbuf= new_rbuf; + c->rsize*= 2; + } - assert(c != NULL); + avail= c->rsize - c->rbytes - (c->rcurr - c->rbuf); + if (avail == 0) + { + break; + } - if (c->rcurr != c->rbuf && - (!c->readval || c->rvbytes > c->rsize - (c->rcurr - c->rbuf) - || (c->readval && c->rcurr - c->rbuf > c->rbytes))) { - if (c->rbytes != 0) /* otherwise there's nothing to copy */ - memmove(c->rbuf, c->rcurr, (size_t)c->rbytes); - c->rcurr = c->rbuf; - } - - while (1) { - if (c->rbytes >= c->rsize) { - char *new_rbuf = realloc(c->rbuf, (size_t)c->rsize * 2); - if (!new_rbuf) { - fprintf(stderr, "Couldn't realloc input buffer.\n"); - c->rbytes = 0; /* ignore what we read */ - return -1; - } - c->rcurr = c->rbuf = new_rbuf; - c->rsize *= 2; - } - - avail = c->rsize - c->rbytes - (c->rcurr - c->rbuf); - if (avail == 0) { - break; - } - - if (c->udp) { - res = (int32_t)ms_udp_read(c, c->rcurr + c->rbytes, (int32_t)avail); - } else { - res = (int)read(c->sfd, c->rcurr + c->rbytes, (size_t)avail); - } - - if (res > 0) { - if (!c->udp) { - __sync_fetch_and_add(&ms_stats.bytes_read, res); - } - gotdata = 1; - c->rbytes += res; - if (res == avail) { - continue; - } else { - break; - } - } - if (res == 0) { - /* connection closed */ - ms_conn_set_state(c, conn_closing); - return -1; - } - if (res == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) break; - /* Should close on unhandled errors. */ - ms_conn_set_state(c, conn_closing); - return -1; - } + if (c->udp) + { + res= (int32_t)ms_udp_read(c, c->rcurr + c->rbytes, (int32_t)avail); + } + else + { + res= (int)read(c->sfd, c->rcurr + c->rbytes, (size_t)avail); + } + + if (res > 0) + { + if (! c->udp) + { + __sync_fetch_and_add(&ms_stats.bytes_read, res); + } + gotdata= 1; + c->rbytes+= res; + if (res == avail) + { + continue; + } + else + { + break; + } + } + if (res == 0) + { + /* connection closed */ + ms_conn_set_state(c, conn_closing); + return -1; + } + if (res == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + break; + /* Should close on unhandled errors. */ + ms_conn_set_state(c, conn_closing); + return -1; } + } + + return gotdata; +} /* ms_try_read_network */ - return gotdata; -} /** * after get the object from server, verify the value if @@ -1445,79 +1719,106 @@ static int ms_try_read_network(ms_conn_t *c) * @param value, received value string * @param vlen, received value string length */ -static void ms_verify_value(ms_conn_t *c, ms_mlget_task_item_t *mlget_item, - char *value, int vlen) +static void ms_verify_value(ms_conn_t *c, + ms_mlget_task_item_t *mlget_item, + char *value, + int vlen) { - if (c->curr_task.verify) { - assert(c->curr_task.item->value_offset != INVALID_OFFSET); - char *orignval = &ms_setting.char_block[c->curr_task.item->value_offset]; - char *orignkey = &ms_setting.char_block[c->curr_task.item->key_suffix_offset]; - - /* verify expire time if necessary */ - if (c->curr_task.item->exp_time > 0) { - struct timeval curr_time; - gettimeofday(&curr_time, NULL); - - /* object expired but get it now */ - if (curr_time.tv_sec - c->curr_task.item->client_time - > c->curr_task.item->exp_time + EXPIRE_TIME_ERROR) { - __sync_fetch_and_add(&ms_stats.exp_get, 1); - - if (ms_setting.verbose) { - char set_time[64]; - char cur_time[64]; - strftime(set_time, 64, "%Y-%m-%d %H:%M:%S", - localtime(&c->curr_task.item->client_time)); - strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S", - localtime(&curr_time.tv_sec)); - fprintf(stderr, "\n<%d expire time verification failed, " - "object expired but get it now\n" - "\tkey len: %d\n" - "\tkey: %lx %.*s\n" - "\tset time: %s current time: %s " - "diff time: %d expire time: %d\n" - "\texpected data: \n" - "\treceived data len: %d\n" - "\treceived data: %.*s\n", - c->sfd, c->curr_task.item->key_size, c->curr_task.item->key_prefix, - c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE, - orignkey, set_time, cur_time, - (int)(curr_time.tv_sec - c->curr_task.item->client_time), - c->curr_task.item->exp_time, - vlen, vlen, value); - fflush(stderr); - } - } - } else { - if (c->curr_task.item->value_size != vlen - || memcmp(orignval, value, (size_t)vlen) != 0) { - __sync_fetch_and_add(&ms_stats.vef_failed, 1); - - if (ms_setting.verbose) { - fprintf(stderr, "\n<%d data verification failed\n" - "\tkey len: %d\n" - "\tkey: %lx %.*s\n" - "\texpected data len: %d\n" - "\texpected data: %.*s\n" - "\treceived data len: %d\n" - "\treceived data: %.*s\n", - c->sfd, c->curr_task.item->key_size, c->curr_task.item->key_prefix, - c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE, - orignkey, c->curr_task.item->value_size, - c->curr_task.item->value_size, - orignval, vlen, vlen, value); - fflush(stderr); - } - } - } + if (c->curr_task.verify) + { + assert(c->curr_task.item->value_offset != INVALID_OFFSET); + char *orignval= &ms_setting.char_block[c->curr_task.item->value_offset]; + char *orignkey= + &ms_setting.char_block[c->curr_task.item->key_suffix_offset]; + + /* verify expire time if necessary */ + if (c->curr_task.item->exp_time > 0) + { + struct timeval curr_time; + gettimeofday(&curr_time, NULL); + + /* object expired but get it now */ + if (curr_time.tv_sec - c->curr_task.item->client_time + > c->curr_task.item->exp_time + EXPIRE_TIME_ERROR) + { + __sync_fetch_and_add(&ms_stats.exp_get, 1); + + if (ms_setting.verbose) + { + char set_time[64]; + char cur_time[64]; + strftime(set_time, 64, "%Y-%m-%d %H:%M:%S", + localtime(&c->curr_task.item->client_time)); + strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S", + localtime(&curr_time.tv_sec)); + fprintf(stderr, + "\n<%d expire time verification failed, " + "object expired but get it now\n" + "\tkey len: %d\n" + "\tkey: %lx %.*s\n" + "\tset time: %s current time: %s " + "diff time: %d expire time: %d\n" + "\texpected data: \n" + "\treceived data len: %d\n" + "\treceived data: %.*s\n", + c->sfd, + c->curr_task.item->key_size, + c->curr_task.item->key_prefix, + c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE, + orignkey, + set_time, + cur_time, + (int)(curr_time.tv_sec - c->curr_task.item->client_time), + c->curr_task.item->exp_time, + vlen, + vlen, + value); + fflush(stderr); + } + } + } + else + { + if ((c->curr_task.item->value_size != vlen) + || (memcmp(orignval, value, (size_t)vlen) != 0)) + { + __sync_fetch_and_add(&ms_stats.vef_failed, 1); + + if (ms_setting.verbose) + { + fprintf(stderr, + "\n<%d data verification failed\n" + "\tkey len: %d\n" + "\tkey: %lx %.*s\n" + "\texpected data len: %d\n" + "\texpected data: %.*s\n" + "\treceived data len: %d\n" + "\treceived data: %.*s\n", + c->sfd, + c->curr_task.item->key_size, + c->curr_task.item->key_prefix, + c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE, + orignkey, + c->curr_task.item->value_size, + c->curr_task.item->value_size, + orignval, + vlen, + vlen, + value); + fflush(stderr); + } + } + } + + c->curr_task.finish_verify= true; + + if (mlget_item != NULL) + { + mlget_item->finish_verify= true; + } + } +} /* ms_verify_value */ - c->curr_task.finish_verify = true; - - if (mlget_item != NULL) { - mlget_item->finish_verify = true; - } - } -} /** * For ASCII protocol, after store the data into the local @@ -1527,53 +1828,60 @@ static void ms_verify_value(ms_conn_t *c, ms_mlget_task_item_t *mlget_item, */ static void ms_ascii_complete_nread(ms_conn_t *c) { - assert(c != NULL); - assert(c->rbytes >= c->rvbytes); - assert(c->protocol == ascii_udp_prot || c->protocol == ascii_prot); - if (c->rvbytes > 2) { - assert(c->rcurr[c->rvbytes - 1] == '\n' && c->rcurr[c->rvbytes - 2] == '\r'); - } - - /* multi-get */ - ms_mlget_task_item_t *mlget_item = NULL; - if ((ms_setting.mult_key_num > 1 && - c->mlget_task.mlget_num >= ms_setting.mult_key_num) || - (c->remain_exec_num == 0 && c->mlget_task.mlget_num > 0)) { - - c->mlget_task.value_index++; - mlget_item = &c->mlget_task.mlget_item[c->mlget_task.value_index]; - - if (mlget_item->item->key_prefix == c->currcmd.key_prefix) { - c->curr_task.item = mlget_item->item; - c->curr_task.verify = mlget_item->verify; - c->curr_task.finish_verify = mlget_item->finish_verify; - mlget_item->get_miss = false; - } else { - /* Try to find the task item in multi-get task array */ - for (int i = 0; i < c->mlget_task.mlget_num; i++) { - mlget_item = &c->mlget_task.mlget_item[i]; - if (mlget_item->item->key_prefix == c->currcmd.key_prefix) { - - c->curr_task.item = mlget_item->item; - c->curr_task.verify = mlget_item->verify; - c->curr_task.finish_verify = mlget_item->finish_verify; - mlget_item->get_miss = false; - - break; - } - } - } - } + assert(c != NULL); + assert(c->rbytes >= c->rvbytes); + assert(c->protocol == ascii_udp_prot || c->protocol == ascii_prot); + if (c->rvbytes > 2) + { + assert( + c->rcurr[c->rvbytes - 1] == '\n' && c->rcurr[c->rvbytes - 2] == '\r'); + } + + /* multi-get */ + ms_mlget_task_item_t *mlget_item= NULL; + if (((ms_setting.mult_key_num > 1) + && (c->mlget_task.mlget_num >= ms_setting.mult_key_num)) + || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0))) + { + c->mlget_task.value_index++; + mlget_item= &c->mlget_task.mlget_item[c->mlget_task.value_index]; + + if (mlget_item->item->key_prefix == c->currcmd.key_prefix) + { + c->curr_task.item= mlget_item->item; + c->curr_task.verify= mlget_item->verify; + c->curr_task.finish_verify= mlget_item->finish_verify; + mlget_item->get_miss= false; + } + else + { + /* Try to find the task item in multi-get task array */ + for (int i= 0; i < c->mlget_task.mlget_num; i++) + { + mlget_item= &c->mlget_task.mlget_item[i]; + if (mlget_item->item->key_prefix == c->currcmd.key_prefix) + { + c->curr_task.item= mlget_item->item; + c->curr_task.verify= mlget_item->verify; + c->curr_task.finish_verify= mlget_item->finish_verify; + mlget_item->get_miss= false; + + break; + } + } + } + } + + ms_verify_value(c, mlget_item, c->rcurr, c->rvbytes - 2); + + c->curr_task.get_miss= false; + c->rbytes-= c->rvbytes; + c->rcurr= c->rcurr + c->rvbytes; + assert(c->rcurr <= (c->rbuf + c->rsize)); + c->readval= false; + c->rvbytes= 0; +} /* ms_ascii_complete_nread */ - ms_verify_value(c, mlget_item, c->rcurr, c->rvbytes - 2); - - c->curr_task.get_miss = false; - c->rbytes -= c->rvbytes; - c->rcurr = c->rcurr + c->rvbytes; - assert(c->rcurr <= (c->rbuf + c->rsize)); - c->readval = false; - c->rvbytes = 0; -} /** * For binary protocol, after store the data into the local @@ -1583,64 +1891,75 @@ static void ms_ascii_complete_nread(ms_conn_t *c) */ static void ms_bin_complete_nread(ms_conn_t *c) { - assert(c != NULL); - assert(c->rbytes >= c->rvbytes); - assert(c->protocol == binary_prot); - - int extlen = c->binary_header.response.extlen; - int keylen = c->binary_header.response.keylen; - uint8_t opcode = c->binary_header.response.opcode; - - /* not get command or not include value, just return */ - if ((opcode != PROTOCOL_BINARY_CMD_GET && opcode != PROTOCOL_BINARY_CMD_GETQ) || - c->rvbytes <= extlen + keylen) { - /* get miss */ - if (c->binary_header.response.opcode == PROTOCOL_BINARY_CMD_GET) { - c->currcmd.retstat = MCD_END; - c->curr_task.get_miss = true; - } - - c->readval = false; - c->rvbytes = 0; - ms_reset_conn(c, false); - return; - } - - /* multi-get */ - ms_mlget_task_item_t *mlget_item = NULL; - if ((ms_setting.mult_key_num > 1 && - c->mlget_task.mlget_num >= ms_setting.mult_key_num) || - (c->remain_exec_num == 0 && c->mlget_task.mlget_num > 0)) { - - c->mlget_task.value_index++; - mlget_item = &c->mlget_task.mlget_item[c->mlget_task.value_index]; - - c->curr_task.item = mlget_item->item; - c->curr_task.verify = mlget_item->verify; - c->curr_task.finish_verify = mlget_item->finish_verify; - mlget_item->get_miss = false; - } - - ms_verify_value(c, mlget_item, c->rcurr + extlen + keylen, c->rvbytes - extlen - keylen); - - c->currcmd.retstat = MCD_END; - c->curr_task.get_miss = false; - c->rbytes -= c->rvbytes; - c->rcurr = c->rcurr + c->rvbytes; - assert(c->rcurr <= (c->rbuf + c->rsize)); - c->readval = false; - c->rvbytes = 0; + assert(c != NULL); + assert(c->rbytes >= c->rvbytes); + assert(c->protocol == binary_prot); + + int extlen= c->binary_header.response.extlen; + int keylen= c->binary_header.response.keylen; + uint8_t opcode= c->binary_header.response.opcode; + + /* not get command or not include value, just return */ + if (((opcode != PROTOCOL_BINARY_CMD_GET) + && (opcode != PROTOCOL_BINARY_CMD_GETQ)) + || (c->rvbytes <= extlen + keylen)) + { + /* get miss */ + if (c->binary_header.response.opcode == PROTOCOL_BINARY_CMD_GET) + { + c->currcmd.retstat= MCD_END; + c->curr_task.get_miss= true; + } + + c->readval= false; + c->rvbytes= 0; + ms_reset_conn(c, false); + return; + } + + /* multi-get */ + ms_mlget_task_item_t *mlget_item= NULL; + if (((ms_setting.mult_key_num > 1) + && (c->mlget_task.mlget_num >= ms_setting.mult_key_num)) + || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0))) + { + c->mlget_task.value_index++; + mlget_item= &c->mlget_task.mlget_item[c->mlget_task.value_index]; + + c->curr_task.item= mlget_item->item; + c->curr_task.verify= mlget_item->verify; + c->curr_task.finish_verify= mlget_item->finish_verify; + mlget_item->get_miss= false; + } + + ms_verify_value(c, + mlget_item, + c->rcurr + extlen + keylen, + c->rvbytes - extlen - keylen); + + c->currcmd.retstat= MCD_END; + c->curr_task.get_miss= false; + c->rbytes-= c->rvbytes; + c->rcurr= c->rcurr + c->rvbytes; + assert(c->rcurr <= (c->rbuf + c->rsize)); + c->readval= false; + c->rvbytes= 0; + + if (ms_setting.mult_key_num > 1) + { + /* multi-get have check all the item */ + if (c->mlget_task.value_index == c->mlget_task.mlget_num - 1) + { + ms_reset_conn(c, false); + } + } + else + { + /* single get */ + ms_reset_conn(c, false); + } +} /* ms_bin_complete_nread */ - if (ms_setting.mult_key_num > 1) { - /* multi-get have check all the item */ - if (c->mlget_task.value_index == c->mlget_task.mlget_num - 1) { - ms_reset_conn(c, false); - } - } else { - /* single get */ - ms_reset_conn(c, false); - } -} /** * we get here after reading the value of get commands. @@ -1649,18 +1968,22 @@ static void ms_bin_complete_nread(ms_conn_t *c) */ static void ms_complete_nread(ms_conn_t *c) { - assert(c != NULL); - assert(c->rbytes >= c->rvbytes); - assert(c->protocol == ascii_udp_prot - || c->protocol == ascii_prot - || c->protocol == binary_prot); + assert(c != NULL); + assert(c->rbytes >= c->rvbytes); + assert(c->protocol == ascii_udp_prot + || c->protocol == ascii_prot + || c->protocol == binary_prot); + + if (c->protocol == binary_prot) + { + ms_bin_complete_nread(c); + } + else + { + ms_ascii_complete_nread(c); + } +} /* ms_complete_nread */ - if (c->protocol == binary_prot) { - ms_bin_complete_nread(c); - } else { - ms_ascii_complete_nread(c); - } -} /** * Adds a message header to a connection. @@ -1671,43 +1994,49 @@ static void ms_complete_nread(ms_conn_t *c) */ static int ms_add_msghdr(ms_conn_t *c) { - struct msghdr *msg; + struct msghdr *msg; - assert(c != NULL); + assert(c != NULL); - if (c->msgsize == c->msgused) { - msg = realloc(c->msglist, (uint64_t)c->msgsize * 2 * sizeof(struct msghdr)); - if (! msg) - return -1; - c->msglist = msg; - c->msgsize *= 2; - } + if (c->msgsize == c->msgused) + { + msg= + realloc(c->msglist, (uint64_t)c->msgsize * 2 * sizeof(struct msghdr)); + if (! msg) + return -1; - msg = c->msglist + c->msgused; + c->msglist= msg; + c->msgsize*= 2; + } - /** - * this wipes msg_iovlen, msg_control, msg_controllen, and - * msg_flags, the last 3 of which aren't defined on solaris: - */ - memset(msg, 0, sizeof(struct msghdr)); + msg= c->msglist + c->msgused; - msg->msg_iov = &c->iov[c->iovused]; + /** + * this wipes msg_iovlen, msg_control, msg_controllen, and + * msg_flags, the last 3 of which aren't defined on solaris: + */ + memset(msg, 0, sizeof(struct msghdr)); - if (c->udp && c->srv_recv_addr_size > 0) { - msg->msg_name = &c->srv_recv_addr; - msg->msg_namelen = c->srv_recv_addr_size; - } + msg->msg_iov= &c->iov[c->iovused]; - c->msgbytes = 0; - c->msgused++; + if (c->udp && (c->srv_recv_addr_size > 0)) + { + msg->msg_name= &c->srv_recv_addr; + msg->msg_namelen= c->srv_recv_addr_size; + } - if (c->udp) { - /* Leave room for the UDP header, which we'll fill in later. */ - return ms_add_iov(c, NULL, UDP_HEADER_SIZE); - } + c->msgbytes= 0; + c->msgused++; + + if (c->udp) + { + /* Leave room for the UDP header, which we'll fill in later. */ + return ms_add_iov(c, NULL, UDP_HEADER_SIZE); + } + + return 0; +} /* ms_add_msghdr */ - return 0; -} /** * Ensures that there is room for another structure iovec in a connection's @@ -1719,26 +2048,32 @@ static int ms_add_msghdr(ms_conn_t *c) */ static int ms_ensure_iov_space(ms_conn_t *c) { - assert(c != NULL); + assert(c != NULL); - if (c->iovused >= c->iovsize) { - int i, iovnum; - struct iovec *new_iov = (struct iovec *)realloc(c->iov, - ((uint64_t)c->iovsize * 2) * sizeof(struct iovec)); - if (! new_iov) - return -1; - c->iov = new_iov; - c->iovsize *= 2; - - /* Point all the msghdr structures at the new list. */ - for (i = 0, iovnum = 0; i < c->msgused; i++) { - c->msglist[i].msg_iov = &c->iov[iovnum]; - iovnum += (int)c->msglist[i].msg_iovlen; - } + if (c->iovused >= c->iovsize) + { + int i, iovnum; + struct iovec *new_iov= (struct iovec *)realloc(c->iov, + ((uint64_t)c->iovsize + * 2) + * sizeof(struct iovec)); + if (! new_iov) + return -1; + + c->iov= new_iov; + c->iovsize*= 2; + + /* Point all the msghdr structures at the new list. */ + for (i= 0, iovnum= 0; i < c->msgused; i++) + { + c->msglist[i].msg_iov= &c->iov[iovnum]; + iovnum+= (int)c->msglist[i].msg_iovlen; } + } + + return 0; +} /* ms_ensure_iov_space */ - return 0; -} /** * Adds data to the list of pending data that will be written out to a @@ -1752,52 +2087,59 @@ static int ms_ensure_iov_space(ms_conn_t *c) */ static int ms_add_iov(ms_conn_t *c, const void *buf, int len) { - struct msghdr *m; - int leftover; - bool limit_to_mtu; + struct msghdr *m; + int leftover; + bool limit_to_mtu; - assert(c != NULL); + assert(c != NULL); - do { - m = &c->msglist[c->msgused - 1]; + do + { + m= &c->msglist[c->msgused - 1]; - /* - * Limit UDP packets, to UDP_MAX_PAYLOAD_SIZE bytes. - */ - limit_to_mtu = c->udp; + /* + * Limit UDP packets, to UDP_MAX_PAYLOAD_SIZE bytes. + */ + limit_to_mtu= c->udp; - /* We may need to start a new msghdr if this one is full. */ - if (m->msg_iovlen == IOV_MAX || - (limit_to_mtu && c->msgbytes >= UDP_MAX_SEND_PAYLOAD_SIZE)) { - ms_add_msghdr(c); - m = &c->msglist[c->msgused - 1]; - } + /* We may need to start a new msghdr if this one is full. */ + if ((m->msg_iovlen == IOV_MAX) + || (limit_to_mtu && (c->msgbytes >= UDP_MAX_SEND_PAYLOAD_SIZE))) + { + ms_add_msghdr(c); + m= &c->msglist[c->msgused - 1]; + } - if (ms_ensure_iov_space(c) != 0) - return -1; + if (ms_ensure_iov_space(c) != 0) + return -1; - /* If the fragment is too big to fit in the datagram, split it up */ - if (limit_to_mtu && len + c->msgbytes > UDP_MAX_SEND_PAYLOAD_SIZE) { - leftover = len + c->msgbytes - UDP_MAX_SEND_PAYLOAD_SIZE; - len -= leftover; - } else { - leftover = 0; - } + /* If the fragment is too big to fit in the datagram, split it up */ + if (limit_to_mtu && (len + c->msgbytes > UDP_MAX_SEND_PAYLOAD_SIZE)) + { + leftover= len + c->msgbytes - UDP_MAX_SEND_PAYLOAD_SIZE; + len-= leftover; + } + else + { + leftover= 0; + } - m = &c->msglist[c->msgused - 1]; - m->msg_iov[m->msg_iovlen].iov_base = (void *)buf; - m->msg_iov[m->msg_iovlen].iov_len = (size_t)len; + m= &c->msglist[c->msgused - 1]; + m->msg_iov[m->msg_iovlen].iov_base= (void *)buf; + m->msg_iov[m->msg_iovlen].iov_len= (size_t)len; - c->msgbytes += len; - c->iovused++; - m->msg_iovlen++; + c->msgbytes+= len; + c->iovused++; + m->msg_iovlen++; - buf = ((char *)buf) + len; - len = leftover; - } while (leftover > 0); + buf= ((char *)buf) + len; + len= leftover; + } + while (leftover > 0); + + return 0; +} /* ms_add_iov */ - return 0; -} /** * Constructs a set of UDP headers and attaches them to the outgoing messages. @@ -1808,48 +2150,56 @@ static int ms_add_iov(ms_conn_t *c, const void *buf, int len) */ static int ms_build_udp_headers(ms_conn_t *c) { - int i; - unsigned char *hdr; - - assert(c != NULL); - - c->request_id = ms_get_udp_request_id(); - - if (c->msgused > c->hdrsize) { - void *new_hdrbuf; - if (c->hdrbuf) - new_hdrbuf = realloc(c->hdrbuf, (size_t)c->msgused * 2 * UDP_HEADER_SIZE); - else - new_hdrbuf = malloc((size_t)c->msgused * 2 * UDP_HEADER_SIZE); - if (! new_hdrbuf) - return -1; - c->hdrbuf = (unsigned char *)new_hdrbuf; - c->hdrsize = c->msgused * 2; - } - - /* If this is a multi-packet request, drop it. */ - if (c->udp && c->msgused > 1) { - fprintf(stderr, "multi-packet request for UDP not supported.\n"); - return -1; - } + int i; + unsigned char *hdr; + + assert(c != NULL); + + c->request_id= ms_get_udp_request_id(); + + if (c->msgused > c->hdrsize) + { + void *new_hdrbuf; + if (c->hdrbuf) + new_hdrbuf= realloc(c->hdrbuf, + (size_t)c->msgused * 2 * UDP_HEADER_SIZE); + else + new_hdrbuf= malloc((size_t)c->msgused * 2 * UDP_HEADER_SIZE); + if (! new_hdrbuf) + return -1; + + c->hdrbuf= (unsigned char *)new_hdrbuf; + c->hdrsize= c->msgused * 2; + } + + /* If this is a multi-packet request, drop it. */ + if (c->udp && (c->msgused > 1)) + { + fprintf(stderr, "multi-packet request for UDP not supported.\n"); + return -1; + } + + hdr= c->hdrbuf; + for (i= 0; i < c->msgused; i++) + { + c->msglist[i].msg_iov[0].iov_base= hdr; + c->msglist[i].msg_iov[0].iov_len= UDP_HEADER_SIZE; + *hdr++= (unsigned char)(c->request_id / 256); + *hdr++= (unsigned char)(c->request_id % 256); + *hdr++= (unsigned char)(i / 256); + *hdr++= (unsigned char)(i % 256); + *hdr++= (unsigned char)(c->msgused / 256); + *hdr++= (unsigned char)(c->msgused % 256); + *hdr++= (unsigned char)1; /* support facebook memcached */ + *hdr++= (unsigned char)0; + assert(hdr == + ((unsigned char *)c->msglist[i].msg_iov[0].iov_base + + UDP_HEADER_SIZE)); + } + + return 0; +} /* ms_build_udp_headers */ - hdr = c->hdrbuf; - for (i = 0; i < c->msgused; i++) { - c->msglist[i].msg_iov[0].iov_base = hdr; - c->msglist[i].msg_iov[0].iov_len = UDP_HEADER_SIZE; - *hdr++ = (unsigned char)(c->request_id / 256); - *hdr++ = (unsigned char)(c->request_id % 256); - *hdr++ = (unsigned char)(i / 256); - *hdr++ = (unsigned char)(i % 256); - *hdr++ = (unsigned char)(c->msgused / 256); - *hdr++ = (unsigned char)(c->msgused % 256); - *hdr++ = (unsigned char)1; /* support facebook memcached */ - *hdr++ = (unsigned char)0; - assert(hdr == ((unsigned char *)c->msglist[i].msg_iov[0].iov_base + UDP_HEADER_SIZE)); - } - - return 0; -} /** * Transmit the next chunk of data from our list of msgbuf structures. @@ -1863,57 +2213,67 @@ static int ms_build_udp_headers(ms_conn_t *c) */ static int ms_transmit(ms_conn_t *c) { - assert(c != NULL); - - if (c->msgcurr < c->msgused && - c->msglist[c->msgcurr].msg_iovlen == 0) { - /* Finished writing the current msg; advance to the next. */ - c->msgcurr++; - } - - if (c->msgcurr < c->msgused) { - ssize_t res; - struct msghdr *m = &c->msglist[c->msgcurr]; - - res = sendmsg(c->sfd, m, 0); - if (res > 0) { - __sync_fetch_and_add(&ms_stats.bytes_written, res); - - /* We've written some of the data. Remove the completed - iovec entries from the list of pending writes. */ - while (m->msg_iovlen > 0 && res >= (ssize_t)m->msg_iov->iov_len) { - res -= (ssize_t)m->msg_iov->iov_len; - m->msg_iovlen--; - m->msg_iov++; - } - - /* Might have written just part of the last iovec entry; - adjust it so the next write will do the rest. */ - if (res > 0) { - m->msg_iov->iov_base = (unsigned char *)m->msg_iov->iov_base + res; - m->msg_iov->iov_len -= (uint64_t)res; - } - return TRANSMIT_INCOMPLETE; - } - if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - if (!ms_update_event(c, EV_WRITE | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - return TRANSMIT_HARD_ERROR; - } - return TRANSMIT_SOFT_ERROR; - } - - /* if res==0 or res==-1 and error is not EAGAIN or EWOULDBLOCK, - we have a real error, on which we close the connection */ - fprintf(stderr, "Failed to write, and not due to blocking.\n"); - + assert(c != NULL); + + if ((c->msgcurr < c->msgused) + && (c->msglist[c->msgcurr].msg_iovlen == 0)) + { + /* Finished writing the current msg; advance to the next. */ + c->msgcurr++; + } + + if (c->msgcurr < c->msgused) + { + ssize_t res; + struct msghdr *m= &c->msglist[c->msgcurr]; + + res= sendmsg(c->sfd, m, 0); + if (res > 0) + { + __sync_fetch_and_add(&ms_stats.bytes_written, res); + + /* We've written some of the data. Remove the completed + * iovec entries from the list of pending writes. */ + while (m->msg_iovlen > 0 && res >= (ssize_t)m->msg_iov->iov_len) + { + res-= (ssize_t)m->msg_iov->iov_len; + m->msg_iovlen--; + m->msg_iov++; + } + + /* Might have written just part of the last iovec entry; + * adjust it so the next write will do the rest. */ + if (res > 0) + { + m->msg_iov->iov_base= (unsigned char *)m->msg_iov->iov_base + res; + m->msg_iov->iov_len-= (uint64_t)res; + } + return TRANSMIT_INCOMPLETE; + } + if ((res == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) + { + if (! ms_update_event(c, EV_WRITE | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); ms_conn_set_state(c, conn_closing); return TRANSMIT_HARD_ERROR; - } else { - return TRANSMIT_COMPLETE; + } + return TRANSMIT_SOFT_ERROR; } -} + + /* if res==0 or res==-1 and error is not EAGAIN or EWOULDBLOCK, + * we have a real error, on which we close the connection */ + fprintf(stderr, "Failed to write, and not due to blocking.\n"); + + ms_conn_set_state(c, conn_closing); + return TRANSMIT_HARD_ERROR; + } + else + { + return TRANSMIT_COMPLETE; + } +} /* ms_transmit */ + /** * Shrinks a connection's buffers if they're too big. This prevents @@ -1927,56 +2287,68 @@ static int ms_transmit(ms_conn_t *c) */ static void ms_conn_shrink(ms_conn_t *c) { - assert(c != NULL); - - if (c->udp) - return; + assert(c != NULL); - if (c->rsize > READ_BUFFER_HIGHWAT && c->rbytes < DATA_BUFFER_SIZE) { - char *newbuf; - - if (c->rcurr != c->rbuf) - memmove(c->rbuf, c->rcurr, (size_t)c->rbytes); - - newbuf = (char *)realloc((void *)c->rbuf, DATA_BUFFER_SIZE); - - if (newbuf) { - c->rbuf = newbuf; - c->rsize = DATA_BUFFER_SIZE; - } - c->rcurr = c->rbuf; - } - - if (c->udp && c->rudpsize > UDP_DATA_BUFFER_HIGHWAT - && c->rudpbytes + UDP_MAX_PAYLOAD_SIZE < UDP_DATA_BUFFER_SIZE) { - char *new_rbuf = (char *)realloc(c->rudpbuf, (size_t)c->rudpsize * 2); - if (!new_rbuf) { - c->rudpbuf = new_rbuf; - c->rudpsize = UDP_DATA_BUFFER_SIZE; - } - /* TODO check error condition? */ - } + if (c->udp) + return; - if (c->msgsize > MSG_LIST_HIGHWAT) { - struct msghdr *newbuf = (struct msghdr *) realloc((void *)c->msglist, - MSG_LIST_INITIAL * sizeof(c->msglist[0])); - if (newbuf) { - c->msglist = newbuf; - c->msgsize = MSG_LIST_INITIAL; - } - /* TODO check error condition? */ - } + if ((c->rsize > READ_BUFFER_HIGHWAT) && (c->rbytes < DATA_BUFFER_SIZE)) + { + char *newbuf; + + if (c->rcurr != c->rbuf) + memmove(c->rbuf, c->rcurr, (size_t)c->rbytes); + + newbuf= (char *)realloc((void *)c->rbuf, DATA_BUFFER_SIZE); + + if (newbuf) + { + c->rbuf= newbuf; + c->rsize= DATA_BUFFER_SIZE; + } + c->rcurr= c->rbuf; + } + + if (c->udp && (c->rudpsize > UDP_DATA_BUFFER_HIGHWAT) + && (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE < UDP_DATA_BUFFER_SIZE)) + { + char *new_rbuf= (char *)realloc(c->rudpbuf, (size_t)c->rudpsize * 2); + if (! new_rbuf) + { + c->rudpbuf= new_rbuf; + c->rudpsize= UDP_DATA_BUFFER_SIZE; + } + /* TODO check error condition? */ + } + + if (c->msgsize > MSG_LIST_HIGHWAT) + { + struct msghdr *newbuf= (struct msghdr *)realloc( + (void *)c->msglist, + MSG_LIST_INITIAL + * sizeof(c->msglist[0])); + if (newbuf) + { + c->msglist= newbuf; + c->msgsize= MSG_LIST_INITIAL; + } + /* TODO check error condition? */ + } + + if (c->iovsize > IOV_LIST_HIGHWAT) + { + struct iovec *newbuf= (struct iovec *)realloc((void *)c->iov, + IOV_LIST_INITIAL + * sizeof(c->iov[0])); + if (newbuf) + { + c->iov= newbuf; + c->iovsize= IOV_LIST_INITIAL; + } + /* TODO check return value */ + } +} /* ms_conn_shrink */ - if (c->iovsize > IOV_LIST_HIGHWAT) { - struct iovec *newbuf = (struct iovec *) realloc((void *)c->iov, - IOV_LIST_INITIAL * sizeof(c->iov[0])); - if (newbuf) { - c->iov = newbuf; - c->iovsize = IOV_LIST_INITIAL; - } - /* TODO check return value */ - } -} /** * Sets a connection's current state in the state machine. Any special @@ -1988,15 +2360,18 @@ static void ms_conn_shrink(ms_conn_t *c) */ static void ms_conn_set_state(ms_conn_t *c, int state) { - assert(c != NULL); + assert(c != NULL); - if (state != c->state) { - if (state == conn_read) { - ms_conn_shrink(c); - } - c->state = state; + if (state != c->state) + { + if (state == conn_read) + { + ms_conn_shrink(c); } -} + c->state= state; + } +} /* ms_conn_set_state */ + /** * update the event if socks change state. for example: when @@ -2010,40 +2385,56 @@ static void ms_conn_set_state(ms_conn_t *c, int state) */ static bool ms_update_event(ms_conn_t *c, const int new_flags) { - /* default event timeout 10 seconds */ - struct timeval t = {.tv_sec = EVENT_TIMEOUT, .tv_usec = 0}; - - assert(c != NULL); - - struct event_base *base = c->event.ev_base; - if (c->ev_flags == new_flags && ms_setting.rep_write_srv == 0 - && (!ms_setting.facebook_test || c->total_sfds == 1)) { - return true; - } + /* default event timeout 10 seconds */ + struct timeval t= + { + .tv_sec= EVENT_TIMEOUT, .tv_usec= 0 + }; + + assert(c != NULL); + + struct event_base *base= c->event.ev_base; + if ((c->ev_flags == new_flags) && (ms_setting.rep_write_srv == 0) + && (! ms_setting.facebook_test || (c->total_sfds == 1))) + { + return true; + } - if (event_del(&c->event) == -1) { - /* try to delete the event again */ - if (event_del(&c->event) == -1) { - return false; - } + if (event_del(&c->event) == -1) + { + /* try to delete the event again */ + if (event_del(&c->event) == -1) + { + return false; } + } - event_set(&c->event, c->sfd, (short)new_flags, ms_event_handler, (void *)c); - event_base_set(base, &c->event); - c->ev_flags = (short)new_flags; + event_set(&c->event, + c->sfd, + (short)new_flags, + ms_event_handler, + (void *)c); + event_base_set(base, &c->event); + c->ev_flags= (short)new_flags; - if (c->total_sfds == 1) { - if (event_add(&c->event, NULL) == -1) { - return false; - } - } else { - if (event_add(&c->event, &t) == -1) { - return false; - } + if (c->total_sfds == 1) + { + if (event_add(&c->event, NULL) == -1) + { + return false; } + } + else + { + if (event_add(&c->event, &t) == -1) + { + return false; + } + } + + return true; +} /* ms_update_event */ - return true; -} /** * If user want to get the expected throughput, we could limit @@ -2057,24 +2448,29 @@ static bool ms_update_event(ms_conn_t *c, const int new_flags) */ static bool ms_need_yield(ms_conn_t *c) { - int64_t tps = 0; - int64_t time_diff = 0; - struct timeval curr_time; - ms_task_t *task = &c->curr_task; - - if (ms_setting.expected_tps > 0) { - gettimeofday(&curr_time, NULL); - time_diff = ms_time_diff(&ms_thread.startup_time, &curr_time); - tps = (int64_t)((task->get_opt + task->set_opt) / ((uint64_t)time_diff / 1000000)); - - /* current throughput is greater than expected throughput */ - if (tps > ms_thread.thread_ctx->tps_perconn) { - return true; - } + int64_t tps= 0; + int64_t time_diff= 0; + struct timeval curr_time; + ms_task_t *task= &c->curr_task; + + if (ms_setting.expected_tps > 0) + { + gettimeofday(&curr_time, NULL); + time_diff= ms_time_diff(&ms_thread.startup_time, &curr_time); + tps= + (int64_t)((task->get_opt + + task->set_opt) / ((uint64_t)time_diff / 1000000)); + + /* current throughput is greater than expected throughput */ + if (tps > ms_thread.thread_ctx->tps_perconn) + { + return true; } + } + + return false; +} /* ms_need_yield */ - return false; -} /** * used to update the start time of each operation @@ -2083,18 +2479,20 @@ static bool ms_need_yield(ms_conn_t *c) */ static void ms_update_start_time(ms_conn_t *c) { - ms_task_item_t *item = c->curr_task.item; - - if (ms_setting.stat_freq > 0 || c->udp - || (c->currcmd.cmd == CMD_SET && item->exp_time > 0)) { + ms_task_item_t *item= c->curr_task.item; - gettimeofday(&c->start_time, NULL); - if (c->currcmd.cmd == CMD_SET && item->exp_time > 0) { - /* record the current time */ - item->client_time = c->start_time.tv_sec; - } + if ((ms_setting.stat_freq > 0) || c->udp + || ((c->currcmd.cmd == CMD_SET) && (item->exp_time > 0))) + { + gettimeofday(&c->start_time, NULL); + if ((c->currcmd.cmd == CMD_SET) && (item->exp_time > 0)) + { + /* record the current time */ + item->client_time= c->start_time.tv_sec; } -} + } +} /* ms_update_start_time */ + /** * run the state machine @@ -2103,154 +2501,182 @@ static void ms_update_start_time(ms_conn_t *c) */ static void ms_drive_machine(ms_conn_t *c) { - bool stop = false; + bool stop= false; + + assert(c != NULL); + + while (! stop) + { + switch (c->state) + { + case conn_read: + if (c->readval) + { + if (c->rbytes >= c->rvbytes) + { + ms_complete_nread(c); + break; + } + } + else + { + if (ms_try_read_line(c) != 0) + { + break; + } + } + + if (ms_try_read_network(c) != 0) + { + break; + } + + /* doesn't read all the response data, wait event wake up */ + if (! c->currcmd.isfinish) + { + if (! ms_update_event(c, EV_READ | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); + ms_conn_set_state(c, conn_closing); + break; + } + stop= true; + break; + } - assert(c != NULL); + /* we have no command line and no data to read from network, next write */ + ms_conn_set_state(c, conn_write); + memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t)); /* replicate command state */ - while (!stop) { - switch (c->state) { - case conn_read: - if (c->readval) { - if (c->rbytes >= c->rvbytes) { - ms_complete_nread(c); - break; - } - } else { - if (ms_try_read_line(c) != 0) { - break; - } - } - - if (ms_try_read_network(c) != 0) { - break; - } - - /* doesn't read all the response data, wait event wake up */ - if (!c->currcmd.isfinish) { - if (!ms_update_event(c, EV_READ | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - break; - } - stop = true; - break; - } - - /* we have no command line and no data to read from network, next write */ - ms_conn_set_state(c, conn_write); - memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t)); /* replicate command state */ + break; - break; + case conn_write: + if (! c->ctnwrite && ms_need_yield(c)) + { + usleep(10); - case conn_write: - if (!c->ctnwrite && ms_need_yield(c)) { - usleep(10); - - if (!ms_update_event(c, EV_WRITE | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - break; - } - stop = true; - break; - } - - if (!c->ctnwrite && ms_exec_task(c) != 0) { - ms_conn_set_state(c, conn_closing); - break; - } - - /* record the start time before starting to send data if necessary */ - if (!c->ctnwrite || (c->change_sfd && c->ctnwrite)) { - if (c->change_sfd) { - c->change_sfd = false; - } - ms_update_start_time(c); - } - - /* change sfd if necessary */ - if (c->change_sfd) { - c->ctnwrite = true; - stop = true; - break; - } - - /* execute task until nothing need be written to network */ - if (!c->ctnwrite && c->msgcurr == c->msgused) { - if (!ms_update_event(c, EV_WRITE | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - break; - } - stop = true; - break; - } - - switch (ms_transmit(c)) { - case TRANSMIT_COMPLETE: - /* we have no data to write to network, next wait repose */ - if (!ms_update_event(c, EV_READ | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - c->ctnwrite = false; - break; - } - ms_conn_set_state(c, conn_read); - c->ctnwrite = false; - stop = true; - break; - - case TRANSMIT_INCOMPLETE: - c->ctnwrite = true; - break; /* Continue in state machine. */ - - case TRANSMIT_HARD_ERROR: - c->ctnwrite = false; - break; - - case TRANSMIT_SOFT_ERROR: - c->ctnwrite = true; - stop = true; - break; - default: - break; - } - break; + if (! ms_update_event(c, EV_WRITE | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); + ms_conn_set_state(c, conn_closing); + break; + } + stop= true; + break; + } + + if (! c->ctnwrite && (ms_exec_task(c) != 0)) + { + ms_conn_set_state(c, conn_closing); + break; + } + + /* record the start time before starting to send data if necessary */ + if (! c->ctnwrite || (c->change_sfd && c->ctnwrite)) + { + if (c->change_sfd) + { + c->change_sfd= false; + } + ms_update_start_time(c); + } + + /* change sfd if necessary */ + if (c->change_sfd) + { + c->ctnwrite= true; + stop= true; + break; + } + + /* execute task until nothing need be written to network */ + if (! c->ctnwrite && (c->msgcurr == c->msgused)) + { + if (! ms_update_event(c, EV_WRITE | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); + ms_conn_set_state(c, conn_closing); + break; + } + stop= true; + break; + } + + switch (ms_transmit(c)) + { + case TRANSMIT_COMPLETE: + /* we have no data to write to network, next wait repose */ + if (! ms_update_event(c, EV_READ | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); + ms_conn_set_state(c, conn_closing); + c->ctnwrite= false; + break; + } + ms_conn_set_state(c, conn_read); + c->ctnwrite= false; + stop= true; + break; + + case TRANSMIT_INCOMPLETE: + c->ctnwrite= true; + break; /* Continue in state machine. */ + + case TRANSMIT_HARD_ERROR: + c->ctnwrite= false; + break; + + case TRANSMIT_SOFT_ERROR: + c->ctnwrite= true; + stop= true; + break; + + default: + break; + } /* switch */ - case conn_closing: - /* recovery mode, need reconnect if connection close */ - if (ms_setting.reconnect && (!ms_global.time_out - || (ms_setting.run_time == 0 && c->remain_exec_num > 0))) { - - if (ms_reconn(c) != 0) { - ms_conn_close(c); - stop = true; - break; - } - - ms_reset_conn(c, false); - - if (c->total_sfds == 1) { - if (!ms_update_event(c, EV_WRITE | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - break; - } - } - - break; - } else { - ms_conn_close(c); - stop = true; - break; - } - default: - assert(0); + break; + + case conn_closing: + /* recovery mode, need reconnect if connection close */ + if (ms_setting.reconnect && (! ms_global.time_out + || ((ms_setting.run_time == 0) + && (c->remain_exec_num > 0)))) + { + if (ms_reconn(c) != 0) + { + ms_conn_close(c); + stop= true; + break; } - } - return; -} + ms_reset_conn(c, false); + + if (c->total_sfds == 1) + { + if (! ms_update_event(c, EV_WRITE | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); + ms_conn_set_state(c, conn_closing); + break; + } + } + + break; + } + else + { + ms_conn_close(c); + stop= true; + break; + } + + default: + assert(0); + } /* switch */ + } +} /* ms_drive_machine */ + /** * the event handler of each thread @@ -2261,30 +2687,35 @@ static void ms_drive_machine(ms_conn_t *c) */ void ms_event_handler(const int fd, const short which, void *arg) { - ms_conn_t *c = (ms_conn_t *)arg; - assert(c != NULL); + ms_conn_t *c= (ms_conn_t *)arg; - c->which = which; + assert(c != NULL); - /* sanity */ - if (fd != c->sfd) { - fprintf(stderr, "Catastrophic: event fd: %d doesn't match conn fd: %d\n", - fd, c->sfd); - ms_conn_close(c); - exit(1); - } - assert(fd == c->sfd); + c->which= which; - /* event timeout, close the current connection */ - if (c->which == EV_TIMEOUT) { - ms_conn_set_state(c, conn_closing); - } + /* sanity */ + if (fd != c->sfd) + { + fprintf(stderr, + "Catastrophic: event fd: %d doesn't match conn fd: %d\n", + fd, + c->sfd); + ms_conn_close(c); + exit(1); + } + assert(fd == c->sfd); - ms_drive_machine(c); + /* event timeout, close the current connection */ + if (c->which == EV_TIMEOUT) + { + ms_conn_set_state(c, conn_closing); + } + + ms_drive_machine(c); + + /* wait for next event */ +} /* ms_event_handler */ - /* wait for next event */ - return; -} /** * get the next socket descriptor index to run for replication @@ -2296,40 +2727,53 @@ void ms_event_handler(const int fd, const short which, void *arg) */ static int ms_get_rep_sock_index(ms_conn_t *c, int cmd) { - int sock_index = -1; - int i = 0; - - if (c->total_sfds == 1) { - return 0; - } + int sock_index= -1; + int i= 0; - if (ms_setting.rep_write_srv == 0) { - return sock_index; - } - - do { - if (cmd == CMD_SET) { - for (i = 0; i < ms_setting.rep_write_srv; i++) { - if (c->tcpsfd[i] > 0) { - break; - } - } - - if (i == ms_setting.rep_write_srv) { - /* random get one replication server to read */ - sock_index = (int)(random() % c->total_sfds); - } else { - /* random get one replication writing server to write */ - sock_index = (int)(random() % ms_setting.rep_write_srv); - } - } else if (cmd == CMD_GET) { - /* random get one replication server to read */ - sock_index = (int)(random() % c->total_sfds); - } - } while (c->tcpsfd[sock_index] == 0); + if (c->total_sfds == 1) + { + return 0; + } + if (ms_setting.rep_write_srv == 0) + { return sock_index; -} + } + + do + { + if (cmd == CMD_SET) + { + for (i= 0; i < ms_setting.rep_write_srv; i++) + { + if (c->tcpsfd[i] > 0) + { + break; + } + } + + if (i == ms_setting.rep_write_srv) + { + /* random get one replication server to read */ + sock_index= (int)(random() % c->total_sfds); + } + else + { + /* random get one replication writing server to write */ + sock_index= (int)(random() % ms_setting.rep_write_srv); + } + } + else if (cmd == CMD_GET) + { + /* random get one replication server to read */ + sock_index= (int)(random() % c->total_sfds); + } + } + while (c->tcpsfd[sock_index] == 0); + + return sock_index; +} /* ms_get_rep_sock_index */ + /** * get the next socket descriptor index to run @@ -2340,14 +2784,17 @@ static int ms_get_rep_sock_index(ms_conn_t *c, int cmd) */ static int ms_get_next_sock_index(ms_conn_t *c) { - int sock_index = 0; + int sock_index= 0; - do { - sock_index = (++c->cur_idx == c->total_sfds) ? 0 : c->cur_idx; - } while (c->tcpsfd[sock_index] == 0); + do + { + sock_index= (++c->cur_idx == c->total_sfds) ? 0 : c->cur_idx; + } + while (c->tcpsfd[sock_index] == 0); + + return sock_index; +} /* ms_get_next_sock_index */ - return sock_index; -} /** * update socket event of the connections @@ -2358,54 +2805,69 @@ static int ms_get_next_sock_index(ms_conn_t *c) */ static int ms_update_conn_sock_event(ms_conn_t *c) { - assert(c != NULL); - - switch (c->currcmd.cmd) { - case CMD_SET: - if (ms_setting.facebook_test && c->udp) { - c->sfd = c->tcpsfd[0]; - c->udp = false; - c->change_sfd = true; - } - break; - case CMD_GET: - if (ms_setting.facebook_test && !c->udp) { - c->sfd = c->udpsfd; - c->udp = true; - c->change_sfd = true; - } - break; - default: - break; - } + assert(c != NULL); + + switch (c->currcmd.cmd) + { + case CMD_SET: + if (ms_setting.facebook_test && c->udp) + { + c->sfd= c->tcpsfd[0]; + c->udp= false; + c->change_sfd= true; + } + break; + + case CMD_GET: + if (ms_setting.facebook_test && ! c->udp) + { + c->sfd= c->udpsfd; + c->udp= true; + c->change_sfd= true; + } + break; + + default: + break; + } /* switch */ + + if (! c->udp && (c->total_sfds > 1)) + { + if (c->cur_idx != c->total_sfds) + { + if (ms_setting.rep_write_srv == 0) + { + c->cur_idx= ms_get_next_sock_index(c); + } + else + { + c->cur_idx= ms_get_rep_sock_index(c, c->currcmd.cmd); + } + } + else + { + /* must select the first sock of the connection at the beginning */ + c->cur_idx= 0; + } + + c->sfd= c->tcpsfd[c->cur_idx]; + assert(c->sfd != 0); + c->change_sfd= true; + } + + if (c->change_sfd) + { + if (! ms_update_event(c, EV_WRITE | EV_PERSIST)) + { + fprintf(stderr, "Couldn't update event.\n"); + ms_conn_set_state(c, conn_closing); + return -1; + } + } + + return 0; +} /* ms_update_conn_sock_event */ - if (!c->udp && c->total_sfds > 1) { - if (c->cur_idx != c->total_sfds) { - if (ms_setting.rep_write_srv == 0) { - c->cur_idx = ms_get_next_sock_index(c); - } else { - c->cur_idx = ms_get_rep_sock_index(c, c->currcmd.cmd); - } - } else { - /* must select the first sock of the connection at the beginning */ - c->cur_idx = 0; - } - - c->sfd = c->tcpsfd[c->cur_idx]; - assert(c->sfd != 0); - c->change_sfd = true; - } - - if (c->change_sfd) { - if (!ms_update_event(c, EV_WRITE | EV_PERSIST)) { - fprintf(stderr, "Couldn't update event.\n"); - ms_conn_set_state(c, conn_closing); - return -1; - } - } - - return 0; -} /** * for ASCII protocol, this function build the set command @@ -2419,38 +2881,49 @@ static int ms_update_conn_sock_event(ms_conn_t *c) */ static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item) { - int value_offset; - int write_len; - char *buffer = c->wbuf; - - write_len= sprintf(buffer, " %u %d %d\r\n", 0, item->exp_time, item->value_size); - - if (write_len > c->wsize) { - /* ought to be always enough. just fail for simplicity */ - fprintf(stderr, "output command line too long.\n"); - return -1; - } - - if (item->value_offset == INVALID_OFFSET) { - value_offset = item->key_suffix_offset; - } else { - value_offset = item->value_offset; - } - - if (ms_add_iov(c, "set ", 4) != 0 || - ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE) != 0 || - ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], - item->key_size - (int)KEY_PREFIX_SIZE) != 0 || - ms_add_iov(c, buffer, write_len) != 0 || - ms_add_iov(c, &ms_setting.char_block[value_offset], item->value_size) != 0 || - ms_add_iov(c, "\r\n", 2) != 0 || - (c->udp && ms_build_udp_headers(c) != 0)) { + int value_offset; + int write_len; + char *buffer= c->wbuf; + + write_len= sprintf(buffer, + " %u %d %d\r\n", + 0, + item->exp_time, + item->value_size); + + if (write_len > c->wsize) + { + /* ought to be always enough. just fail for simplicity */ + fprintf(stderr, "output command line too long.\n"); + return -1; + } + + if (item->value_offset == INVALID_OFFSET) + { + value_offset= item->key_suffix_offset; + } + else + { + value_offset= item->value_offset; + } + + if ((ms_add_iov(c, "set ", 4) != 0) + || (ms_add_iov(c, (char *)&item->key_prefix, + (int)KEY_PREFIX_SIZE) != 0) + || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], + item->key_size - (int)KEY_PREFIX_SIZE) != 0) + || (ms_add_iov(c, buffer, write_len) != 0) + || (ms_add_iov(c, &ms_setting.char_block[value_offset], + item->value_size) != 0) + || (ms_add_iov(c, "\r\n", 2) != 0) + || (c->udp && (ms_build_udp_headers(c) != 0))) + { + return -1; + } - return -1; - } + return 0; +} /* ms_build_ascii_write_buf_set */ - return 0; -} /** * used to send set command to server @@ -2463,40 +2936,49 @@ static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item) */ int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item) { - assert(c != NULL); + assert(c != NULL); - c->currcmd.cmd = CMD_SET; - c->currcmd.isfinish = false; - c->currcmd.retstat = MCD_FAILURE; + c->currcmd.cmd= CMD_SET; + c->currcmd.isfinish= false; + c->currcmd.retstat= MCD_FAILURE; - if (ms_update_conn_sock_event(c) != 0) { - return -1; - } + if (ms_update_conn_sock_event(c) != 0) + { + return -1; + } + + c->msgcurr= 0; + c->msgused= 0; + c->iovused= 0; + if (ms_add_msghdr(c) != 0) + { + fprintf(stderr, "Out of memory preparing request."); + return -1; + } - c->msgcurr = 0; - c->msgused = 0; - c->iovused = 0; - if (ms_add_msghdr(c) != 0) { - fprintf(stderr, "Out of memory preparing request."); - return -1; + /* binary protocol */ + if (c->protocol == binary_prot) + { + if (ms_build_bin_write_buf_set(c, item) != 0) + { + return -1; } - - /* binary protocol */ - if (c->protocol == binary_prot) { - if (ms_build_bin_write_buf_set(c, item) != 0) { - return -1; - } - } else { - if (ms_build_ascii_write_buf_set(c, item) != 0) { - return -1; - } + } + else + { + if (ms_build_ascii_write_buf_set(c, item) != 0) + { + return -1; } + } - __sync_fetch_and_add(&ms_stats.obj_bytes, item->key_size + item->value_size); - __sync_fetch_and_add(&ms_stats.cmd_set, 1); + __sync_fetch_and_add(&ms_stats.obj_bytes, + item->key_size + item->value_size); + __sync_fetch_and_add(&ms_stats.cmd_set, 1); + + return 0; +} /* ms_mcd_set */ - return 0; -} /** * for ASCII protocol, this function build the get command @@ -2510,18 +2992,20 @@ int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item) */ static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item) { - if (ms_add_iov(c, "get ", 4) != 0 || - ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE) != 0 || - ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], - item->key_size - (int)KEY_PREFIX_SIZE) != 0 || - ms_add_iov(c, "\r\n", 2) != 0 || - (c->udp && ms_build_udp_headers(c) != 0)) { + if ((ms_add_iov(c, "get ", 4) != 0) + || (ms_add_iov(c, (char *)&item->key_prefix, + (int)KEY_PREFIX_SIZE) != 0) + || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], + item->key_size - (int)KEY_PREFIX_SIZE) != 0) + || (ms_add_iov(c, "\r\n", 2) != 0) + || (c->udp && (ms_build_udp_headers(c) != 0))) + { + return -1; + } - return -1; - } + return 0; +} /* ms_build_ascii_write_buf_get */ - return 0; -} /** * used to send the get command to server @@ -2535,42 +3019,50 @@ static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item) */ int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item, bool verify) { - /* verify not supported yet */ - UNUSED_ARGUMENT(verify); + /* verify not supported yet */ + UNUSED_ARGUMENT(verify); - assert(c != NULL); + assert(c != NULL); - c->currcmd.cmd = CMD_GET; - c->currcmd.isfinish = false; - c->currcmd.retstat = MCD_FAILURE; + c->currcmd.cmd= CMD_GET; + c->currcmd.isfinish= false; + c->currcmd.retstat= MCD_FAILURE; - if (ms_update_conn_sock_event(c) != 0) { - return -1; - } + if (ms_update_conn_sock_event(c) != 0) + { + return -1; + } + + c->msgcurr= 0; + c->msgused= 0; + c->iovused= 0; + if (ms_add_msghdr(c) != 0) + { + fprintf(stderr, "Out of memory preparing request."); + return -1; + } - c->msgcurr = 0; - c->msgused = 0; - c->iovused = 0; - if (ms_add_msghdr(c) != 0) { - fprintf(stderr, "Out of memory preparing request."); - return -1; + /* binary protocol */ + if (c->protocol == binary_prot) + { + if (ms_build_bin_write_buf_get(c, item) != 0) + { + return -1; } - - /* binary protocol */ - if (c->protocol == binary_prot) { - if (ms_build_bin_write_buf_get(c, item) != 0) { - return -1; - } - } else { - if (ms_build_ascii_write_buf_get(c, item) != 0) { - return -1; - } + } + else + { + if (ms_build_ascii_write_buf_get(c, item) != 0) + { + return -1; } + } - __sync_fetch_and_add(&ms_stats.cmd_get, 1); + __sync_fetch_and_add(&ms_stats.cmd_get, 1); + + return 0; +} /* ms_mcd_get */ - return 0; -} /** * for ASCII protocol, this function build the multi-get command @@ -2582,30 +3074,36 @@ int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item, bool verify) */ static int ms_build_ascii_write_buf_mlget(ms_conn_t *c) { - ms_task_item_t *item; + ms_task_item_t *item; - if (ms_add_iov(c, "get", 3) != 0) { - return -1; - } - - for (int i = 0; i < c->mlget_task.mlget_num; i++) { - item = c->mlget_task.mlget_item[i].item; - assert(item != NULL); - if (ms_add_iov(c, " ", 1) != 0 || - ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE) != 0 || - ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], - item->key_size - (int)KEY_PREFIX_SIZE) != 0) { - return -1; - } - } + if (ms_add_iov(c, "get", 3) != 0) + { + return -1; + } + + for (int i= 0; i < c->mlget_task.mlget_num; i++) + { + item= c->mlget_task.mlget_item[i].item; + assert(item != NULL); + if ((ms_add_iov(c, " ", 1) != 0) + || (ms_add_iov(c, (char *)&item->key_prefix, + (int)KEY_PREFIX_SIZE) != 0) + || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], + item->key_size - (int)KEY_PREFIX_SIZE) != 0)) + { + return -1; + } + } + + if ((ms_add_iov(c, "\r\n", 2) != 0) + || (c->udp && (ms_build_udp_headers(c) != 0))) + { + return -1; + } - if (ms_add_iov(c, "\r\n", 2) != 0 || - (c->udp && ms_build_udp_headers(c) != 0)) { - return -1; - } + return 0; +} /* ms_build_ascii_write_buf_mlget */ - return 0; -} /** * used to send the multi-get command to server @@ -2616,46 +3114,55 @@ static int ms_build_ascii_write_buf_mlget(ms_conn_t *c) */ int ms_mcd_mlget(ms_conn_t *c) { - ms_task_item_t *item; - - assert(c != NULL); - assert(c->mlget_task.mlget_num >= 1); + ms_task_item_t *item; - c->currcmd.cmd = CMD_GET; - c->currcmd.isfinish = false; - c->currcmd.retstat = MCD_FAILURE; - - if (ms_update_conn_sock_event(c) != 0) { - return -1; - } + assert(c != NULL); + assert(c->mlget_task.mlget_num >= 1); - c->msgcurr = 0; - c->msgused = 0; - c->iovused = 0; - if (ms_add_msghdr(c) != 0) { - fprintf(stderr, "Out of memory preparing request."); - return -1; - } + c->currcmd.cmd= CMD_GET; + c->currcmd.isfinish= false; + c->currcmd.retstat= MCD_FAILURE; - /* binary protocol */ - if (c->protocol == binary_prot) { - if (ms_build_bin_write_buf_mlget(c) != 0) { - return -1; - } - } else { - if (ms_build_ascii_write_buf_mlget(c) != 0) { - return -1; - } - } + if (ms_update_conn_sock_event(c) != 0) + { + return -1; + } + + c->msgcurr= 0; + c->msgused= 0; + c->iovused= 0; + if (ms_add_msghdr(c) != 0) + { + fprintf(stderr, "Out of memory preparing request."); + return -1; + } + + /* binary protocol */ + if (c->protocol == binary_prot) + { + if (ms_build_bin_write_buf_mlget(c) != 0) + { + return -1; + } + } + else + { + if (ms_build_ascii_write_buf_mlget(c) != 0) + { + return -1; + } + } + + /* decrease operation time of each item */ + for (int i= 0; i < c->mlget_task.mlget_num; i++) + { + item= c->mlget_task.mlget_item[i].item; + __sync_fetch_and_add(&ms_stats.cmd_get, 1); + } - /* decrease operation time of each item */ - for (int i = 0; i < c->mlget_task.mlget_num; i++) { - item = c->mlget_task.mlget_item[i].item; - __sync_fetch_and_add(&ms_stats.cmd_get, 1); - } + return 0; +} /* ms_mcd_mlget */ - return 0; -} /** * binary protocol support @@ -2670,71 +3177,91 @@ int ms_mcd_mlget(ms_conn_t *c) */ static int ms_bin_process_response(ms_conn_t *c) { - const char *errstr = NULL; - - assert(c != NULL); + const char *errstr= NULL; + + assert(c != NULL); + + uint32_t bodylen= c->binary_header.response.bodylen; + uint8_t opcode= c->binary_header.response.opcode; + uint16_t status= c->binary_header.response.status; + + if (bodylen > 0) + { + c->rvbytes= (int32_t)bodylen; + c->readval= true; + return 1; + } + else + { + switch (status) + { + case PROTOCOL_BINARY_RESPONSE_SUCCESS: + if (opcode == PROTOCOL_BINARY_CMD_SET) + { + c->currcmd.retstat= MCD_STORED; + } + else if (opcode == PROTOCOL_BINARY_CMD_DELETE) + { + c->currcmd.retstat= MCD_DELETED; + } + else if (opcode == PROTOCOL_BINARY_CMD_GET) + { + c->currcmd.retstat= MCD_END; + } + break; + + case PROTOCOL_BINARY_RESPONSE_ENOMEM: + errstr= "Out of memory"; + c->currcmd.retstat= MCD_SERVER_ERROR; + break; + + case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND: + errstr= "Unknown command"; + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + break; + + case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT: + errstr= "Not found"; + c->currcmd.retstat= MCD_NOTFOUND; + break; + + case PROTOCOL_BINARY_RESPONSE_EINVAL: + errstr= "Invalid arguments"; + c->currcmd.retstat= MCD_PROTOCOL_ERROR; + break; + + case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS: + errstr= "Data exists for key."; + break; + + case PROTOCOL_BINARY_RESPONSE_E2BIG: + errstr= "Too large."; + c->currcmd.retstat= MCD_SERVER_ERROR; + break; + + case PROTOCOL_BINARY_RESPONSE_NOT_STORED: + errstr= "Not stored."; + c->currcmd.retstat= MCD_NOTSTORED; + break; - uint32_t bodylen = c->binary_header.response.bodylen; - uint8_t opcode = c->binary_header.response.opcode; - uint16_t status = c->binary_header.response.status; - - if (bodylen > 0) { - c->rvbytes = (int32_t)bodylen; - c->readval = true; - return 1; - } else { - switch (status) { - case PROTOCOL_BINARY_RESPONSE_SUCCESS: - if (opcode == PROTOCOL_BINARY_CMD_SET) { - c->currcmd.retstat = MCD_STORED; - } else if (opcode == PROTOCOL_BINARY_CMD_DELETE) { - c->currcmd.retstat = MCD_DELETED; - } else if (opcode == PROTOCOL_BINARY_CMD_GET) { - c->currcmd.retstat = MCD_END; - } - break; - case PROTOCOL_BINARY_RESPONSE_ENOMEM: - errstr = "Out of memory"; - c->currcmd.retstat = MCD_SERVER_ERROR; - break; - case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND: - errstr = "Unknown command"; - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - break; - case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT: - errstr = "Not found"; - c->currcmd.retstat = MCD_NOTFOUND; - break; - case PROTOCOL_BINARY_RESPONSE_EINVAL: - errstr = "Invalid arguments"; - c->currcmd.retstat = MCD_PROTOCOL_ERROR; - break; - case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS: - errstr = "Data exists for key."; - break; - case PROTOCOL_BINARY_RESPONSE_E2BIG: - errstr = "Too large."; - c->currcmd.retstat = MCD_SERVER_ERROR; - break; - case PROTOCOL_BINARY_RESPONSE_NOT_STORED: - errstr = "Not stored."; - c->currcmd.retstat = MCD_NOTSTORED; - break; - default: - errstr = "Unknown error"; - c->currcmd.retstat = MCD_UNKNOWN_READ_FAILURE; - break; - } + default: + errstr= "Unknown error"; + c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE; + break; + } /* switch */ - if (errstr != NULL) { - fprintf(stderr, "%s\n", errstr); - } + if (errstr != NULL) + { + fprintf(stderr, "%s\n", errstr); } + } + + return 0; +} /* ms_bin_process_response */ - return 0; -} /* build binary header and add the header to the buffer to send */ + /** * build binary header and add the header to the buffer to send * @@ -2744,28 +3271,33 @@ static int ms_bin_process_response(ms_conn_t *c) * @param key_len, length of key * @param body_len. length of body */ -static void ms_add_bin_header(ms_conn_t *c, uint8_t opcode, uint8_t hdr_len, - uint16_t key_len, uint32_t body_len) { - protocol_binary_request_header* header; +static void ms_add_bin_header(ms_conn_t *c, + uint8_t opcode, + uint8_t hdr_len, + uint16_t key_len, + uint32_t body_len) +{ + protocol_binary_request_header *header; - assert(c != NULL); + assert(c != NULL); - header = (protocol_binary_request_header *)c->wcurr; + header= (protocol_binary_request_header *)c->wcurr; - header->request.magic = (uint8_t)PROTOCOL_BINARY_REQ; - header->request.opcode = (uint8_t)opcode; - header->request.keylen = htonl(key_len); + header->request.magic= (uint8_t)PROTOCOL_BINARY_REQ; + header->request.opcode= (uint8_t)opcode; + header->request.keylen= htonl(key_len); - header->request.extlen = (uint8_t)hdr_len; - header->request.datatype = (uint8_t)PROTOCOL_BINARY_RAW_BYTES; - header->request.reserved = 0; + header->request.extlen= (uint8_t)hdr_len; + header->request.datatype= (uint8_t)PROTOCOL_BINARY_RAW_BYTES; + header->request.reserved= 0; - header->request.bodylen = htonl(body_len); - header->request.opaque = 0; - header->request.cas = 0; + header->request.bodylen= htonl(body_len); + header->request.opaque= 0; + header->request.cas= 0; + + ms_add_iov(c, c->wcurr, sizeof(header->request)); +} /* ms_add_bin_header */ - ms_add_iov(c, c->wcurr, sizeof(header->request)); -} /** * add the key to the socket write buffer array @@ -2776,11 +3308,12 @@ static void ms_add_bin_header(ms_conn_t *c, uint8_t opcode, uint8_t hdr_len, */ static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item) { - ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE); - ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], - item->key_size - (int)KEY_PREFIX_SIZE); + ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE); + ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset], + item->key_size - (int)KEY_PREFIX_SIZE); } + /** * for binary protocol, this function build the set command * and add the command to send buffer array. @@ -2793,28 +3326,37 @@ static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item) */ static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item) { - assert(c->wbuf == c->wcurr); - - int value_offset; - protocol_binary_request_set* rep = (protocol_binary_request_set*)c->wcurr; - uint16_t keylen = (uint16_t)item->key_size; - uint32_t bodylen = (uint32_t)sizeof(rep->message.body) + (uint32_t)keylen + (uint32_t)item->value_size; + assert(c->wbuf == c->wcurr); + + int value_offset; + protocol_binary_request_set *rep= (protocol_binary_request_set *)c->wcurr; + uint16_t keylen= (uint16_t)item->key_size; + uint32_t bodylen= (uint32_t)sizeof(rep->message.body) + + (uint32_t)keylen + (uint32_t)item->value_size; + + ms_add_bin_header(c, + PROTOCOL_BINARY_CMD_SET, + sizeof(rep->message.body), + keylen, + bodylen); + rep->message.body.flags= 0; + rep->message.body.expiration= htonl((uint32_t)item->exp_time); + ms_add_iov(c, &rep->message.body, sizeof(rep->message.body)); + ms_add_key_to_iov(c, item); + + if (item->value_offset == INVALID_OFFSET) + { + value_offset= item->key_suffix_offset; + } + else + { + value_offset= item->value_offset; + } + ms_add_iov(c, &ms_setting.char_block[value_offset], item->value_size); + + return 0; +} /* ms_build_bin_write_buf_set */ - ms_add_bin_header(c, PROTOCOL_BINARY_CMD_SET, sizeof(rep->message.body), keylen, bodylen); - rep->message.body.flags = 0; - rep->message.body.expiration = htonl((uint32_t)item->exp_time); - ms_add_iov(c, &rep->message.body, sizeof(rep->message.body)); - ms_add_key_to_iov(c, item); - - if (item->value_offset == INVALID_OFFSET) { - value_offset = item->key_suffix_offset; - } else { - value_offset = item->value_offset; - } - ms_add_iov(c, &ms_setting.char_block[value_offset], item->value_size); - - return 0; -} /** * for binary protocol, this function build the get command and @@ -2828,13 +3370,15 @@ static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item) */ static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item) { - assert(c->wbuf == c->wcurr); + assert(c->wbuf == c->wcurr); - ms_add_bin_header(c, PROTOCOL_BINARY_CMD_GET, 0, (uint16_t)item->key_size, (uint32_t)item->key_size); - ms_add_key_to_iov(c, item); + ms_add_bin_header(c, PROTOCOL_BINARY_CMD_GET, 0, (uint16_t)item->key_size, + (uint32_t)item->key_size); + ms_add_key_to_iov(c, item); + + return 0; +} /* ms_build_bin_write_buf_get */ - return 0; -} /** * for binary protocol, this function build the multi-get @@ -2848,21 +3392,25 @@ static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item) */ static int ms_build_bin_write_buf_mlget(ms_conn_t *c) { - ms_task_item_t *item; + ms_task_item_t *item; - assert(c->wbuf == c->wcurr); + assert(c->wbuf == c->wcurr); - for (int i = 0; i < c->mlget_task.mlget_num; i++) { - item = c->mlget_task.mlget_item[i].item; - assert(item != NULL); + for (int i= 0; i < c->mlget_task.mlget_num; i++) + { + item= c->mlget_task.mlget_item[i].item; + assert(item != NULL); - ms_add_bin_header(c, PROTOCOL_BINARY_CMD_GET, 0, (uint16_t)item->key_size, (uint32_t)item->key_size); - ms_add_key_to_iov(c, item); - c->wcurr += sizeof(protocol_binary_request_get); - } - - c->wcurr = c->wbuf; + ms_add_bin_header(c, + PROTOCOL_BINARY_CMD_GET, + 0, + (uint16_t)item->key_size, + (uint32_t)item->key_size); + ms_add_key_to_iov(c, item); + c->wcurr+= sizeof(protocol_binary_request_get); + } - return 0; -} + c->wcurr= c->wbuf; + return 0; +} /* ms_build_bin_write_buf_mlget */ diff --git a/clients/ms_conn.h b/clients/ms_conn.h index a8fd7613..efdd4aa9 100644 --- a/clients/ms_conn.h +++ b/clients/ms_conn.h @@ -23,79 +23,89 @@ extern "C" { #endif -#define DATA_BUFFER_SIZE (1024 * 1024 + 2048) /* read buffer, 1M + 2k, enough for the max value(1M) */ -#define WRITE_BUFFER_SIZE (32 * 1024) /* write buffer, 32k */ -#define UDP_DATA_BUFFER_SIZE (1 * 1024 * 1024) /* read buffer for UDP, 1M */ -#define UDP_MAX_PAYLOAD_SIZE 1400 /* server limit UDP payload size */ -#define UDP_MAX_SEND_PAYLOAD_SIZE 1400 /* mtu size is 1500 */ -#define UDP_HEADER_SIZE 8 /* UDP header size */ -#define MAX_SENDBUF_SIZE (256 * 1024 * 1024) /* Maximum socket buffer size */ -#define SOCK_WAIT_TIMEOUT 10 /* maximum waiting time of UDP, 10s */ -#define EVENT_TIMEOUT 10 /* maximum waiting time of event,10s */ -#define MAX_UDP_PACKET (1 << 16) /* maximum UDP packets, 65536 */ +#define DATA_BUFFER_SIZE (1024 * 1024 + 2048) /* read buffer, 1M + 2k, enough for the max value(1M) */ +#define WRITE_BUFFER_SIZE (32 * 1024) /* write buffer, 32k */ +#define UDP_DATA_BUFFER_SIZE (1 * 1024 * 1024) /* read buffer for UDP, 1M */ +#define UDP_MAX_PAYLOAD_SIZE 1400 /* server limit UDP payload size */ +#define UDP_MAX_SEND_PAYLOAD_SIZE 1400 /* mtu size is 1500 */ +#define UDP_HEADER_SIZE 8 /* UDP header size */ +#define MAX_SENDBUF_SIZE (256 * 1024 * 1024) /* Maximum socket buffer size */ +#define SOCK_WAIT_TIMEOUT 10 /* maximum waiting time of UDP, 10s */ +#define EVENT_TIMEOUT 10 /* maximum waiting time of event,10s */ +#define MAX_UDP_PACKET (1 << 16) /* maximum UDP packets, 65536 */ /* Initial size of the sendmsg() scatter/gather array. */ -#define IOV_LIST_INITIAL 400 +#define IOV_LIST_INITIAL 400 /* Initial number of sendmsg() argument structures to allocate. */ -#define MSG_LIST_INITIAL 10 +#define MSG_LIST_INITIAL 10 /* High water marks for buffer shrinking */ -#define READ_BUFFER_HIGHWAT (2 * DATA_BUFFER_SIZE) -#define UDP_DATA_BUFFER_HIGHWAT (4 * UDP_DATA_BUFFER_SIZE) -#define IOV_LIST_HIGHWAT 600 -#define MSG_LIST_HIGHWAT 100 +#define READ_BUFFER_HIGHWAT (2 * DATA_BUFFER_SIZE) +#define UDP_DATA_BUFFER_HIGHWAT (4 * UDP_DATA_BUFFER_SIZE) +#define IOV_LIST_HIGHWAT 600 +#define MSG_LIST_HIGHWAT 100 /* parse udp header */ -#define HEADER_TO_REQID(ptr) ((uint16_t)*ptr * 256 + (uint16_t)*(ptr + 1)) -#define HEADER_TO_SEQNUM(ptr) ((uint16_t)*(ptr + 2) * 256 + (uint16_t)*(ptr + 3)) -#define HEADER_TO_PACKETS(ptr) ((uint16_t)*(ptr + 4) * 256 + (uint16_t)*(ptr + 5)) +#define HEADER_TO_REQID(ptr) ((uint16_t)*ptr * 256 \ + + (uint16_t)*(ptr + 1)) +#define HEADER_TO_SEQNUM(ptr) ((uint16_t)*(ptr \ + + 2) * 256 \ + + (uint16_t)*(ptr + 3)) +#define HEADER_TO_PACKETS(ptr) ((uint16_t)*(ptr \ + + 4) * 256 \ + + (uint16_t)*(ptr + 5)) /* states of connection */ -enum conn_states { - conn_read, /* reading in a command line */ - conn_write, /* writing out a simple response */ - conn_closing, /* closing this connection */ +enum conn_states +{ + conn_read, /* reading in a command line */ + conn_write, /* writing out a simple response */ + conn_closing, /* closing this connection */ }; /* returned states of memcached command */ -enum mcd_ret { - MCD_SUCCESS, /* command success */ - MCD_FAILURE, /* command failure */ - MCD_UNKNOWN_READ_FAILURE, /* unknown read failure */ - MCD_PROTOCOL_ERROR, /* protocol error */ - MCD_CLIENT_ERROR, /* client error, wrong command */ - MCD_SERVER_ERROR, /* server error, server run command failed */ - MCD_DATA_EXISTS, /* object is existent in server */ - MCD_NOTSTORED, /* server doesn't set the object successfully */ - MCD_STORED, /* server set the object successfully */ - MCD_NOTFOUND, /* server not find the object */ - MCD_END, /* end of the response of get command */ - MCD_DELETED, /* server delete the object successfully */ - MCD_STAT, /* response of stats command */ +enum mcd_ret +{ + MCD_SUCCESS, /* command success */ + MCD_FAILURE, /* command failure */ + MCD_UNKNOWN_READ_FAILURE, /* unknown read failure */ + MCD_PROTOCOL_ERROR, /* protocol error */ + MCD_CLIENT_ERROR, /* client error, wrong command */ + MCD_SERVER_ERROR, /* server error, server run command failed */ + MCD_DATA_EXISTS, /* object is existent in server */ + MCD_NOTSTORED, /* server doesn't set the object successfully */ + MCD_STORED, /* server set the object successfully */ + MCD_NOTFOUND, /* server not find the object */ + MCD_END, /* end of the response of get command */ + MCD_DELETED, /* server delete the object successfully */ + MCD_STAT, /* response of stats command */ }; /* used to store the current or previous running command state */ -typedef struct cmdstat { - int cmd; /* command name */ - int retstat; /* return state of this command */ - bool isfinish; /* if it read all the response data */ - uint64_t key_prefix; /* key prefix */ +typedef struct cmdstat +{ + int cmd; /* command name */ + int retstat; /* return state of this command */ + bool isfinish; /* if it read all the response data */ + uint64_t key_prefix; /* key prefix */ } ms_cmdstat_t; /* udp packet structure */ -typedef struct udppkt { - uint8_t *header; /* udp header of the packet */ - char *data; /* udp data of the packet */ - int rbytes; /* number of data in the packet */ - int copybytes; /* number of copied data in the packet */ +typedef struct udppkt +{ + uint8_t *header; /* udp header of the packet */ + char *data; /* udp data of the packet */ + int rbytes; /* number of data in the packet */ + int copybytes; /* number of copied data in the packet */ } ms_udppkt_t; /* three protocols supported */ -enum protocol { - ascii_prot = 3, /* ASCII protocol */ - ascii_udp_prot, /* ASCII UDP protocol*/ - binary_prot, /* binary protocol */ +enum protocol +{ + ascii_prot = 3, /* ASCII protocol */ + ascii_udp_prot, /* ASCII UDP protocol*/ + binary_prot, /* binary protocol */ }; /** @@ -107,100 +117,104 @@ enum protocol { * concurrency structure includes all the private variables of * the concurrency. */ -typedef struct conn { - int conn_idx; /* connection index in the thread */ - int sfd; /* current tcp sock handler of the connection structure */ - int udpsfd; /* current udp sock handler of the connection structure*/ - int state; /* state of the connection */ - struct event event; /* event for libevent */ - short ev_flags; /* event flag for libevent */ - short which; /* which events were just triggered */ - bool change_sfd; /* whether change sfd */ - - int *tcpsfd; /* TCP sock array */ - int total_sfds; /* how many socks in the tcpsfd array */ - int alive_sfds; /* alive socks */ - int cur_idx; /* current sock index in tcpsfd array */ - - ms_cmdstat_t precmd; /* previous command state */ - ms_cmdstat_t currcmd; /* current command state */ - - char *rbuf; /* buffer to read commands into */ - char *rcurr; /* but if we parsed some already, this is where we stopped */ - int rsize; /* total allocated size of rbuf */ - int rbytes; /* how much data, starting from rcur, do we have unparsed */ - - bool readval; /* read value state, read known data size */ - int rvbytes; /* total value size need to read */ - - char *wbuf; /* buffer to write commands out */ - char *wcurr; /* for multi-get, where we stopped */ - int wsize; /* total allocated size of wbuf */ - bool ctnwrite; /* continue to write */ - - /* data for the mwrite state */ - struct iovec *iov; - int iovsize; /* number of elements allocated in iov[] */ - int iovused; /* number of elements used in iov[] */ - - struct msghdr *msglist; - int msgsize; /* number of elements allocated in msglist[] */ - int msgused; /* number of elements used in msglist[] */ - int msgcurr; /* element in msglist[] being transmitted now */ - int msgbytes; /* number of bytes in current msg */ - - /* data for UDP clients */ - int udp; /* is this is a UDP "connection" */ - int request_id; /* UDP request ID of current operation, if this is a UDP "connection" */ - uint8_t *hdrbuf; /* udp packet headers */ - int hdrsize; /* number of headers' worth of space is allocated */ - struct sockaddr srv_recv_addr; /* Sent the most recent request to which server */ - socklen_t srv_recv_addr_size; - - /* udp read buffer */ - char *rudpbuf; /* buffer to read commands into for udp */ - int rudpsize; /* total allocated size of rudpbuf */ - int rudpbytes; /* how much data, starting from rudpbuf */ - - /* order udp packet */ - ms_udppkt_t *udppkt; /* the offset of udp packet in rudpbuf */ - int packets; /* number of total packets need to read */ - int recvpkt; /* number of received packets */ - int pktcurr; /* current packet in rudpbuf being ordered */ - int ordcurr; /* current ordered packet */ - - ms_task_item_t *item_win; /* task sequence */ - int win_size; /* current task window size */ - uint64_t set_cursor; /* current set item index in the item window */ - ms_task_t curr_task; /* current running task */ - ms_mlget_task_t mlget_task; /* multi-get task */ - - int warmup_num; /* to run how many warm up operations*/ - int remain_warmup_num; /* left how many warm up operations to run */ - int64_t exec_num; /* to run how many task operations */ - int64_t remain_exec_num; /* how many remained task operations to run */ - - /* response time statistic and time out control */ - struct timeval start_time; /* start time of current operation(s) */ - struct timeval end_time; /* end time of current operation(s) */ - - /* Binary protocol stuff */ - protocol_binary_response_header binary_header; /* local temporary binary header */ - enum protocol protocol; /* which protocol this connection speaks */ +typedef struct conn +{ + int conn_idx; /* connection index in the thread */ + int sfd; /* current tcp sock handler of the connection structure */ + int udpsfd; /* current udp sock handler of the connection structure*/ + int state; /* state of the connection */ + struct event event; /* event for libevent */ + short ev_flags; /* event flag for libevent */ + short which; /* which events were just triggered */ + bool change_sfd; /* whether change sfd */ + + int *tcpsfd; /* TCP sock array */ + int total_sfds; /* how many socks in the tcpsfd array */ + int alive_sfds; /* alive socks */ + int cur_idx; /* current sock index in tcpsfd array */ + + ms_cmdstat_t precmd; /* previous command state */ + ms_cmdstat_t currcmd; /* current command state */ + + char *rbuf; /* buffer to read commands into */ + char *rcurr; /* but if we parsed some already, this is where we stopped */ + int rsize; /* total allocated size of rbuf */ + int rbytes; /* how much data, starting from rcur, do we have unparsed */ + + bool readval; /* read value state, read known data size */ + int rvbytes; /* total value size need to read */ + + char *wbuf; /* buffer to write commands out */ + char *wcurr; /* for multi-get, where we stopped */ + int wsize; /* total allocated size of wbuf */ + bool ctnwrite; /* continue to write */ + + /* data for the mwrite state */ + struct iovec *iov; + int iovsize; /* number of elements allocated in iov[] */ + int iovused; /* number of elements used in iov[] */ + + struct msghdr *msglist; + int msgsize; /* number of elements allocated in msglist[] */ + int msgused; /* number of elements used in msglist[] */ + int msgcurr; /* element in msglist[] being transmitted now */ + int msgbytes; /* number of bytes in current msg */ + + /* data for UDP clients */ + int udp; /* is this is a UDP "connection" */ + int request_id; /* UDP request ID of current operation, if this is a UDP "connection" */ + uint8_t *hdrbuf; /* udp packet headers */ + int hdrsize; /* number of headers' worth of space is allocated */ + struct sockaddr srv_recv_addr; /* Sent the most recent request to which server */ + socklen_t srv_recv_addr_size; + + /* udp read buffer */ + char *rudpbuf; /* buffer to read commands into for udp */ + int rudpsize; /* total allocated size of rudpbuf */ + int rudpbytes; /* how much data, starting from rudpbuf */ + + /* order udp packet */ + ms_udppkt_t *udppkt; /* the offset of udp packet in rudpbuf */ + int packets; /* number of total packets need to read */ + int recvpkt; /* number of received packets */ + int pktcurr; /* current packet in rudpbuf being ordered */ + int ordcurr; /* current ordered packet */ + + ms_task_item_t *item_win; /* task sequence */ + int win_size; /* current task window size */ + uint64_t set_cursor; /* current set item index in the item window */ + ms_task_t curr_task; /* current running task */ + ms_mlget_task_t mlget_task; /* multi-get task */ + + int warmup_num; /* to run how many warm up operations*/ + int remain_warmup_num; /* left how many warm up operations to run */ + int64_t exec_num; /* to run how many task operations */ + int64_t remain_exec_num; /* how many remained task operations to run */ + + /* response time statistic and time out control */ + struct timeval start_time; /* start time of current operation(s) */ + struct timeval end_time; /* end time of current operation(s) */ + + /* Binary protocol stuff */ + protocol_binary_response_header binary_header; /* local temporary binary header */ + enum protocol protocol; /* which protocol this connection speaks */ } ms_conn_t; /* used to generate the key prefix */ uint64_t ms_get_key_prefix(void); + /** * setup a connection, each connection structure of each * thread must call this function to initialize. */ int ms_setup_conn(ms_conn_t *c); + /* after one operation completes, reset the connection */ void ms_reset_conn(ms_conn_t *c, bool timeout); + /** * reconnect several disconnected socks in the connection * structure, the ever-1-second timer of the thread will check @@ -209,15 +223,19 @@ void ms_reset_conn(ms_conn_t *c, bool timeout); */ int ms_reconn_socks(ms_conn_t *c); + /* used to send set command to server */ int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item); + /* used to send the get command to server */ int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item, bool verify); + /* used to send the multi-get command to server */ int ms_mcd_mlget(ms_conn_t *c); + #ifdef __cplusplus } #endif diff --git a/clients/ms_memslap.h b/clients/ms_memslap.h index f3731fba..a2f6254d 100644 --- a/clients/ms_memslap.h +++ b/clients/ms_memslap.h @@ -30,83 +30,88 @@ extern "C" { #endif /* command line option */ -typedef enum { - OPT_VERSION= 'V', - OPT_HELP= 'h', - OPT_UDP = 'U', - OPT_SERVERS= 's', - OPT_EXECUTE_NUMBER = 'x', - OPT_THREAD_NUMBER = 'T', - OPT_CONCURRENCY = 'c', - OPT_FIXED_LTH = 'X', - OPT_VERIFY = 'v', - OPT_GETS_DIVISION = 'd', - OPT_TIME = 't', - OPT_CONFIG_CMD = 'F', - OPT_WINDOW_SIZE = 'w', - OPT_EXPIRE = 'e', - OPT_STAT_FREQ = 'S', - OPT_RECONNECT = 'R', - OPT_VERBOSE = 'b', - OPT_FACEBOOK_TEST = 'a', - OPT_SOCK_PER_CONN = 'n', - OPT_BINARY_PROTOCOL = 'B', - OPT_OVERWRITE = 'o', - OPT_TPS = 'P', - OPT_REP_WRITE_SRV = 'p', +typedef enum +{ + OPT_VERSION= 'V', + OPT_HELP= 'h', + OPT_UDP= 'U', + OPT_SERVERS= 's', + OPT_EXECUTE_NUMBER= 'x', + OPT_THREAD_NUMBER= 'T', + OPT_CONCURRENCY= 'c', + OPT_FIXED_LTH= 'X', + OPT_VERIFY= 'v', + OPT_GETS_DIVISION= 'd', + OPT_TIME= 't', + OPT_CONFIG_CMD= 'F', + OPT_WINDOW_SIZE= 'w', + OPT_EXPIRE= 'e', + OPT_STAT_FREQ= 'S', + OPT_RECONNECT= 'R', + OPT_VERBOSE= 'b', + OPT_FACEBOOK_TEST= 'a', + OPT_SOCK_PER_CONN= 'n', + OPT_BINARY_PROTOCOL= 'B', + OPT_OVERWRITE= 'o', + OPT_TPS= 'P', + OPT_REP_WRITE_SRV= 'p', } ms_options_t; /* global statistic of response time */ -typedef struct statistic { - pthread_mutex_t stat_mutex; /* synchronize the following members */ +typedef struct statistic +{ + pthread_mutex_t stat_mutex; /* synchronize the following members */ - ms_stat_t get_stat; /* statistics of get command */ - ms_stat_t set_stat; /* statistics of set command */ - ms_stat_t total_stat; /* statistics of both get and set commands */ + ms_stat_t get_stat; /* statistics of get command */ + ms_stat_t set_stat; /* statistics of set command */ + ms_stat_t total_stat; /* statistics of both get and set commands */ } ms_statistic_t; /* global status statistic structure */ -typedef struct stats { - int32_t active_conns; /* active connections */ - uint64_t bytes_read; /* read bytes */ - uint64_t bytes_written; /* written bytes */ - uint64_t obj_bytes; /* object bytes */ - uint64_t pre_cmd_get; /* previous total get command count */ - uint64_t pre_cmd_set; /* previous total set command count */ - uint64_t cmd_get; /* current total get command count */ - uint64_t cmd_set; /* current total set command count */ - uint64_t get_misses; /* total objects of get miss */ - uint64_t vef_miss; /* total objects of verification miss */ - uint64_t vef_failed; /* total objects of verification failed */ - uint64_t unexp_unget; /* total objects which is unexpired but not get */ - uint64_t exp_get; /* total objects which is expired but get */ - uint64_t pkt_disorder; /* disorder packages of UDP */ - uint64_t pkt_drop; /* packages dropped of UDP */ - uint64_t udp_timeout; /* how many times timeout of UDP happens */ +typedef struct stats +{ + int32_t active_conns; /* active connections */ + uint64_t bytes_read; /* read bytes */ + uint64_t bytes_written; /* written bytes */ + uint64_t obj_bytes; /* object bytes */ + uint64_t pre_cmd_get; /* previous total get command count */ + uint64_t pre_cmd_set; /* previous total set command count */ + uint64_t cmd_get; /* current total get command count */ + uint64_t cmd_set; /* current total set command count */ + uint64_t get_misses; /* total objects of get miss */ + uint64_t vef_miss; /* total objects of verification miss */ + uint64_t vef_failed; /* total objects of verification failed */ + uint64_t unexp_unget; /* total objects which is unexpired but not get */ + uint64_t exp_get; /* total objects which is expired but get */ + uint64_t pkt_disorder; /* disorder packages of UDP */ + uint64_t pkt_drop; /* packages dropped of UDP */ + uint64_t udp_timeout; /* how many times timeout of UDP happens */ } ms_stats_t; /* lock adapter */ -typedef struct sync_lock { - int count; - pthread_mutex_t lock; - pthread_cond_t cond; +typedef struct sync_lock +{ + int count; + pthread_mutex_t lock; + pthread_cond_t cond; } ms_sync_lock_t; /* global variable structure */ -typedef struct global { - /* synchronize lock */ - ms_sync_lock_t init_lock; - ms_sync_lock_t run_lock; +typedef struct global +{ + /* synchronize lock */ + ms_sync_lock_t init_lock; + ms_sync_lock_t run_lock; - /* mutex for outputing error log synchronously when memslap crashes */ - pthread_mutex_t quit_mutex; + /* mutex for outputing error log synchronously when memslap crashes */ + pthread_mutex_t quit_mutex; - /* mutex for generating key prefix */ - pthread_mutex_t seq_mutex; + /* mutex for generating key prefix */ + pthread_mutex_t seq_mutex; - /* global synchronous flags for slap mode */ - bool finish_warmup; - bool time_out; + /* global synchronous flags for slap mode */ + bool finish_warmup; + bool time_out; } ms_global_t; /* global structure */ diff --git a/clients/ms_setting.c b/clients/ms_setting.c index 79033299..8bcb4db5 100644 --- a/clients/ms_setting.c +++ b/clients/ms_setting.c @@ -12,25 +12,25 @@ #include "ms_setting.h" #include "ms_conn.h" -#define MAX_EXEC_NUM 0x4000000000000000 /* 1 << 62 */ -#define ADDR_ALIGN(addr) ((addr + 15) & ~(16 -1)) /* 16 bytes aligned */ -#define RAND_CHAR_SIZE (10 * 1024 * 1024) /* 10M character table */ -#define RESERVED_RAND_CHAR_SIZE (2 * 1024 * 1024) /* reserved 2M to avoid pointer sloping over */ - -#define DEFAULT_THREADS_NUM 1 /* default start one thread */ -#define DEFAULT_CONNS_NUM 16 /* default each thread with 16 connections */ -#define DEFAULT_EXE_NUM 0 /* default execute number is 0 */ -#define DEFAULT_VERIFY_RATE 0.0 /* default it doesn't do data verification */ -#define DEFAULT_OVERWRITE_RATE 0.0 /* default it doesn't do overwrite */ -#define DEFAULT_DIV 1 /* default it runs single get */ -#define DEFAULT_RUN_TIME 600 /* default run time 10 minutes */ -#define DEFAULT_WINDOW_SIZE (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */ -#define DEFAULT_SOCK_PER_CONN 1 /* default socks per connection is 1 */ +#define MAX_EXEC_NUM 0x4000000000000000 /* 1 << 62 */ +#define ADDR_ALIGN(addr) ((addr + 15) & ~(16 - 1)) /* 16 bytes aligned */ +#define RAND_CHAR_SIZE (10 * 1024 * 1024) /* 10M character table */ +#define RESERVED_RAND_CHAR_SIZE (2 * 1024 * 1024) /* reserved 2M to avoid pointer sloping over */ + +#define DEFAULT_THREADS_NUM 1 /* default start one thread */ +#define DEFAULT_CONNS_NUM 16 /* default each thread with 16 connections */ +#define DEFAULT_EXE_NUM 0 /* default execute number is 0 */ +#define DEFAULT_VERIFY_RATE 0.0 /* default it doesn't do data verification */ +#define DEFAULT_OVERWRITE_RATE 0.0 /* default it doesn't do overwrite */ +#define DEFAULT_DIV 1 /* default it runs single get */ +#define DEFAULT_RUN_TIME 600 /* default run time 10 minutes */ +#define DEFAULT_WINDOW_SIZE (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */ +#define DEFAULT_SOCK_PER_CONN 1 /* default socks per connection is 1 */ /* Use this for string generation */ -#define CHAR_COUNT 64 /* number of characters used to generate character table */ -const char ALPHANUMBERICS[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-"; +#define CHAR_COUNT 64 /* number of characters used to generate character table */ +const char ALPHANUMBERICS[]= + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-"; ms_setting_t ms_setting; /* store the settings specified by user */ @@ -39,11 +39,12 @@ ms_setting_t ms_setting; /* store the settings specified by user */ static void ms_get_serverlist(char *str); static int ms_get_cpu_count(void); ms_conf_type_t ms_get_conf_type(char *line); -static int ms_is_line_data(char* line); -static int ms_read_is_data(char* line, ssize_t nread); +static int ms_is_line_data(char *line); +static int ms_read_is_data(char *line, ssize_t nread); static void ms_no_config_file(void); static void ms_parse_cfg_file(char *cfg_file); + /* initialize setting structure */ static void ms_init_random_block(void); static void ms_calc_avg_size(void); @@ -63,64 +64,74 @@ static void ms_setting_slapmode_init_post(void); */ static void ms_get_serverlist(char *str) { - char *string; - int64_t port; - char *begin_ptr; - char *end_ptr = str + strlen(str); - ms_mcd_server_t *srvs = NULL; - char buffer[512]; - char *ptr = NULL; - - /** - * Servers list format is like this. For example: - * "localhost:11108, localhost:11109" - */ - for (begin_ptr = str, string = index(str, ','); - begin_ptr != end_ptr; - string = index(begin_ptr, ',')) { - port = 0; - - if (string) { - memcpy(buffer, begin_ptr, (size_t)(string - begin_ptr)); - buffer[(unsigned int)(string - begin_ptr)]= '\0'; - begin_ptr = string+1; - } else { - size_t length= strlen(begin_ptr); - memcpy(buffer, begin_ptr, length); - buffer[length] = '\0'; - begin_ptr = end_ptr; - } - - ptr = index(buffer, ':'); - - if (ptr != NULL) { - ptr[0] = '\0'; - ptr++; - port = strtol(ptr, (char **)NULL, 10); - } + char *string; + int64_t port; + char *begin_ptr; + char *end_ptr= str + strlen(str); + ms_mcd_server_t *srvs= NULL; + char buffer[512]; + char *ptr= NULL; + + /** + * Servers list format is like this. For example: + * "localhost:11108, localhost:11109" + */ + for (begin_ptr= str, string= index(str, ','); + begin_ptr != end_ptr; + string= index(begin_ptr, ',')) + { + port= 0; + + if (string) + { + memcpy(buffer, begin_ptr, (size_t)(string - begin_ptr)); + buffer[(unsigned int)(string - begin_ptr)]= '\0'; + begin_ptr= string + 1; + } + else + { + size_t length= strlen(begin_ptr); + memcpy(buffer, begin_ptr, length); + buffer[length]= '\0'; + begin_ptr= end_ptr; + } + + ptr= index(buffer, ':'); + + if (ptr != NULL) + { + ptr[0]= '\0'; + ptr++; + port= strtol(ptr, (char **)NULL, 10); + } + + assert(ms_setting.srv_cnt < ms_setting.total_srv_cnt); + strcpy(ms_setting.servers[ms_setting.srv_cnt].srv_host_name, buffer); + ms_setting.servers[ms_setting.srv_cnt].srv_port= (int)port; + ms_setting.servers[ms_setting.srv_cnt].disconn_cnt= 0; + ms_setting.servers[ms_setting.srv_cnt].reconn_cnt= 0; + ms_setting.srv_cnt++; + + if (ms_setting.srv_cnt >= ms_setting.total_srv_cnt) + { + srvs= (ms_mcd_server_t *)realloc( + ms_setting.servers, + (uint64_t)ms_setting.total_srv_cnt + * sizeof(ms_mcd_server_t) * 2); + if (srvs == NULL) + { + fprintf(stderr, "Can't reallocate servers structure.\n"); + exit(1); + } + ms_setting.servers= srvs; + ms_setting.total_srv_cnt*= 2; + } - assert(ms_setting.srv_cnt < ms_setting.total_srv_cnt); - strcpy(ms_setting.servers[ms_setting.srv_cnt].srv_host_name, buffer); - ms_setting.servers[ms_setting.srv_cnt].srv_port = (int)port; - ms_setting.servers[ms_setting.srv_cnt].disconn_cnt = 0; - ms_setting.servers[ms_setting.srv_cnt].reconn_cnt = 0; - ms_setting.srv_cnt++; - - if (ms_setting.srv_cnt >= ms_setting.total_srv_cnt) { - srvs = (ms_mcd_server_t *)realloc(ms_setting.servers, - (uint64_t)ms_setting.total_srv_cnt * sizeof(ms_mcd_server_t) * 2); - if (srvs == NULL) { - fprintf(stderr, "Can't reallocate servers structure.\n"); - exit(1); - } - ms_setting.servers = srvs; - ms_setting.total_srv_cnt *= 2; - } + if (isspace(*begin_ptr)) + begin_ptr++; + } +} /* ms_get_serverlist */ - if (isspace(*begin_ptr)) - begin_ptr++; - } -} /** * used to get the CPU count of the current system @@ -130,27 +141,32 @@ static void ms_get_serverlist(char *str) static int ms_get_cpu_count() { #ifdef HAVE__SC_NPROCESSORS_ONLN - return (sysconf(_SC_NPROCESSORS_CONF)); + return sysconf(_SC_NPROCESSORS_CONF); + #else -#ifdef HAVE_CPU_SET_T - int cpu_count = 0; - cpu_set_t cpu_set; +# ifdef HAVE_CPU_SET_T + int cpu_count= 0; + cpu_set_t cpu_set; - sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set); + sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set); - for (int i = 0; i < (sizeof(cpu_set_t) * 8); i++) { - if (CPU_ISSET(i, &cpu_set)) { - cpu_count++; - } + for (int i= 0; i < (sizeof(cpu_set_t) * 8); i++) + { + if (CPU_ISSET(i, &cpu_set)) + { + cpu_count++; } + } - return cpu_count; -#endif + return cpu_count; + +# endif #endif - /* the system with one cpu at least */ - return 1; -} + /* the system with one cpu at least */ + return 1; +} /* ms_get_cpu_count */ + /** * used to get the configure type based on the type string read @@ -162,16 +178,24 @@ static int ms_get_cpu_count() */ ms_conf_type_t ms_get_conf_type(char *line) { - if (!memcmp(line, "key", strlen("key")) ) { - return CONF_KEY; - } else if (!memcmp(line, "value", strlen("value"))) { - return CONF_VALUE; - } else if (!memcmp(line, "cmd", strlen("cmd"))) { - return CONF_CMD; - } else { - return CONF_NULL; - } -} + if (! memcmp(line, "key", strlen("key"))) + { + return CONF_KEY; + } + else if (! memcmp(line, "value", strlen("value"))) + { + return CONF_VALUE; + } + else if (! memcmp(line, "cmd", strlen("cmd"))) + { + return CONF_CMD; + } + else + { + return CONF_NULL; + } +} /* ms_get_conf_type */ + /** * judge whether the line is a line with useful data. used to @@ -181,18 +205,22 @@ ms_conf_type_t ms_get_conf_type(char *line) * * @return if success, return 1, else return 0 */ -static int ms_is_line_data(char* line) +static int ms_is_line_data(char *line) { - assert(line != NULL); + assert(line != NULL); - char* begin_ptr = line; + char *begin_ptr= line; + + while (isspace(*begin_ptr)) + { + begin_ptr++; + } + if ((begin_ptr[0] == '\0') || (begin_ptr[0] == '#')) + return 0; + + return 1; +} /* ms_is_line_data */ - while(isspace(*begin_ptr)) - begin_ptr++; - if (begin_ptr[0] == '\0' || begin_ptr[0] == '#') - return 0; - return 1; -} /** * function to bypass blank line and comments @@ -202,12 +230,14 @@ static int ms_is_line_data(char* line) * * @return if it's EOF or not line data, return 0, else return 1 */ -static int ms_read_is_data(char* line, ssize_t nread) +static int ms_read_is_data(char *line, ssize_t nread) { - if (nread == EOF || !ms_is_line_data(line)) - return 0; - return 1; -} + if ((nread == EOF) || ! ms_is_line_data(line)) + return 0; + + return 1; +} /* ms_read_is_data */ + /** * if no configuration file, use this function to create the default @@ -215,12 +245,14 @@ static int ms_read_is_data(char* line, ssize_t nread) */ static void ms_no_config_file() { - FILE *fd = fopen("config", "w+"); - fprintf(fd, "%s", DEFAULT_CONGIF_STR); - fclose(fd); + FILE *fd= fopen("config", "w+"); + + fprintf(fd, "%s", DEFAULT_CONGIF_STR); + fclose(fd); + + ms_setting.cfg_file= strdup("config"); +} /* ms_no_config_file */ - ms_setting.cfg_file = strdup("config"); -} /** * parse the configuration file @@ -229,198 +261,236 @@ static void ms_no_config_file() */ static void ms_parse_cfg_file(char *cfg_file) { - FILE *f; - size_t start_len, end_len; - double proportion; - size_t frequence; - char* line = NULL; - size_t read_len; - ssize_t nread; - int cmd_type; - ms_conf_type_t conf_type; - int end_of_file = 0; - ms_key_distr_t *key_distr = NULL; - ms_value_distr_t *val_distr = NULL; - bool no_cfg = false; - - if (cfg_file == NULL) { - ms_no_config_file(); - cfg_file = ms_setting.cfg_file; - no_cfg = true; - } - - /*read key value configure file*/ - if ( (f = fopen(cfg_file, "r")) == NULL) { - fprintf(stderr, "Can not open file: '%s'.\n", cfg_file); - exit(1); - } - - while (1) { - if ((((nread = getline(&line, &read_len, f)) == 1) || - !ms_read_is_data(line, nread)) && (nread != EOF))/* bypass blank line */ - continue; - if (nread == EOF) { - fprintf(stderr, "Bad configuration file, no configuration find.\n"); - exit(1); - } - conf_type = ms_get_conf_type(line); - break; - } - - while (!end_of_file) { - switch (conf_type) { - case CONF_KEY: - while (1) { - if ((((nread = getline(&line, &read_len, f)) == 1) || - !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ - continue; - - if (nread != EOF) { - if (sscanf(line, "%lu %lu %lf ", &start_len, - &end_len, &proportion) != 3) { - conf_type = ms_get_conf_type(line); - break; - } - ms_setting.key_distr[ms_setting.key_rng_cnt].start_len = start_len; - ms_setting.key_distr[ms_setting.key_rng_cnt].end_len = end_len; - ms_setting.key_distr[ms_setting.key_rng_cnt].key_prop = proportion; - ms_setting.key_rng_cnt++; - - if (ms_setting.key_rng_cnt >= ms_setting.total_key_rng_cnt) { - key_distr = (ms_key_distr_t *)realloc(ms_setting.key_distr, - (uint64_t)ms_setting.total_key_rng_cnt * sizeof(ms_key_distr_t) * 2); - if (key_distr == NULL) { - fprintf(stderr, "Can't reallocate key distribution structure.\n"); - exit(1); - } - ms_setting.key_distr = key_distr; - ms_setting.total_key_rng_cnt *= 2; - } - continue; - } - end_of_file = 1; - break; - } + FILE *f; + size_t start_len, end_len; + double proportion; + size_t frequence; + char *line= NULL; + size_t read_len; + ssize_t nread; + int cmd_type; + ms_conf_type_t conf_type; + int end_of_file= 0; + ms_key_distr_t *key_distr= NULL; + ms_value_distr_t *val_distr= NULL; + bool no_cfg= false; + + if (cfg_file == NULL) + { + ms_no_config_file(); + cfg_file= ms_setting.cfg_file; + no_cfg= true; + } + + /*read key value configure file*/ + if ((f= fopen(cfg_file, "r")) == NULL) + { + fprintf(stderr, "Can not open file: '%s'.\n", cfg_file); + exit(1); + } + + while (1) + { + if ((((nread= getline(&line, &read_len, f)) == 1) + || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ + continue; + if (nread == EOF) + { + fprintf(stderr, "Bad configuration file, no configuration find.\n"); + exit(1); + } + conf_type= ms_get_conf_type(line); + break; + } + + while (! end_of_file) + { + switch (conf_type) + { + case CONF_KEY: + while (1) + { + if ((((nread= getline(&line, &read_len, f)) == 1) + || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ + continue; + + if (nread != EOF) + { + if (sscanf(line, "%lu %lu %lf ", &start_len, + &end_len, &proportion) != 3) + { + conf_type= ms_get_conf_type(line); break; - - case CONF_VALUE: - while (1) { - if ((((nread = getline(&line, &read_len, f)) == 1) || - !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ - continue; - - if (nread != EOF) { - if (sscanf(line, "%lu %lu %lf %lu", &start_len, &end_len, - &proportion, &frequence) !=3 ) { - conf_type = ms_get_conf_type(line); - break; - } - ms_setting.value_distr[ms_setting.val_rng_cnt].start_len = start_len; - ms_setting.value_distr[ms_setting.val_rng_cnt].end_len = end_len; - ms_setting.value_distr[ms_setting.val_rng_cnt].value_prop = proportion; - ms_setting.val_rng_cnt++; - - if (ms_setting.val_rng_cnt >= ms_setting.total_val_rng_cnt) { - val_distr = (ms_value_distr_t *)realloc(ms_setting.value_distr, - (uint64_t)ms_setting.total_val_rng_cnt * sizeof(ms_value_distr_t) * 2); - if (val_distr == NULL) { - fprintf(stderr, "Can't reallocate key distribution structure.\n"); - exit(1); - } - ms_setting.value_distr = val_distr; - ms_setting.total_val_rng_cnt *= 2; - } - continue; - } - end_of_file = 1; - break; + } + ms_setting.key_distr[ms_setting.key_rng_cnt].start_len= start_len; + ms_setting.key_distr[ms_setting.key_rng_cnt].end_len= end_len; + ms_setting.key_distr[ms_setting.key_rng_cnt].key_prop= proportion; + ms_setting.key_rng_cnt++; + + if (ms_setting.key_rng_cnt >= ms_setting.total_key_rng_cnt) + { + key_distr= (ms_key_distr_t *)realloc( + ms_setting.key_distr, + (uint64_t)ms_setting. + total_key_rng_cnt * sizeof(ms_key_distr_t) * 2); + if (key_distr == NULL) + { + fprintf(stderr, + "Can't reallocate key distribution structure.\n"); + exit(1); } + ms_setting.key_distr= key_distr; + ms_setting.total_key_rng_cnt*= 2; + } + continue; + } + end_of_file= 1; + break; + } + break; + + case CONF_VALUE: + while (1) + { + if ((((nread= getline(&line, &read_len, f)) == 1) + || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ + continue; + + if (nread != EOF) + { + if (sscanf(line, "%lu %lu %lf %lu", &start_len, &end_len, + &proportion, &frequence) != 3) + { + conf_type= ms_get_conf_type(line); break; - - case CONF_CMD: - while (1) { - if ((((nread = getline(&line, &read_len, f)) == 1) || - !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ - continue; - - if (nread != EOF) { - if (sscanf(line, "%d %lf\n", &cmd_type, &proportion) != 2) { - conf_type = ms_get_conf_type(line); - break; - } - ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_type = cmd_type; - ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_prop = proportion; - ms_setting.cmd_used_count++; - continue; - } - end_of_file = 1; - break; - } - - case CONF_NULL: - while (1) { - if ((((nread = getline(&line, &read_len, f)) == 1) || - !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ - continue; - - if (nread != EOF) { - if ((conf_type = ms_get_conf_type(line)) != CONF_NULL) { - break; - } - continue; - } - end_of_file = 1; - break; + } + ms_setting.value_distr[ms_setting.val_rng_cnt].start_len= + start_len; + ms_setting.value_distr[ms_setting.val_rng_cnt].end_len= end_len; + ms_setting.value_distr[ms_setting.val_rng_cnt].value_prop= + proportion; + ms_setting.val_rng_cnt++; + + if (ms_setting.val_rng_cnt >= ms_setting.total_val_rng_cnt) + { + val_distr= (ms_value_distr_t *)realloc( + ms_setting.value_distr, + (uint64_t)ms_setting. + total_val_rng_cnt * sizeof(ms_value_distr_t) * 2); + if (val_distr == NULL) + { + fprintf(stderr, + "Can't reallocate key distribution structure.\n"); + exit(1); } + ms_setting.value_distr= val_distr; + ms_setting.total_val_rng_cnt*= 2; + } + continue; + } + end_of_file= 1; + break; + } + break; + + case CONF_CMD: + while (1) + { + if ((((nread= getline(&line, &read_len, f)) == 1) + || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ + continue; + + if (nread != EOF) + { + if (sscanf(line, "%d %lf\n", &cmd_type, &proportion) != 2) + { + conf_type= ms_get_conf_type(line); break; - default: - assert(0); + } + ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_type= + cmd_type; + ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_prop= + proportion; + ms_setting.cmd_used_count++; + continue; + } + end_of_file= 1; + break; + } + + case CONF_NULL: + while (1) + { + if ((((nread= getline(&line, &read_len, f)) == 1) + || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */ + continue; + + if (nread != EOF) + { + if ((conf_type= ms_get_conf_type(line)) != CONF_NULL) + { break; + } + continue; } - } + end_of_file= 1; + break; + } + break; - fclose(f); + default: + assert(0); + break; + } /* switch */ + } - if (no_cfg) { - remove(ms_setting.cfg_file); - } + fclose(f); + + if (no_cfg) + { + remove(ms_setting.cfg_file); + } + + if (line != NULL) + free(line); +} /* ms_parse_cfg_file */ - if (line != NULL) - free(line); -} /* calculate the average size of key and value */ static void ms_calc_avg_size() { - double avg_val_size = 0.0; - double avg_key_size = 0.0; - double val_pro = 0.0; - double key_pro = 0.0; - double averge_len = 0.0; - size_t start_len = 0; - size_t end_len = 0; - - for (int j = 0; j < ms_setting.val_rng_cnt; j++) { - val_pro = ms_setting.value_distr[j].value_prop; - start_len = ms_setting.value_distr[j].start_len; - end_len = ms_setting.value_distr[j].end_len; - - averge_len = val_pro * ((double)(start_len + end_len)) / 2; - avg_val_size += averge_len; - } - - for (int j = 0; j < ms_setting.key_rng_cnt; j++) { - key_pro = ms_setting.key_distr[j].key_prop; - start_len = ms_setting.key_distr[j].start_len; - end_len = ms_setting.key_distr[j].end_len; - - averge_len = key_pro * ((double)(start_len + end_len)) / 2; - avg_key_size += averge_len; - } + double avg_val_size= 0.0; + double avg_key_size= 0.0; + double val_pro= 0.0; + double key_pro= 0.0; + double averge_len= 0.0; + size_t start_len= 0; + size_t end_len= 0; + + for (int j= 0; j < ms_setting.val_rng_cnt; j++) + { + val_pro= ms_setting.value_distr[j].value_prop; + start_len= ms_setting.value_distr[j].start_len; + end_len= ms_setting.value_distr[j].end_len; + + averge_len= val_pro * ((double)(start_len + end_len)) / 2; + avg_val_size+= averge_len; + } + + for (int j= 0; j < ms_setting.key_rng_cnt; j++) + { + key_pro= ms_setting.key_distr[j].key_prop; + start_len= ms_setting.key_distr[j].start_len; + end_len= ms_setting.key_distr[j].end_len; + + averge_len= key_pro * ((double)(start_len + end_len)) / 2; + avg_key_size+= averge_len; + } + + ms_setting.avg_val_size= (size_t)avg_val_size; + ms_setting.avg_key_size= (size_t)avg_key_size; +} /* ms_calc_avg_size */ - ms_setting.avg_val_size = (size_t)avg_val_size; - ms_setting.avg_key_size = (size_t)avg_key_size; -} /** * used to shuffle key and value distribution array to ensure @@ -433,38 +503,44 @@ static void ms_calc_avg_size() */ static int ms_shuffle_distr(ms_distr_t *distr, int length) { - int i, j; - int tmp_offset; - size_t tmp_size; - int64_t rnd; - - for (i = 0; i < length; i++) { - rnd = random(); - j = (int)(rnd % (length - i)) + i; - - switch (rnd % 3) { - case 0: - tmp_size = distr[j].key_size; - distr[j].key_size = distr[i].key_size; - distr[i].key_size = tmp_size; - break; - case 1: - tmp_offset = distr[j].key_offset; - distr[j].key_offset = distr[i].key_offset; - distr[i].key_offset = tmp_offset; - break; - case 2: - tmp_size = distr[j].value_size; - distr[j].value_size = distr[i].value_size; - distr[i].value_size = tmp_size; - break; - default: - break; - } - } - - return 0; -} + int i, j; + int tmp_offset; + size_t tmp_size; + int64_t rnd; + + for (i= 0; i < length; i++) + { + rnd= random(); + j= (int)(rnd % (length - i)) + i; + + switch (rnd % 3) + { + case 0: + tmp_size= distr[j].key_size; + distr[j].key_size= distr[i].key_size; + distr[i].key_size= tmp_size; + break; + + case 1: + tmp_offset= distr[j].key_offset; + distr[j].key_offset= distr[i].key_offset; + distr[i].key_offset= tmp_offset; + break; + + case 2: + tmp_size= distr[j].value_size; + distr[j].value_size= distr[i].value_size; + distr[i].value_size= tmp_size; + break; + + default: + break; + } /* switch */ + } + + return 0; +} /* ms_shuffle_distr */ + /** * according to the key and value distribution, to build the @@ -475,143 +551,187 @@ static int ms_shuffle_distr(ms_distr_t *distr, int length) */ static void ms_build_distr() { - int offset = 0; - int end = 0; - int key_cnt = 0; - int value_cnt = 0; - size_t average_len = 0; - size_t diff_len = 0; - size_t start_len = 0; - size_t end_len = 0; - int rnd = 0; - ms_distr_t *distr = NULL; - int units = (int)ms_setting.win_size / UNIT_ITEMS_COUNT; - - /* calculate average value size and key size */ - ms_calc_avg_size(); - - ms_setting.char_blk_size = RAND_CHAR_SIZE; - int key_scope_size = (int)((ms_setting.char_blk_size - RESERVED_RAND_CHAR_SIZE) - / UNIT_ITEMS_COUNT); - - ms_setting.distr = (ms_distr_t *)malloc(sizeof(ms_distr_t) * ms_setting.win_size); - if (ms_setting.distr == NULL) { - fprintf(stderr, "Can't allocate distribution array."); + int offset= 0; + int end= 0; + int key_cnt= 0; + int value_cnt= 0; + size_t average_len= 0; + size_t diff_len= 0; + size_t start_len= 0; + size_t end_len= 0; + int rnd= 0; + ms_distr_t *distr= NULL; + int units= (int)ms_setting.win_size / UNIT_ITEMS_COUNT; + + /* calculate average value size and key size */ + ms_calc_avg_size(); + + ms_setting.char_blk_size= RAND_CHAR_SIZE; + int key_scope_size= + (int)((ms_setting.char_blk_size - RESERVED_RAND_CHAR_SIZE) + / UNIT_ITEMS_COUNT); + + ms_setting.distr= (ms_distr_t *)malloc( + sizeof(ms_distr_t) * ms_setting.win_size); + if (ms_setting.distr == NULL) + { + fprintf(stderr, "Can't allocate distribution array."); + exit(1); + } + + /** + * character block is divided by how many different key + * size, each different key size has the same size character + * range. + */ + for (int m= 0; m < units; m++) + { + for (int i= 0; i < UNIT_ITEMS_COUNT; i++) + { + ms_setting.distr[m * UNIT_ITEMS_COUNT + i].key_offset= + ADDR_ALIGN(key_scope_size * i); + } + } + + /* initialize key size distribution */ + for (int m= 0; m < units; m++) + { + for (int j= 0; j < ms_setting.key_rng_cnt; j++) + { + key_cnt= (int)(UNIT_ITEMS_COUNT * ms_setting.key_distr[j].key_prop); + start_len= ms_setting.key_distr[j].start_len; + end_len= ms_setting.key_distr[j].end_len; + if ((start_len < MIN_KEY_SIZE) || (end_len < MIN_KEY_SIZE)) + { + fprintf(stderr, "key length must be greater than 16 bytes.\n"); exit(1); - } + } - /** - * character block is divided by how many different key - * size, each different key size has the same size character - * range. - */ - for (int m = 0; m < units; m++) { - for (int i = 0; i < UNIT_ITEMS_COUNT; i++) { - ms_setting.distr[m * UNIT_ITEMS_COUNT + i].key_offset = - ADDR_ALIGN(key_scope_size * i); + if (! ms_setting.binary_prot + && ((start_len > MAX_KEY_SIZE) || (end_len > MAX_KEY_SIZE))) + { + fprintf(stderr, "key length must be less than 250 bytes.\n"); + exit(1); + } + + average_len= (start_len + end_len) / 2; + diff_len= (end_len - start_len) / 2; + for (int k= 0; k < key_cnt; k++) + { + if (offset >= (m + 1) * UNIT_ITEMS_COUNT) + { + break; } - } - - /* initialize key size distribution */ - for (int m = 0; m < units; m++) { - for (int j = 0; j < ms_setting.key_rng_cnt; j++) { - key_cnt = (int)(UNIT_ITEMS_COUNT * ms_setting.key_distr[j].key_prop); - start_len = ms_setting.key_distr[j].start_len; - end_len = ms_setting.key_distr[j].end_len; - if (start_len < MIN_KEY_SIZE || end_len < MIN_KEY_SIZE) { - fprintf(stderr, "key length must be greater than 16 bytes.\n"); - exit(1); - } - - if (!ms_setting.binary_prot && (start_len > MAX_KEY_SIZE || end_len > MAX_KEY_SIZE)) { - fprintf(stderr, "key length must be less than 250 bytes.\n"); - exit(1); - } - - average_len = (start_len + end_len) / 2; - diff_len = (end_len - start_len) / 2; - for (int k = 0; k < key_cnt; k++) { - if (offset >= (m + 1) * UNIT_ITEMS_COUNT) { - break; - } - rnd = (int)random(); - if (k % 2 == 0) { - ms_setting.distr[offset].key_size = (diff_len == 0) ? average_len : - average_len + (size_t)rnd % diff_len; - } else { - ms_setting.distr[offset].key_size = (diff_len == 0) ? average_len : - average_len - (size_t)rnd % diff_len; - } - offset++; - } + rnd= (int)random(); + if (k % 2 == 0) + { + ms_setting.distr[offset].key_size= + (diff_len == 0) ? average_len : + average_len + (size_t)rnd + % diff_len; } - - if (offset < (m + 1) * UNIT_ITEMS_COUNT) { - end = (m + 1) * UNIT_ITEMS_COUNT - offset; - for (int i = 0; i < end; i++) { - ms_setting.distr[offset].key_size = ms_setting.avg_key_size; - offset++; - } + else + { + ms_setting.distr[offset].key_size= + (diff_len == 0) ? average_len : + average_len - (size_t)rnd + % diff_len; + } + offset++; + } + } + + if (offset < (m + 1) * UNIT_ITEMS_COUNT) + { + end= (m + 1) * UNIT_ITEMS_COUNT - offset; + for (int i= 0; i < end; i++) + { + ms_setting.distr[offset].key_size= ms_setting.avg_key_size; + offset++; + } + } + } + offset= 0; + + /* initialize value distribution */ + if (ms_setting.fixed_value_size != 0) + { + for (int i= 0; i < units * UNIT_ITEMS_COUNT; i++) + { + ms_setting.distr[i].value_size= ms_setting.fixed_value_size; + } + } + else + { + for (int m= 0; m < units; m++) + { + for (int j= 0; j < ms_setting.val_rng_cnt; j++) + { + value_cnt= + (int)(UNIT_ITEMS_COUNT * ms_setting.value_distr[j].value_prop); + start_len= ms_setting.value_distr[j].start_len; + end_len= ms_setting.value_distr[j].end_len; + if ((start_len <= 0) || (end_len <= 0)) + { + fprintf(stderr, "value length must be greater than 0 bytes.\n"); + exit(1); } - } - offset = 0; - /* initialize value distribution */ - if (ms_setting.fixed_value_size != 0) { - for (int i = 0; i < units * UNIT_ITEMS_COUNT; i++) { - ms_setting.distr[i].value_size = ms_setting.fixed_value_size; + if ((start_len > MAX_VALUE_SIZE) || (end_len > MAX_VALUE_SIZE)) + { + fprintf(stderr, "key length must be less than or equal to 1M.\n"); + exit(1); } - } else { - for (int m = 0; m < units; m++) { - for (int j = 0; j < ms_setting.val_rng_cnt; j++) { - value_cnt = (int)(UNIT_ITEMS_COUNT * ms_setting.value_distr[j].value_prop); - start_len = ms_setting.value_distr[j].start_len; - end_len = ms_setting.value_distr[j].end_len; - if (start_len <= 0 || end_len <= 0) { - fprintf(stderr, "value length must be greater than 0 bytes.\n"); - exit(1); - } - - if (start_len > MAX_VALUE_SIZE || end_len > MAX_VALUE_SIZE) { - fprintf(stderr, "key length must be less than or equal to 1M.\n"); - exit(1); - } - - average_len = (start_len + end_len) / 2; - diff_len = (end_len - start_len) / 2; - for (int k = 0; k < value_cnt; k++) { - if (offset >= (m + 1) * UNIT_ITEMS_COUNT) { - break; - } - rnd = (int)random(); - if (k % 2 == 0) { - ms_setting.distr[offset].value_size = (diff_len == 0) ? average_len : - average_len + (size_t)rnd % diff_len; - } else { - ms_setting.distr[offset].value_size = (diff_len == 0) ? average_len : - average_len - (size_t)rnd % diff_len; - } - offset++; - } - } - if (offset < (m + 1) * UNIT_ITEMS_COUNT) { - end = (m + 1) * UNIT_ITEMS_COUNT - offset; - for (int i =0; i < end; i++) { - ms_setting.distr[offset++].value_size = ms_setting.avg_val_size; - } - } + average_len= (start_len + end_len) / 2; + diff_len= (end_len - start_len) / 2; + for (int k= 0; k < value_cnt; k++) + { + if (offset >= (m + 1) * UNIT_ITEMS_COUNT) + { + break; + } + rnd= (int)random(); + if (k % 2 == 0) + { + ms_setting.distr[offset].value_size= + (diff_len == 0) ? average_len : + average_len + + (size_t)rnd % diff_len; + } + else + { + ms_setting.distr[offset].value_size= + (diff_len == 0) ? average_len : + average_len + - (size_t)rnd % diff_len; + } + offset++; + } + } + + if (offset < (m + 1) * UNIT_ITEMS_COUNT) + { + end= (m + 1) * UNIT_ITEMS_COUNT - offset; + for (int i= 0; i < end; i++) + { + ms_setting.distr[offset++].value_size= ms_setting.avg_val_size; } + } } + } - /* shuffle distribution */ - for (int i = 0; i < units; i++) { - distr = &ms_setting.distr[i * UNIT_ITEMS_COUNT]; - for (int j = 0; j < 4; j++) { - ms_shuffle_distr(distr, UNIT_ITEMS_COUNT); - } + /* shuffle distribution */ + for (int i= 0; i < units; i++) + { + distr= &ms_setting.distr[i * UNIT_ITEMS_COUNT]; + for (int j= 0; j < 4; j++) + { + ms_shuffle_distr(distr, UNIT_ITEMS_COUNT); } -} + } +} /* ms_build_distr */ + /** * used to initialize the global character block. The character @@ -622,21 +742,24 @@ static void ms_build_distr() */ static void ms_init_random_block() { - char *ptr = NULL; + char *ptr= NULL; - assert(ms_setting.char_blk_size > 0); + assert(ms_setting.char_blk_size > 0); - ms_setting.char_block = (char *)malloc(ms_setting.char_blk_size); - if (ms_setting.char_block == NULL) { - fprintf(stderr, "Can't allocate global char block."); - exit(1); - } - ptr = ms_setting.char_block; + ms_setting.char_block= (char *)malloc(ms_setting.char_blk_size); + if (ms_setting.char_block == NULL) + { + fprintf(stderr, "Can't allocate global char block."); + exit(1); + } + ptr= ms_setting.char_block; + + for (int i= 0; (size_t)i < ms_setting.char_blk_size; i++) + { + *(ptr++)= ALPHANUMBERICS[random() % CHAR_COUNT]; + } +} /* ms_init_random_block */ - for (int i = 0; (size_t)i < ms_setting.char_blk_size; i++) { - *(ptr++) = ALPHANUMBERICS[random() % CHAR_COUNT]; - } -} /** * after initialization, call this function to output the main @@ -644,207 +767,246 @@ static void ms_init_random_block() */ static void ms_print_setting() { - fprintf(stdout, "threads count: %d\n", ms_setting.nthreads); - fprintf(stdout, "concurrency: %d\n", ms_setting.nconns); - if (ms_setting.run_time > 0) { - fprintf(stdout, "run time: %ds\n", ms_setting.run_time); - } else { - fprintf(stdout, "execute number: %ld\n", ms_setting.exec_num); - } - fprintf(stdout, "windows size: %ldk\n", (int64_t)(ms_setting.win_size / 1024)); - fprintf(stdout, "set proportion: set_prop=%.2f\n", - ms_setting.cmd_distr[CMD_SET].cmd_prop); - fprintf(stdout, "get proportion: get_prop=%.2f\n", - ms_setting.cmd_distr[CMD_GET].cmd_prop); - fflush(stdout); -} + fprintf(stdout, "threads count: %d\n", ms_setting.nthreads); + fprintf(stdout, "concurrency: %d\n", ms_setting.nconns); + if (ms_setting.run_time > 0) + { + fprintf(stdout, "run time: %ds\n", ms_setting.run_time); + } + else + { + fprintf(stdout, "execute number: %ld\n", ms_setting.exec_num); + } + fprintf(stdout, "windows size: %ldk\n", + (int64_t)(ms_setting.win_size / 1024)); + fprintf(stdout, "set proportion: set_prop=%.2f\n", + ms_setting.cmd_distr[CMD_SET].cmd_prop); + fprintf(stdout, "get proportion: get_prop=%.2f\n", + ms_setting.cmd_distr[CMD_GET].cmd_prop); + fflush(stdout); +} /* ms_print_setting */ + /** * previous part of slap mode initialization of setting structure */ static void ms_setting_slapmode_init_pre() { - ms_setting.exec_num = DEFAULT_EXE_NUM; - ms_setting.verify_percent = DEFAULT_VERIFY_RATE; - ms_setting.exp_ver_per = DEFAULT_VERIFY_RATE; - ms_setting.overwrite_percent = DEFAULT_OVERWRITE_RATE; - ms_setting.mult_key_num = DEFAULT_DIV; - ms_setting.fixed_value_size = 0; - ms_setting.win_size = DEFAULT_WINDOW_SIZE; - ms_setting.udp = false; - ms_setting.reconnect = false; - ms_setting.verbose = false; - ms_setting.facebook_test = false; - ms_setting.binary_prot = false; - ms_setting.stat_freq = 0; - ms_setting.srv_str = NULL; - ms_setting.cfg_file = NULL; - ms_setting.sock_per_conn = DEFAULT_SOCK_PER_CONN; - ms_setting.expected_tps = 0; - ms_setting.rep_write_srv = 0; -} + ms_setting.exec_num= DEFAULT_EXE_NUM; + ms_setting.verify_percent= DEFAULT_VERIFY_RATE; + ms_setting.exp_ver_per= DEFAULT_VERIFY_RATE; + ms_setting.overwrite_percent= DEFAULT_OVERWRITE_RATE; + ms_setting.mult_key_num= DEFAULT_DIV; + ms_setting.fixed_value_size= 0; + ms_setting.win_size= DEFAULT_WINDOW_SIZE; + ms_setting.udp= false; + ms_setting.reconnect= false; + ms_setting.verbose= false; + ms_setting.facebook_test= false; + ms_setting.binary_prot= false; + ms_setting.stat_freq= 0; + ms_setting.srv_str= NULL; + ms_setting.cfg_file= NULL; + ms_setting.sock_per_conn= DEFAULT_SOCK_PER_CONN; + ms_setting.expected_tps= 0; + ms_setting.rep_write_srv= 0; +} /* ms_setting_slapmode_init_pre */ + /** * previous part of initialization of setting structure */ void ms_setting_init_pre() { - memset(&ms_setting, 0, sizeof(ms_setting_t)); - - /* common initialize */ - ms_setting.ncpu = ms_get_cpu_count(); - ms_setting.nthreads = DEFAULT_THREADS_NUM; - ms_setting.nconns = DEFAULT_CONNS_NUM; - ms_setting.run_time = DEFAULT_RUN_TIME; - ms_setting.total_srv_cnt = MCD_SRVS_NUM_INIT; - ms_setting.servers = (ms_mcd_server_t *)malloc((uint64_t)ms_setting.total_srv_cnt - * sizeof(ms_mcd_server_t)); - if (ms_setting.servers == NULL) { - fprintf(stderr, "Can't allocate servers structure.\n"); - exit(1); - } + memset(&ms_setting, 0, sizeof(ms_setting_t)); + + /* common initialize */ + ms_setting.ncpu= ms_get_cpu_count(); + ms_setting.nthreads= DEFAULT_THREADS_NUM; + ms_setting.nconns= DEFAULT_CONNS_NUM; + ms_setting.run_time= DEFAULT_RUN_TIME; + ms_setting.total_srv_cnt= MCD_SRVS_NUM_INIT; + ms_setting.servers= (ms_mcd_server_t *)malloc( + (uint64_t)ms_setting.total_srv_cnt + * sizeof(ms_mcd_server_t)); + if (ms_setting.servers == NULL) + { + fprintf(stderr, "Can't allocate servers structure.\n"); + exit(1); + } + + ms_setting_slapmode_init_pre(); +} /* ms_setting_init_pre */ - ms_setting_slapmode_init_pre(); -} /** * post part of slap mode initialization of setting structure */ static void ms_setting_slapmode_init_post() { - ms_setting.total_key_rng_cnt = KEY_RANGE_COUNT_INIT; - ms_setting.key_distr = (ms_key_distr_t *)malloc((uint64_t)ms_setting.total_key_rng_cnt - * sizeof(ms_key_distr_t)); - if (ms_setting.key_distr == NULL) { - fprintf(stderr, "Can't allocate key distribution structure.\n"); - exit(1); - } - - ms_setting.total_val_rng_cnt = VALUE_RANGE_COUNT_INIT; - ms_setting.value_distr = (ms_value_distr_t *)malloc((uint64_t)ms_setting.total_val_rng_cnt - * sizeof(ms_value_distr_t)); - if (ms_setting.value_distr == NULL) { - fprintf(stderr, "Can't allocate value distribution structure.\n"); - exit(1); - } - - ms_parse_cfg_file(ms_setting.cfg_file); - - /* run time mode */ - if (ms_setting.exec_num == 0 && ms_setting.run_time != 0) { - ms_setting.exec_num = (int64_t)MAX_EXEC_NUM; - } else { - /* execute number mode */ - ms_setting.run_time = 0; - } - - if (ms_setting.rep_write_srv > 0) { - /* for replication test, need enable reconnect feature */ - ms_setting.reconnect = true; - } - - if (ms_setting.facebook_test && ms_setting.mult_key_num < 2) { - fprintf(stderr, "facebook test must work with multi-get, " - "please specify multi-get key number " - "with '--division' option.\n"); - exit(1); - } - - if (ms_setting.facebook_test && ms_setting.udp) { - fprintf(stderr, "facebook test couldn't work with UDP.\n"); - exit(1); - } - - if (ms_setting.udp && ms_setting.sock_per_conn > 1) { - fprintf(stderr, "UDP doesn't support multi-socks " - "in one connection structure.\n"); - exit(1); - } - - if ((ms_setting.udp || ms_setting.facebook_test) && ms_setting.binary_prot) { - fprintf(stderr, "Binary protocol doesn't support UDP now.\n"); - exit(1); - } - - if (ms_setting.rep_write_srv > 0 && ms_setting.srv_cnt < 2) { - fprintf(stderr, "Please specify 2 servers at least for replication\n"); - exit(1); - } - - if (ms_setting.rep_write_srv > 0 && ms_setting.srv_cnt < ms_setting.rep_write_srv) { - fprintf(stderr, "Servers to do replication writing " - "is larger than the total servers\n"); - exit(1); - } - - if (ms_setting.udp && ms_setting.rep_write_srv > 0) { - fprintf(stderr, "UDP doesn't support replication.\n"); - exit(1); - } - - if (ms_setting.rep_write_srv > 0 && ms_setting.sock_per_conn > 1) { - fprintf(stderr, "Replication doesn't support multi-socks " - "in one connection structure.\n"); - exit(1); - } - - if (ms_setting.facebook_test && ms_setting.rep_write_srv > 0) { - fprintf(stderr, "facebook test couldn't work with replication.\n"); - exit(1); - } + ms_setting.total_key_rng_cnt= KEY_RANGE_COUNT_INIT; + ms_setting.key_distr= (ms_key_distr_t *)malloc( + (uint64_t)ms_setting.total_key_rng_cnt + * sizeof(ms_key_distr_t)); + if (ms_setting.key_distr == NULL) + { + fprintf(stderr, "Can't allocate key distribution structure.\n"); + exit(1); + } + + ms_setting.total_val_rng_cnt= VALUE_RANGE_COUNT_INIT; + ms_setting.value_distr= (ms_value_distr_t *)malloc( + (uint64_t)ms_setting.total_val_rng_cnt + * sizeof( + ms_value_distr_t)); + if (ms_setting.value_distr == NULL) + { + fprintf(stderr, "Can't allocate value distribution structure.\n"); + exit(1); + } + + ms_parse_cfg_file(ms_setting.cfg_file); + + /* run time mode */ + if ((ms_setting.exec_num == 0) && (ms_setting.run_time != 0)) + { + ms_setting.exec_num= (int64_t)MAX_EXEC_NUM; + } + else + { + /* execute number mode */ + ms_setting.run_time= 0; + } + + if (ms_setting.rep_write_srv > 0) + { + /* for replication test, need enable reconnect feature */ + ms_setting.reconnect= true; + } + + if (ms_setting.facebook_test && (ms_setting.mult_key_num < 2)) + { + fprintf(stderr, "facebook test must work with multi-get, " + "please specify multi-get key number " + "with '--division' option.\n"); + exit(1); + } + + if (ms_setting.facebook_test && ms_setting.udp) + { + fprintf(stderr, "facebook test couldn't work with UDP.\n"); + exit(1); + } + + if (ms_setting.udp && (ms_setting.sock_per_conn > 1)) + { + fprintf(stderr, "UDP doesn't support multi-socks " + "in one connection structure.\n"); + exit(1); + } + + if ((ms_setting.udp + || ms_setting.facebook_test) && ms_setting.binary_prot) + { + fprintf(stderr, "Binary protocol doesn't support UDP now.\n"); + exit(1); + } + + if ((ms_setting.rep_write_srv > 0) && (ms_setting.srv_cnt < 2)) + { + fprintf(stderr, "Please specify 2 servers at least for replication\n"); + exit(1); + } + + if ((ms_setting.rep_write_srv > 0) + && (ms_setting.srv_cnt < ms_setting.rep_write_srv)) + { + fprintf(stderr, "Servers to do replication writing " + "is larger than the total servers\n"); + exit(1); + } + + if (ms_setting.udp && (ms_setting.rep_write_srv > 0)) + { + fprintf(stderr, "UDP doesn't support replication.\n"); + exit(1); + } + + if ((ms_setting.rep_write_srv > 0) && (ms_setting.sock_per_conn > 1)) + { + fprintf(stderr, "Replication doesn't support multi-socks " + "in one connection structure.\n"); + exit(1); + } + + if (ms_setting.facebook_test && (ms_setting.rep_write_srv > 0)) + { + fprintf(stderr, "facebook test couldn't work with replication.\n"); + exit(1); + } + + if (ms_setting.reconnect && (ms_setting.sock_per_conn > 1)) + { + fprintf(stderr, "Reconnection doesn't support multi-socks " + "in one connection structure.\n"); + exit(1); + } + + ms_build_distr(); + + /* initialize global character block */ + ms_init_random_block(); + ms_print_setting(); +} /* ms_setting_slapmode_init_post */ - if (ms_setting.reconnect && ms_setting.sock_per_conn > 1) { - fprintf(stderr, "Reconnection doesn't support multi-socks " - "in one connection structure.\n"); - exit(1); - } - - ms_build_distr(); - - /* initialize global character block */ - ms_init_random_block(); - ms_print_setting(); -} /** * post part of initialization of setting structure */ void ms_setting_init_post() { - ms_get_serverlist(ms_setting.srv_str); - ms_setting_slapmode_init_post(); + ms_get_serverlist(ms_setting.srv_str); + ms_setting_slapmode_init_post(); } + /** * clean up the global setting structure */ void ms_setting_cleanup() { - if (ms_setting.distr != NULL) { - free(ms_setting.distr); - } - - if (ms_setting.char_block != NULL) { - free(ms_setting.char_block); - } - - if (ms_setting.srv_str != NULL) { - free(ms_setting.srv_str); - } - - if (ms_setting.cfg_file != NULL) { - free(ms_setting.cfg_file); - } - - if (ms_setting.servers != NULL) { - free(ms_setting.servers); - } - - if (ms_setting.key_distr != NULL) { - free(ms_setting.key_distr); - } - - if (ms_setting.value_distr != NULL) { - free(ms_setting.value_distr); - } -} + if (ms_setting.distr != NULL) + { + free(ms_setting.distr); + } + + if (ms_setting.char_block != NULL) + { + free(ms_setting.char_block); + } + + if (ms_setting.srv_str != NULL) + { + free(ms_setting.srv_str); + } + + if (ms_setting.cfg_file != NULL) + { + free(ms_setting.cfg_file); + } + + if (ms_setting.servers != NULL) + { + free(ms_setting.servers); + } + + if (ms_setting.key_distr != NULL) + { + free(ms_setting.key_distr); + } + + if (ms_setting.value_distr != NULL) + { + free(ms_setting.value_distr); + } +} /* ms_setting_cleanup */ diff --git a/clients/ms_setting.h b/clients/ms_setting.h index 83ef68b2..d08998c6 100644 --- a/clients/ms_setting.h +++ b/clients/ms_setting.h @@ -17,135 +17,145 @@ extern "C" { #endif -#define MCD_SRVS_NUM_INIT 8 -#define MCD_HOST_LENGTH 64 -#define KEY_RANGE_COUNT_INIT 8 -#define VALUE_RANGE_COUNT_INIT 8 -#define PROP_ERROR 0.001 +#define MCD_SRVS_NUM_INIT 8 +#define MCD_HOST_LENGTH 64 +#define KEY_RANGE_COUNT_INIT 8 +#define VALUE_RANGE_COUNT_INIT 8 +#define PROP_ERROR 0.001 -#define MIN_KEY_SIZE 16 -#define MAX_KEY_SIZE 250 -#define MAX_VALUE_SIZE (1024 * 1024) +#define MIN_KEY_SIZE 16 +#define MAX_KEY_SIZE 250 +#define MAX_VALUE_SIZE (1024 * 1024) /* the content of the configuration file for memslap running without configuration file */ -#define DEFAULT_CONGIF_STR "key\n" \ - "64 64 1\n" \ - "value\n" \ - "1024 1024 1\n" \ - "cmd\n" \ - "0 0.1\n" \ - "1 0.9" +#define DEFAULT_CONGIF_STR \ + "key\n" \ + "64 64 1\n" \ + "value\n" \ + "1024 1024 1\n" \ + "cmd\n" \ + "0 0.1\n" \ + "1 0.9" /* Used to parse the value length return by server and path string */ -typedef struct token_s { - char *value; - size_t length; +typedef struct token_s +{ + char *value; + size_t length; } token_t; -#define MAX_TOKENS 10 +#define MAX_TOKENS 10 /* server information */ -typedef struct mcd_sever{ - char srv_host_name[MCD_HOST_LENGTH]; /* host name of server */ - int srv_port; /* server port */ - - /* for calculating how long the server disconnects */ - int disconn_cnt; /* number of disconnections count */ - int reconn_cnt; /* number of reconnections count */ - struct timeval disconn_time; /* start time of disconnection */ - struct timeval reconn_time; /* end time of reconnection */ -}ms_mcd_server_t; +typedef struct mcd_sever +{ + char srv_host_name[MCD_HOST_LENGTH]; /* host name of server */ + int srv_port; /* server port */ + + /* for calculating how long the server disconnects */ + int disconn_cnt; /* number of disconnections count */ + int reconn_cnt; /* number of reconnections count */ + struct timeval disconn_time; /* start time of disconnection */ + struct timeval reconn_time; /* end time of reconnection */ +} ms_mcd_server_t; /* information of an item distribution including key and value */ -typedef struct distr { - size_t key_size; /* size of key */ - int key_offset; /* offset of one key in character block */ - size_t value_size; /* size of value */ +typedef struct distr +{ + size_t key_size; /* size of key */ + int key_offset; /* offset of one key in character block */ + size_t value_size; /* size of value */ } ms_distr_t; /* information of key distribution */ -typedef struct key_distr{ - size_t start_len; /* start of the key length range */ - size_t end_len; /* end of the key length range */ - double key_prop; /* key proportion */ -}ms_key_distr_t; +typedef struct key_distr +{ + size_t start_len; /* start of the key length range */ + size_t end_len; /* end of the key length range */ + double key_prop; /* key proportion */ +} ms_key_distr_t; /* information of value distribution */ -typedef struct value_distr{ - size_t start_len; /* start of the value length range */ - size_t end_len; /* end of the value length range */ - double value_prop; /* value proportion */ -}ms_value_distr_t; +typedef struct value_distr +{ + size_t start_len; /* start of the value length range */ + size_t end_len; /* end of the value length range */ + double value_prop; /* value proportion */ +} ms_value_distr_t; /* memcached command types */ -typedef enum cmd_type{ - CMD_SET, - CMD_GET, - CMD_NULL, +typedef enum cmd_type +{ + CMD_SET, + CMD_GET, + CMD_NULL, } ms_cmd_type_t; /* types in the configuration file */ -typedef enum conf_type{ - CONF_KEY, - CONF_VALUE, - CONF_CMD, - CONF_NULL, -}ms_conf_type_t; +typedef enum conf_type +{ + CONF_KEY, + CONF_VALUE, + CONF_CMD, + CONF_NULL, +} ms_conf_type_t; /* information of command distribution */ -typedef struct cmd_distr{ - ms_cmd_type_t cmd_type; /* command type */ - double cmd_prop; /* proportion of the command */ -}ms_cmd_distr_t; +typedef struct cmd_distr +{ + ms_cmd_type_t cmd_type; /* command type */ + double cmd_prop; /* proportion of the command */ +} ms_cmd_distr_t; /* global setting structure */ -typedef struct setting { - int ncpu; /* cpu count of this system */ - int nthreads; /* total thread count, must equal or less than cpu cores */ - int nconns; /* total conn count, must multiply by total thread count */ - int64_t exec_num; /* total execute number */ - int run_time; /* total run time */ - - uint32_t char_blk_size; /* global character block size */ - char *char_block; /* global character block with random character */ - ms_distr_t *distr; /* distribution from configure file */ - - char *srv_str; /* string includes servers information */ - char *cfg_file; /* configure file name */ - - ms_mcd_server_t *servers; /* servers array */ - int total_srv_cnt; /* total servers count of the servers array */ - int srv_cnt; /* servers count */ - - ms_key_distr_t *key_distr; /* array of key distribution */ - int total_key_rng_cnt; /* total key range count of the array */ - int key_rng_cnt; /* actual key range count */ - - ms_value_distr_t *value_distr; /* array of value distribution */ - int total_val_rng_cnt; /* total value range count of the array */ - int val_rng_cnt; /* actual value range count */ - - ms_cmd_distr_t cmd_distr[CMD_NULL];/* total we have CMD_NULL commands */ - int cmd_used_count; /* supported command count */ - - size_t fixed_value_size; /* fixed value size */ - size_t avg_val_size; /* average value size */ - size_t avg_key_size; /* average value size */ - - double verify_percent; /* percent of data verification */ - double exp_ver_per; /* percent of data verification with expire time */ - double overwrite_percent; /* percent of overwrite */ - int mult_key_num; /* number of keys used by multi-get once */ - size_t win_size; /* item window size per connection */ - bool udp; /* whether or not use UDP */ - int stat_freq; /* statistic frequency second */ - bool reconnect; /* whether it reconnect when connection close */ - bool verbose; /* whether it outputs detailed information when verification */ - bool facebook_test; /* facebook test, TCP set and multi-get with UDP */ - int sock_per_conn; /* number of socks per connection structure */ - bool binary_prot; /* whether it use binary protocol */ - int expected_tps; /* expected throughput */ - int rep_write_srv; /* which servers are used to do replication writing */ +typedef struct setting +{ + int ncpu; /* cpu count of this system */ + int nthreads; /* total thread count, must equal or less than cpu cores */ + int nconns; /* total conn count, must multiply by total thread count */ + int64_t exec_num; /* total execute number */ + int run_time; /* total run time */ + + uint32_t char_blk_size; /* global character block size */ + char *char_block; /* global character block with random character */ + ms_distr_t *distr; /* distribution from configure file */ + + char *srv_str; /* string includes servers information */ + char *cfg_file; /* configure file name */ + + ms_mcd_server_t *servers; /* servers array */ + int total_srv_cnt; /* total servers count of the servers array */ + int srv_cnt; /* servers count */ + + ms_key_distr_t *key_distr; /* array of key distribution */ + int total_key_rng_cnt; /* total key range count of the array */ + int key_rng_cnt; /* actual key range count */ + + ms_value_distr_t *value_distr; /* array of value distribution */ + int total_val_rng_cnt; /* total value range count of the array */ + int val_rng_cnt; /* actual value range count */ + + ms_cmd_distr_t cmd_distr[CMD_NULL]; /* total we have CMD_NULL commands */ + int cmd_used_count; /* supported command count */ + + size_t fixed_value_size; /* fixed value size */ + size_t avg_val_size; /* average value size */ + size_t avg_key_size; /* average value size */ + + double verify_percent; /* percent of data verification */ + double exp_ver_per; /* percent of data verification with expire time */ + double overwrite_percent; /* percent of overwrite */ + int mult_key_num; /* number of keys used by multi-get once */ + size_t win_size; /* item window size per connection */ + bool udp; /* whether or not use UDP */ + int stat_freq; /* statistic frequency second */ + bool reconnect; /* whether it reconnect when connection close */ + bool verbose; /* whether it outputs detailed information when verification */ + bool facebook_test; /* facebook test, TCP set and multi-get with UDP */ + int sock_per_conn; /* number of socks per connection structure */ + bool binary_prot; /* whether it use binary protocol */ + int expected_tps; /* expected throughput */ + int rep_write_srv; /* which servers are used to do replication writing */ } ms_setting_t; extern ms_setting_t ms_setting; @@ -153,13 +163,16 @@ extern ms_setting_t ms_setting; /* previous part of initialization of setting structure */ void ms_setting_init_pre(void); + /* post part of initialization of setting structure */ void ms_setting_init_post(void); + /* clean up the global setting structure */ void ms_setting_cleanup(void); -#define UNUSED_ARGUMENT(x) (void)x + +#define UNUSED_ARGUMENT(x) (void)x #ifdef __cplusplus } diff --git a/clients/ms_sigsegv.c b/clients/ms_sigsegv.c index a37914eb..69f038f9 100644 --- a/clients/ms_sigsegv.c +++ b/clients/ms_sigsegv.c @@ -22,20 +22,20 @@ #define NO_CPP_DEMANGLE #ifndef NO_CPP_DEMANGLE -#include +# include #endif #undef REG_RIP #if defined(REG_RIP) - #define SIGSEGV_STACK_IA64 - #define REGFORMAT "%016lx" +# define SIGSEGV_STACK_IA64 +# define REGFORMAT "%016lx" #elif defined(REG_EIP) - #define SIGSEGV_STACK_X86 - #define REGFORMAT "%08x" +# define SIGSEGV_STACK_X86 +# define REGFORMAT "%08x" #else - #define SIGSEGV_STACK_GENERIC - #define REGFORMAT "%x" +# define SIGSEGV_STACK_GENERIC +# define REGFORMAT "%x" #endif /* prototypes */ @@ -43,127 +43,140 @@ int ms_setup_sigsegv(void); int ms_setup_sigpipe(void); int ms_setup_sigint(void); + /* signal seg reaches, this function will run */ -static void ms_signal_segv(int signum, siginfo_t * info, void * ptr) { - int i; +static void ms_signal_segv(int signum, siginfo_t *info, void *ptr) +{ + int i; - UNUSED_ARGUMENT(signum); - UNUSED_ARGUMENT(info); - UNUSED_ARGUMENT(ptr); + UNUSED_ARGUMENT(signum); + UNUSED_ARGUMENT(info); + UNUSED_ARGUMENT(ptr); - pthread_mutex_lock(&ms_global.quit_mutex); - fprintf(stderr, "Segmentation fault occurred.\n"); + pthread_mutex_lock(&ms_global.quit_mutex); + fprintf(stderr, "Segmentation fault occurred.\n"); #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) - int f = 0; - Dl_info dlinfo; - void **bp = 0; - void *ip = 0; + int f= 0; + Dl_info dlinfo; + void **bp= 0; + void *ip= 0; #else - void *bt[20]; - char **strings; - int sz; + void *bt[20]; + char **strings; + int sz; #endif #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) -#if defined(SIGSEGV_STACK_IA64) - ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP]; - bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP]; -#elif defined(SIGSEGV_STACK_X86) - ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; - bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; -#endif - - fprintf(stderr, "Stack trace:\n"); - while(bp && ip) { - if(!dladdr(ip, &dlinfo)) - break; - - const char *symname = dlinfo.dli_sname; -#ifndef NO_CPP_DEMANGLE - int status; - char *tmp = __cxa_demangle(symname, NULL, 0, &status); - - if(status == 0 && tmp) - symname = tmp; -#endif - - fprintf(stderr, "% 2d: %p <%s+%u> (%s)\n", - ++f, - ip, - symname, - (unsigned)(ip - dlinfo.dli_saddr), - dlinfo.dli_fname); - -#ifndef NO_CPP_DEMANGLE - if(tmp) - free(tmp); -#endif - - if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main")) - break; - - ip = bp[1]; - bp = (void**)bp[0]; - } +# if defined(SIGSEGV_STACK_IA64) + ip= (void *)ucontext->uc_mcontext.gregs[REG_RIP]; + bp= (void **)ucontext->uc_mcontext.gregs[REG_RBP]; +# elif defined(SIGSEGV_STACK_X86) + ip= (void *)ucontext->uc_mcontext.gregs[REG_EIP]; + bp= (void **)ucontext->uc_mcontext.gregs[REG_EBP]; +# endif + + fprintf(stderr, "Stack trace:\n"); + while (bp && ip) + { + if (! dladdr(ip, &dlinfo)) + break; + + const char *symname= dlinfo.dli_sname; +# ifndef NO_CPP_DEMANGLE + int status; + char *tmp= __cxa_demangle(symname, NULL, 0, &status); + + if ((status == 0) && tmp) + symname= tmp; +# endif + + fprintf(stderr, "% 2d: %p <%s+%u> (%s)\n", + ++f, + ip, + symname, + (unsigned)(ip - dlinfo.dli_saddr), + dlinfo.dli_fname); + +# ifndef NO_CPP_DEMANGLE + if (tmp) + free(tmp); +# endif + + if (dlinfo.dli_sname && ! strcmp(dlinfo.dli_sname, "main")) + break; + + ip= bp[1]; + bp= (void **)bp[0]; + } #else - fprintf(stderr, "Stack trace:\n"); - sz = backtrace(bt, 20); - strings = backtrace_symbols(bt, sz); - - for(i = 0; i < sz; ++i) - fprintf(stderr, "%s\n", strings[i]); + fprintf(stderr, "Stack trace:\n"); + sz= backtrace(bt, 20); + strings= backtrace_symbols(bt, sz); + + for (i= 0; i < sz; ++i) + { + fprintf(stderr, "%s\n", strings[i]); + } #endif - fprintf(stderr, "End of stack trace\n"); - pthread_mutex_unlock(&ms_global.quit_mutex); - exit (1); -} + fprintf(stderr, "End of stack trace\n"); + pthread_mutex_unlock(&ms_global.quit_mutex); + exit(1); +} /* ms_signal_segv */ + /* signal pipe reaches, this function will run */ -static void ms_signal_pipe(int signum, siginfo_t* info, void*ptr) +static void ms_signal_pipe(int signum, siginfo_t *info, void *ptr) { - UNUSED_ARGUMENT(signum); - UNUSED_ARGUMENT(info); - UNUSED_ARGUMENT(ptr); - - pthread_mutex_lock(&ms_global.quit_mutex); - fprintf(stderr, "\tMemslap encountered a server error. Quitting...\n"); - fprintf(stderr, "\tError info: SIGPIPE captured (from write?)\n"); - fprintf(stderr, "\tProbably a socket I/O error when the server is down.\n"); - pthread_mutex_unlock(&ms_global.quit_mutex); - exit(1); -} + UNUSED_ARGUMENT(signum); + UNUSED_ARGUMENT(info); + UNUSED_ARGUMENT(ptr); + + pthread_mutex_lock(&ms_global.quit_mutex); + fprintf(stderr, "\tMemslap encountered a server error. Quitting...\n"); + fprintf(stderr, "\tError info: SIGPIPE captured (from write?)\n"); + fprintf(stderr, + "\tProbably a socket I/O error when the server is down.\n"); + pthread_mutex_unlock(&ms_global.quit_mutex); + exit(1); +} /* ms_signal_pipe */ + /* signal int reaches, this function will run */ -static void ms_signal_int(int signum, siginfo_t* info, void*ptr) +static void ms_signal_int(int signum, siginfo_t *info, void *ptr) { - UNUSED_ARGUMENT(signum); - UNUSED_ARGUMENT(info); - UNUSED_ARGUMENT(ptr); - - pthread_mutex_lock(&ms_global.quit_mutex); - fprintf(stderr, "SIGINT handled.\n"); - pthread_mutex_unlock(&ms_global.quit_mutex); - exit(1); -} + UNUSED_ARGUMENT(signum); + UNUSED_ARGUMENT(info); + UNUSED_ARGUMENT(ptr); + + pthread_mutex_lock(&ms_global.quit_mutex); + fprintf(stderr, "SIGINT handled.\n"); + pthread_mutex_unlock(&ms_global.quit_mutex); + exit(1); +} /* ms_signal_int */ + /** * redirect signal seg * * @return if success, return 0, else return -1 */ -int ms_setup_sigsegv(void) { - struct sigaction action; - memset(&action, 0, sizeof(action)); - action.sa_sigaction = ms_signal_segv; - action.sa_flags = SA_SIGINFO; - if(sigaction(SIGSEGV, &action, NULL) < 0) { - perror("sigaction"); - return 0; - } - - return -1; -} +int ms_setup_sigsegv(void) +{ + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_sigaction= ms_signal_segv; + action.sa_flags= SA_SIGINFO; + if (sigaction(SIGSEGV, &action, NULL) < 0) + { + perror("sigaction"); + return 0; + } + + return -1; +} /* ms_setup_sigsegv */ + /** * redirect signal pipe @@ -172,17 +185,20 @@ int ms_setup_sigsegv(void) { */ int ms_setup_sigpipe(void) { - struct sigaction action_2; - memset(&action_2, 0, sizeof(action_2)); - action_2.sa_sigaction = ms_signal_pipe; - action_2.sa_flags = SA_SIGINFO; - if(sigaction(SIGPIPE, &action_2, NULL) < 0) { - perror("sigaction"); - return 0; - } - - return -1; -} + struct sigaction action_2; + + memset(&action_2, 0, sizeof(action_2)); + action_2.sa_sigaction= ms_signal_pipe; + action_2.sa_flags= SA_SIGINFO; + if (sigaction(SIGPIPE, &action_2, NULL) < 0) + { + perror("sigaction"); + return 0; + } + + return -1; +} /* ms_setup_sigpipe */ + /** * redirect signal int @@ -191,22 +207,26 @@ int ms_setup_sigpipe(void) */ int ms_setup_sigint(void) { - struct sigaction action_3; - memset(&action_3, 0, sizeof(action_3)); - action_3.sa_sigaction = ms_signal_int; - action_3.sa_flags = SA_SIGINFO; - if(sigaction(SIGINT, &action_3, NULL) < 0) { - perror("sigaction"); - return 0; - } - - return -1; -} + struct sigaction action_3; + + memset(&action_3, 0, sizeof(action_3)); + action_3.sa_sigaction= ms_signal_int; + action_3.sa_flags= SA_SIGINFO; + if (sigaction(SIGINT, &action_3, NULL) < 0) + { + perror("sigaction"); + return 0; + } + + return -1; +} /* ms_setup_sigint */ + #ifndef SIGSEGV_NO_AUTO_INIT -static void __attribute((constructor)) ms_init(void) { - ms_setup_sigsegv(); - ms_setup_sigpipe(); - ms_setup_sigint(); +static void __attribute((constructor)) ms_init(void) +{ + ms_setup_sigsegv(); + ms_setup_sigpipe(); + ms_setup_sigint(); } #endif diff --git a/clients/ms_sigsegv.h b/clients/ms_sigsegv.h index f933b5bb..7990ff67 100644 --- a/clients/ms_sigsegv.h +++ b/clients/ms_sigsegv.h @@ -18,12 +18,15 @@ extern "C" { /* redirect signal seg */ int ms_setup_sigsegv(void); + /* redirect signal pipe */ int ms_setup_sigpipe(void); + /* redirect signal int */ int ms_setup_sigint(void); + #ifdef __cplusplus } #endif diff --git a/clients/ms_stats.c b/clients/ms_stats.c index af6183cd..960467fd 100644 --- a/clients/ms_stats.c +++ b/clients/ms_stats.c @@ -10,7 +10,7 @@ */ #include "ms_stats.h" -#define array_size(x) (sizeof(x) / sizeof((x)[0])) +#define array_size(x) (sizeof(x) / sizeof((x)[0])) static int ms_local_log2(uint64_t value); static uint64_t ms_get_events(ms_stat_t *stat); @@ -25,14 +25,16 @@ static uint64_t ms_get_events(ms_stat_t *stat); */ static int ms_local_log2(uint64_t value) { - int result = 0; + int result= 0; - while (result <= 63 && ((uint64_t) 1 << result) < value) { - result++; - } + while (result <= 63 && ((uint64_t)1 << result) < value) + { + result++; + } + + return result; +} /* ms_local_log2 */ - return result; -} /** * initialize statistic structure @@ -42,25 +44,24 @@ static int ms_local_log2(uint64_t value) */ void ms_init_stats(ms_stat_t *stat, const char *name) { - memset(stat, 0, sizeof(*stat)); - - stat->name = (char *)name; - stat->min_time = (uint64_t) -1; - stat->max_time = 0; - stat->period_min_time = (uint64_t) -1; - stat->period_max_time = 0; - stat->log_product = 0; - stat->total_time = 0; - stat->pre_total_time = 0; - stat->squares = 0; - stat->pre_squares = 0; - stat->pre_events = 0; - stat->pre_log_product = 0; - stat->get_miss = 0; - stat->pre_get_miss = 0; + memset(stat, 0, sizeof(*stat)); + + stat->name= (char *)name; + stat->min_time= (uint64_t)-1; + stat->max_time= 0; + stat->period_min_time= (uint64_t)-1; + stat->period_max_time= 0; + stat->log_product= 0; + stat->total_time= 0; + stat->pre_total_time= 0; + stat->squares= 0; + stat->pre_squares= 0; + stat->pre_events= 0; + stat->pre_log_product= 0; + stat->get_miss= 0; + stat->pre_get_miss= 0; +} /* ms_init_stats */ - return; -} /** * record one event @@ -71,37 +72,42 @@ void ms_init_stats(ms_stat_t *stat, const char *name) */ void ms_record_event(ms_stat_t *stat, uint64_t total_time, int get_miss) { - stat->total_time += total_time; + stat->total_time+= total_time; - if (total_time < stat->min_time) { - stat->min_time = total_time; - } + if (total_time < stat->min_time) + { + stat->min_time= total_time; + } - if (total_time > stat->max_time) { - stat->max_time = total_time; - } + if (total_time > stat->max_time) + { + stat->max_time= total_time; + } - if (total_time < stat->period_min_time) { - stat->period_min_time = total_time; - } + if (total_time < stat->period_min_time) + { + stat->period_min_time= total_time; + } - if (total_time > stat->period_max_time) { - stat->period_max_time = total_time; - } + if (total_time > stat->period_max_time) + { + stat->period_max_time= total_time; + } - if (get_miss) { - stat->get_miss++; - } + if (get_miss) + { + stat->get_miss++; + } - stat->dist[ms_local_log2(total_time)]++; - stat->squares += (double)(total_time * total_time); + stat->dist[ms_local_log2(total_time)]++; + stat->squares+= (double)(total_time * total_time); - if (total_time != 0) { - stat->log_product += log((double) total_time); - } + if (total_time != 0) + { + stat->log_product+= log((double)total_time); + } +} /* ms_record_event */ - return; -} /** * get the events count @@ -112,14 +118,16 @@ void ms_record_event(ms_stat_t *stat, uint64_t total_time, int get_miss) */ static uint64_t ms_get_events(ms_stat_t *stat) { - uint64_t events = 0; + uint64_t events= 0; - for (uint32_t i = 0; i < array_size(stat->dist); i++) { - events += stat->dist[i]; - } + for (uint32_t i= 0; i < array_size(stat->dist); i++) + { + events+= stat->dist[i]; + } + + return events; +} /* ms_get_events */ - return events; -} /** * dump the statistics @@ -128,55 +136,64 @@ static uint64_t ms_get_events(ms_stat_t *stat) */ void ms_dump_stats(ms_stat_t *stat) { - uint64_t events = 0; - int max_non_zero = 0; - int min_non_zero = 0; - double average = 0; - - for (uint32_t i = 0; i < array_size(stat->dist); i++) { - events += stat->dist[i]; - if (stat->dist[i] != 0) { - max_non_zero = (int)i; - } + uint64_t events= 0; + int max_non_zero= 0; + int min_non_zero= 0; + double average= 0; + + for (uint32_t i= 0; i < array_size(stat->dist); i++) + { + events+= stat->dist[i]; + if (stat->dist[i] != 0) + { + max_non_zero= (int)i; } + } - if (events == 0) { - return; + if (events == 0) + { + return; + } + average= (double)(stat->total_time / events); + + printf("%s Statistics (%lld events)\n", stat->name, (long long)events); + printf(" Min: %8lld\n", (long long)stat->min_time); + printf(" Max: %8lld\n", (long long)stat->max_time); + printf(" Avg: %8lld\n", (long long)(stat->total_time / events)); + printf(" Geo: %8.2lf\n", exp(stat->log_product / (double)events)); + + if (events > 1) + { + printf(" Std: %8.2lf\n", + sqrt((stat->squares - (double)events * average + * average) / ((double)events - 1))); + } + printf(" Log2 Dist:"); + + for (int i= 0; i <= max_non_zero - 4; i+= 4) + { + if ((stat->dist[i + 0] != 0) + || (stat->dist[i + 1] != 0) + || (stat->dist[i + 2] != 0) + || (stat->dist[i + 3] != 0)) + { + min_non_zero= i; + break; } - average = (double)(stat->total_time / events); - - printf("%s Statistics (%lld events)\n", stat->name, (long long)events); - printf(" Min: %8lld\n", (long long)stat->min_time); - printf(" Max: %8lld\n", (long long)stat->max_time); - printf(" Avg: %8lld\n", (long long)(stat->total_time / events)); - printf(" Geo: %8.2lf\n", exp(stat->log_product / (double)events)); + } - if (events > 1) { - printf(" Std: %8.2lf\n", - sqrt((stat->squares - (double)events * average * average) / ((double)events - 1))); - } - printf(" Log2 Dist:"); - - for (int i = 0; i <= max_non_zero - 4; i += 4) { - if (stat->dist[i + 0] != 0 - || stat->dist[i + 1] != 0 - || stat->dist[i + 2] != 0 - || stat->dist[i + 3] != 0) { - min_non_zero = i; - break; - } + for (int i= min_non_zero; i <= max_non_zero; i++) + { + if ((i % 4) == 0) + { + printf("\n %2d:", (int)i); } + printf(" %6ld", stat->dist[i]); + } - for (int i = min_non_zero; i <= max_non_zero; i++) { - if ((i % 4) == 0) { - printf("\n %2d:", (int) i); - } - printf(" %6ld", stat->dist[i]); - } + printf("\n\n"); +} /* ms_dump_stats */ - printf("\n\n"); - return; -} /** * dump the format statistics @@ -186,74 +203,101 @@ void ms_dump_stats(ms_stat_t *stat) * @param freq, statistic frequency * @param obj_size, average object size */ -void ms_dump_format_stats(ms_stat_t *stat, int run_time, - int freq, int obj_size) +void ms_dump_format_stats(ms_stat_t *stat, + int run_time, + int freq, + int obj_size) { - uint64_t events = 0; - double global_average = 0; - uint64_t global_tps = 0; - double global_rate = 0; - double global_std = 0; - double global_log = 0; - - uint64_t diff_time = 0; - uint64_t diff_events = 0; - double diff_squares = 0; - double diff_log_product = 0; - double period_average = 0; - uint64_t period_tps = 0; - double period_rate = 0; - double period_std = 0; - double period_log = 0; - - if ((events = ms_get_events(stat)) == 0) { - return; - } - - global_average = (double)(stat->total_time / events); - global_tps = events / (uint64_t)run_time; - global_rate = (double)events * obj_size / 1024 / 1024 / run_time; - global_std = sqrt((stat->squares - (double)events * global_average - * global_average) / (double)(events - 1)); - global_log = exp(stat->log_product / (double)events); - - diff_time = stat->total_time - stat->pre_total_time; - diff_events = events - stat->pre_events; - if (diff_events >= 1) { - period_average = (double)(diff_time / diff_events); - period_tps = diff_events / (uint64_t)freq; - period_rate = (double)diff_events * obj_size / 1024 / 1024 / freq; - diff_squares = (double)stat->squares - (double)stat->pre_squares; - period_std = sqrt((diff_squares - (double)diff_events * period_average - * period_average) / (double)(diff_events - 1)); - diff_log_product = stat->log_product - stat->pre_log_product; - period_log = exp(diff_log_product / (double)diff_events); - } - - printf("%s Statistics\n", stat->name); - printf("%-8s %-8s %-12s %-12s %-10s %-10s %-8s %-10s %-10s %-10s %-10s\n", "Type", - "Time(s)", "Ops", "TPS(ops/s)", "Net(M/s)", "Get_miss", "Min(us)", "Max(us)", - "Avg(us)", "Std_dev", "Geo_dist"); - - printf("%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n", - "Period", freq, (long long)diff_events, (long long)period_tps, global_rate, - (long long)(stat->get_miss - stat->pre_get_miss), - (long long)stat->period_min_time, (long long)stat->period_max_time, - (long long)period_average, period_std, period_log); - - printf("%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n\n", - "Global", run_time, (long long)events, (long long)global_tps, period_rate, - (long long)stat->get_miss, (long long)stat->min_time, - (long long)stat->max_time, (long long)global_average, - global_std, global_log); - - stat->pre_events = events; - stat->pre_squares = (uint64_t)stat->squares; - stat->pre_total_time = stat->total_time; - stat->pre_log_product = stat->log_product; - stat->period_min_time = (uint64_t)-1; - stat->period_max_time = 0; - stat->pre_get_miss = stat->get_miss; - + uint64_t events= 0; + double global_average= 0; + uint64_t global_tps= 0; + double global_rate= 0; + double global_std= 0; + double global_log= 0; + + uint64_t diff_time= 0; + uint64_t diff_events= 0; + double diff_squares= 0; + double diff_log_product= 0; + double period_average= 0; + uint64_t period_tps= 0; + double period_rate= 0; + double period_std= 0; + double period_log= 0; + + if ((events= ms_get_events(stat)) == 0) + { return; -} + } + + global_average= (double)(stat->total_time / events); + global_tps= events / (uint64_t)run_time; + global_rate= (double)events * obj_size / 1024 / 1024 / run_time; + global_std= sqrt((stat->squares - (double)events * global_average + * global_average) / (double)(events - 1)); + global_log= exp(stat->log_product / (double)events); + + diff_time= stat->total_time - stat->pre_total_time; + diff_events= events - stat->pre_events; + if (diff_events >= 1) + { + period_average= (double)(diff_time / diff_events); + period_tps= diff_events / (uint64_t)freq; + period_rate= (double)diff_events * obj_size / 1024 / 1024 / freq; + diff_squares= (double)stat->squares - (double)stat->pre_squares; + period_std= sqrt((diff_squares - (double)diff_events * period_average + * period_average) / (double)(diff_events - 1)); + diff_log_product= stat->log_product - stat->pre_log_product; + period_log= exp(diff_log_product / (double)diff_events); + } + + printf("%s Statistics\n", stat->name); + printf("%-8s %-8s %-12s %-12s %-10s %-10s %-8s %-10s %-10s %-10s %-10s\n", + "Type", + "Time(s)", + "Ops", + "TPS(ops/s)", + "Net(M/s)", + "Get_miss", + "Min(us)", + "Max(us)", + "Avg(us)", + "Std_dev", + "Geo_dist"); + + printf( + "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n", + "Period", + freq, + (long long)diff_events, + (long long)period_tps, + global_rate, + (long long)(stat->get_miss - stat->pre_get_miss), + (long long)stat->period_min_time, + (long long)stat->period_max_time, + (long long)period_average, + period_std, + period_log); + + printf( + "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n\n", + "Global", + run_time, + (long long)events, + (long long)global_tps, + period_rate, + (long long)stat->get_miss, + (long long)stat->min_time, + (long long)stat->max_time, + (long long)global_average, + global_std, + global_log); + + stat->pre_events= events; + stat->pre_squares= (uint64_t)stat->squares; + stat->pre_total_time= stat->total_time; + stat->pre_log_product= stat->log_product; + stat->period_min_time= (uint64_t)-1; + stat->period_max_time= 0; + stat->pre_get_miss= stat->get_miss; +} /* ms_dump_format_stats */ diff --git a/clients/ms_stats.h b/clients/ms_stats.h index 9b67cf79..5ac88b3f 100644 --- a/clients/ms_stats.h +++ b/clients/ms_stats.h @@ -23,37 +23,44 @@ extern "C" { #endif /* statistic structure of response time */ -typedef struct { - char * name; - uint64_t total_time; - uint64_t min_time; - uint64_t max_time; - uint64_t get_miss; - uint64_t dist[65]; - double squares; - double log_product; - - uint64_t period_min_time; - uint64_t period_max_time; - uint64_t pre_get_miss; - uint64_t pre_events; - uint64_t pre_total_time; - uint64_t pre_squares; - double pre_log_product; +typedef struct +{ + char *name; + uint64_t total_time; + uint64_t min_time; + uint64_t max_time; + uint64_t get_miss; + uint64_t dist[65]; + double squares; + double log_product; + + uint64_t period_min_time; + uint64_t period_max_time; + uint64_t pre_get_miss; + uint64_t pre_events; + uint64_t pre_total_time; + uint64_t pre_squares; + double pre_log_product; } ms_stat_t; /* initialize statistic */ void ms_init_stats(ms_stat_t *stat, const char *name); + /* record one event */ void ms_record_event(ms_stat_t *stat, uint64_t time, int get_miss); + /* dump the statistics */ void ms_dump_stats(ms_stat_t *stat); + /* dump the format statistics */ -void ms_dump_format_stats(ms_stat_t *stat, int run_time, - int freq, int obj_size); +void ms_dump_format_stats(ms_stat_t *stat, + int run_time, + int freq, + int obj_size); + #ifdef __cplusplus } diff --git a/clients/ms_task.c b/clients/ms_task.c index 8e2c7351..21dabe01 100644 --- a/clients/ms_task.c +++ b/clients/ms_task.c @@ -12,8 +12,8 @@ #include "ms_setting.h" /* command distribution adjustment cycle */ -#define CMD_DISTR_ADJUST_CYCLE 1000 -#define DISADJUST_FACTOR 0.03 /** +#define CMD_DISTR_ADJUST_CYCLE 1000 +#define DISADJUST_FACTOR 0.03 /** * In one adjustment cycle, if undo set or get * operations proportion is more than 3% , means * there are too many new item or need more new @@ -28,25 +28,31 @@ static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c); static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c); static ms_task_item_t *ms_get_pre_set_item(ms_conn_t *c); + /* select next operation to do */ static void ms_select_opt(ms_conn_t *c, ms_task_t *task); + /* set and get speed estimate for controlling and adjustment */ static bool ms_is_set_too_fast(ms_task_t *task); static bool ms_is_get_too_fast(ms_task_t *task); static void ms_kick_out_item(ms_task_item_t *item); + /* miss rate adjustment */ static bool ms_need_overwirte_item(ms_task_t *task); static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task); + /* deal with data verification initialization */ static void ms_task_data_verify_init(ms_task_t *task); static void ms_task_expire_verify_init(ms_task_t *task); + /* select a new task to do */ static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup); + /* run the selected task */ static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item); static void ms_update_stat_result(ms_conn_t *c); @@ -59,6 +65,7 @@ static void ms_send_signal(ms_sync_lock_t *sync_lock); static void ms_warmup_server(ms_conn_t *c); static int ms_run_getset_task(ms_conn_t *c); + /** * used to get the current operation item(object) * @@ -68,9 +75,10 @@ static int ms_run_getset_task(ms_conn_t *c); */ static ms_task_item_t *ms_get_cur_opt_item(ms_conn_t *c) { - return(c->curr_task.item); + return c->curr_task.item; } + /** * used to get the next item to do get operation * @@ -81,21 +89,27 @@ static ms_task_item_t *ms_get_cur_opt_item(ms_conn_t *c) */ static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c) { - ms_task_item_t *item = NULL; - - if (c->set_cursor <= 0) { - /* the first item in the window */ - item = &c->item_win[0]; - } else if (c->set_cursor > 0 && c->set_cursor < (uint32_t)c->win_size) { - /* random get one item set before */ - item = &c->item_win[random() % (int64_t)c->set_cursor]; - } else { - /* random get one item from the window */ - item = &c->item_win[random() % c->win_size]; - } + ms_task_item_t *item= NULL; + + if (c->set_cursor <= 0) + { + /* the first item in the window */ + item= &c->item_win[0]; + } + else if (c->set_cursor > 0 && c->set_cursor < (uint32_t)c->win_size) + { + /* random get one item set before */ + item= &c->item_win[random() % (int64_t)c->set_cursor]; + } + else + { + /* random get one item from the window */ + item= &c->item_win[random() % c->win_size]; + } + + return item; +} /* ms_get_next_get_item */ - return item; -} /** * used to get the next item to do set operation @@ -107,14 +121,15 @@ static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c) */ static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c) { - /** - * when a set command successes, the cursor will plus 1. If set - * fails, the cursor doesn't change. it isn't necessary to - * increase the cursor here. - */ - return(&c->item_win[(int64_t)c->set_cursor % c->win_size]); + /** + * when a set command successes, the cursor will plus 1. If set + * fails, the cursor doesn't change. it isn't necessary to + * increase the cursor here. + */ + return &c->item_win[(int64_t)c->set_cursor % c->win_size]; } + /** * If we need do overwrite, we could select a item set before. * This function is used to get a item set before to do @@ -127,12 +142,16 @@ static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c) */ static ms_task_item_t *ms_get_pre_set_item(ms_conn_t *c) { - if (c->set_cursor <= 0) { - return (&c->item_win[0]); - } else { - return(&c->item_win[(int64_t)--c->set_cursor % c->win_size]); - } -} + if (c->set_cursor <= 0) + { + return &c->item_win[0]; + } + else + { + return &c->item_win[(int64_t)-- c->set_cursor % c->win_size]; + } +} /* ms_get_pre_set_item */ + /** * According to the proportion of operations(get or set), select @@ -143,30 +162,35 @@ static ms_task_item_t *ms_get_pre_set_item(ms_conn_t *c) */ static void ms_select_opt(ms_conn_t *c, ms_task_t *task) { - double get_prop = ms_setting.cmd_distr[CMD_GET].cmd_prop; - double set_prop = ms_setting.cmd_distr[CMD_SET].cmd_prop; - - /* update cycle operation number if necessary */ - if (task->cycle_undo_get == 0 || task->cycle_undo_set == 0) { + double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop; + double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop; + + /* update cycle operation number if necessary */ + if ((task->cycle_undo_get == 0) || (task->cycle_undo_set == 0)) + { + task->cycle_undo_get+= (int)(CMD_DISTR_ADJUST_CYCLE * get_prop); + task->cycle_undo_set+= (int)(CMD_DISTR_ADJUST_CYCLE * set_prop); + } + + /** + * According to operation distribution to choose doing which + * operation. If it can't set new object to sever, just change + * to do get operation. + */ + if ((set_prop > PROP_ERROR) + && ((double)task->get_opt * set_prop >= (double)task->set_opt + * get_prop)) + { + task->cmd= CMD_SET; + task->item= ms_get_next_set_item(c); + } + else + { + task->cmd= CMD_GET; + task->item= ms_get_next_get_item(c); + } +} /* ms_select_opt */ - task->cycle_undo_get += (int)(CMD_DISTR_ADJUST_CYCLE * get_prop); - task->cycle_undo_set += (int)(CMD_DISTR_ADJUST_CYCLE * set_prop); - } - - /** - * According to operation distribution to choose doing which - * operation. If it can't set new object to sever, just change - * to do get operation. - */ - if (set_prop > PROP_ERROR - && (double)task->get_opt * set_prop >= (double)task->set_opt * get_prop) { - task->cmd = CMD_SET; - task->item = ms_get_next_set_item(c); - } else { - task->cmd = CMD_GET; - task->item = ms_get_next_get_item(c); - } -} /** * used to judge whether the number of get operations done is @@ -178,25 +202,27 @@ static void ms_select_opt(ms_conn_t *c, ms_task_t *task) */ static bool ms_is_get_too_fast(ms_task_t *task) { - double get_prop = ms_setting.cmd_distr[CMD_GET].cmd_prop; - double set_prop = ms_setting.cmd_distr[CMD_SET].cmd_prop; + double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop; + double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop; - /* no get operation */ - if (get_prop < PROP_ERROR) { - return false; - } + /* no get operation */ + if (get_prop < PROP_ERROR) + { + return false; + } - int max_undo_set = (int)(set_prop / get_prop *(1.0 + DISADJUST_FACTOR)) - * task->cycle_undo_get; + int max_undo_set= (int)(set_prop / get_prop * (1.0 + DISADJUST_FACTOR)) + * task->cycle_undo_get; - if ((double)task->get_opt * set_prop > (double)task->set_opt * get_prop - && task->cycle_undo_set > max_undo_set) { + if (((double)task->get_opt * set_prop > (double)task->set_opt * get_prop) + && (task->cycle_undo_set > max_undo_set)) + { + return true; + } - return true; - } + return false; +} /* ms_is_get_too_fast */ - return false; -} /** * used to judge whether the number of set operations done is @@ -208,25 +234,28 @@ static bool ms_is_get_too_fast(ms_task_t *task) */ static bool ms_is_set_too_fast(ms_task_t *task) { - double get_prop = ms_setting.cmd_distr[CMD_GET].cmd_prop; - double set_prop = ms_setting.cmd_distr[CMD_SET].cmd_prop; + double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop; + double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop; - /* no set operation */ - if (set_prop < PROP_ERROR) { - return false; - } + /* no set operation */ + if (set_prop < PROP_ERROR) + { + return false; + } - /* If it does set operation too fast, skip some */ - int max_undo_get = (int)((get_prop / set_prop * (1.0 + DISADJUST_FACTOR)) - * (double)task->cycle_undo_set); + /* If it does set operation too fast, skip some */ + int max_undo_get= (int)((get_prop / set_prop * (1.0 + DISADJUST_FACTOR)) + * (double)task->cycle_undo_set); - if ((double)task->get_opt * set_prop < (double)task->set_opt * get_prop - && task->cycle_undo_get > max_undo_get) { - return true; - } + if (((double)task->get_opt * set_prop < (double)task->set_opt * get_prop) + && (task->cycle_undo_get > max_undo_get)) + { + return true; + } + + return false; +} /* ms_is_set_too_fast */ - return false; -} /** * kick out the old item in the window, and add a new item to @@ -240,13 +269,14 @@ static bool ms_is_set_too_fast(ms_task_t *task) */ static void ms_kick_out_item(ms_task_item_t *item) { - /* allocate a new item */ - item->key_prefix = ms_get_key_prefix(); + /* allocate a new item */ + item->key_prefix= ms_get_key_prefix(); + + item->key_suffix_offset++; + item->value_offset= INVALID_OFFSET; /* new item use invalid value offset */ + item->client_time= 0; +} /* ms_kick_out_item */ - item->key_suffix_offset++; - item->value_offset = INVALID_OFFSET; /* new item use invalid value offset */ - item->client_time = 0; -} /** * used to judge whether we need overwrite object based on the @@ -259,22 +289,24 @@ static void ms_kick_out_item(ms_task_item_t *item) */ static bool ms_need_overwirte_item(ms_task_t *task) { - ms_task_item_t *item = task->item; + ms_task_item_t *item= task->item; - assert(item != NULL); - assert(task->cmd == CMD_SET); + assert(item != NULL); + assert(task->cmd == CMD_SET); - /** - * according to data overwrite percent to determine if do data - * overwrite. - */ - if (task->overwrite_set < (double)task->set_opt * ms_setting.overwrite_percent) { + /** + * according to data overwrite percent to determine if do data + * overwrite. + */ + if (task->overwrite_set < (double)task->set_opt + * ms_setting.overwrite_percent) + { + return true; + } - return true; - } + return false; +} /* ms_need_overwirte_item */ - return false; -} /** * used to adjust operation. the function must be called after @@ -289,72 +321,92 @@ static bool ms_need_overwirte_item(ms_task_t *task) */ static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task) { - ms_task_item_t *item = task->item; - assert(item != NULL); - - if (task->cmd == CMD_SET) { - /* If did set operation too fast, skip some */ - if (ms_is_set_too_fast(task)) { - - /* get the item instead */ - if (item->value_offset != INVALID_OFFSET) { - task->cmd = CMD_GET; - return true; - } - } - - /* If the current item is not a new item, kick it out */ - if (item->value_offset != INVALID_OFFSET) { - if(ms_need_overwirte_item(task)) { - /* overwrite */ - task->overwrite_set++; - } else { - /* kick out the current item to do set operation */ - ms_kick_out_item(item); - } - } else { /* it's a new item */ - /* need overwrite */ - if (ms_need_overwirte_item(task)) { - item = ms_get_pre_set_item(c); - if (item->value_offset != INVALID_OFFSET) { - task->item = item; - task->overwrite_set++; - } else { /* previous set item is a new item */ - /* select the previous item to run, and cancel overwrite */ - task->item = item; - } - } - } - task->cmd = CMD_SET; + ms_task_item_t *item= task->item; + + assert(item != NULL); + + if (task->cmd == CMD_SET) + { + /* If did set operation too fast, skip some */ + if (ms_is_set_too_fast(task)) + { + /* get the item instead */ + if (item->value_offset != INVALID_OFFSET) + { + task->cmd= CMD_GET; return true; - } else { + } + } - if (item->value_offset == INVALID_OFFSET) { - task->cmd = CMD_SET; - return true; + /* If the current item is not a new item, kick it out */ + if (item->value_offset != INVALID_OFFSET) + { + if (ms_need_overwirte_item(task)) + { + /* overwrite */ + task->overwrite_set++; + } + else + { + /* kick out the current item to do set operation */ + ms_kick_out_item(item); + } + } + else /* it's a new item */ + { + /* need overwrite */ + if (ms_need_overwirte_item(task)) + { + item= ms_get_pre_set_item(c); + if (item->value_offset != INVALID_OFFSET) + { + task->item= item; + task->overwrite_set++; } - - /** - * If It does get operation too fast, it will change the - * operation to set. - */ - if (ms_is_get_too_fast(task)) { - /* don't kick out the first item in the window */ - if (!ms_is_set_too_fast(task)) { - ms_kick_out_item(item); - task->cmd = CMD_SET; - return true; - } else { - return false; - } + else /* previous set item is a new item */ + { + /* select the previous item to run, and cancel overwrite */ + task->item= item; } + } + } + task->cmd= CMD_SET; + return true; + } + else + { + if (item->value_offset == INVALID_OFFSET) + { + task->cmd= CMD_SET; + return true; + } - assert(item->value_offset != INVALID_OFFSET); - - task->cmd = CMD_GET; + /** + * If It does get operation too fast, it will change the + * operation to set. + */ + if (ms_is_get_too_fast(task)) + { + /* don't kick out the first item in the window */ + if (! ms_is_set_too_fast(task)) + { + ms_kick_out_item(item); + task->cmd= CMD_SET; return true; + } + else + { + return false; + } } -} + + assert(item->value_offset != INVALID_OFFSET); + + task->cmd= CMD_GET; + return true; + } +} /* ms_adjust_opt */ + /** * used to initialize the task which need verify data. @@ -363,27 +415,32 @@ static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task) */ static void ms_task_data_verify_init(ms_task_t *task) { - ms_task_item_t *item = task->item; - - assert(item != NULL); - assert(task->cmd == CMD_GET); - + ms_task_item_t *item= task->item; + + assert(item != NULL); + assert(task->cmd == CMD_GET); + + /** + * according to data verification percent to determine if do + * data verification. + */ + if (task->verified_get < (double)task->get_opt + * ms_setting.verify_percent) + { /** - * according to data verification percent to determine if do - * data verification. + * currently it doesn't do verify, just increase the counter, + * and do verification next proper get command */ - if (task->verified_get < (double)task->get_opt * ms_setting.verify_percent) { - /** - * currently it doesn't do verify, just increase the counter, - * and do verification next proper get command - */ - if (task->item->value_offset != INVALID_OFFSET && item->exp_time == 0) { - task->verify = true; - task->finish_verify = false; - task->verified_get++; - } + if ((task->item->value_offset != INVALID_OFFSET) + && (item->exp_time == 0)) + { + task->verify= true; + task->finish_verify= false; + task->verified_get++; } -} + } +} /* ms_task_data_verify_init */ + /** * used to initialize the task which need verify expire time. @@ -392,15 +449,16 @@ static void ms_task_data_verify_init(ms_task_t *task) */ static void ms_task_expire_verify_init(ms_task_t *task) { - ms_task_item_t *item = task->item; + ms_task_item_t *item= task->item; - assert(item != NULL); - assert(task->cmd == CMD_GET); - assert(item->exp_time > 0); + assert(item != NULL); + assert(task->cmd == CMD_GET); + assert(item->exp_time > 0); + + task->verify= true; + task->finish_verify= false; +} /* ms_task_expire_verify_init */ - task->verify = true; - task->finish_verify = false; -} /** * used to get one task, the function initializes the task @@ -414,50 +472,57 @@ static void ms_task_expire_verify_init(ms_task_t *task) */ static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup) { - ms_task_t *task = &c->curr_task; + ms_task_t *task= &c->curr_task; - while (1) { - task->verify = false; - task->finish_verify = true; - task->get_miss = true; + while (1) + { + task->verify= false; + task->finish_verify= true; + task->get_miss= true; - if (warmup) { - task->cmd = CMD_SET; - task->item = ms_get_next_set_item(c); + if (warmup) + { + task->cmd= CMD_SET; + task->item= ms_get_next_set_item(c); - return task; - } - - /* according to operation distribution to choose doing which operation */ - ms_select_opt(c, task); - - if (!ms_adjust_opt(c, task)) { - continue; - } + return task; + } - if (ms_setting.verify_percent > 0 && task->cmd == CMD_GET) { - ms_task_data_verify_init(task); - } + /* according to operation distribution to choose doing which operation */ + ms_select_opt(c, task); - if (ms_setting.exp_ver_per > 0 && task->cmd == CMD_GET - && task->item->exp_time > 0) { - ms_task_expire_verify_init(task); - } + if (! ms_adjust_opt(c, task)) + { + continue; + } - break; + if ((ms_setting.verify_percent > 0) && (task->cmd == CMD_GET)) + { + ms_task_data_verify_init(task); } - /** - * Only update get and delete counter, set counter will be - * updated after set operation successes. - */ - if (task->cmd == CMD_GET) { - task->get_opt++; - task->cycle_undo_get--; + if ((ms_setting.exp_ver_per > 0) && (task->cmd == CMD_GET) + && (task->item->exp_time > 0)) + { + ms_task_expire_verify_init(task); } - return task; -} + break; + } + + /** + * Only update get and delete counter, set counter will be + * updated after set operation successes. + */ + if (task->cmd == CMD_GET) + { + task->get_opt++; + task->cycle_undo_get--; + } + + return task; +} /* ms_get_task */ + /** * send a signal to the main monitor thread @@ -466,11 +531,12 @@ static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup) */ static void ms_send_signal(ms_sync_lock_t *sync_lock) { - pthread_mutex_lock(&sync_lock->lock); - sync_lock->count++; - pthread_cond_signal(&sync_lock->cond); - pthread_mutex_unlock(&sync_lock->lock); -} + pthread_mutex_lock(&sync_lock->lock); + sync_lock->count++; + pthread_cond_signal(&sync_lock->cond); + pthread_mutex_unlock(&sync_lock->lock); +} /* ms_send_signal */ + /** * If user only want to do get operation, but there is no object @@ -481,44 +547,51 @@ static void ms_send_signal(ms_sync_lock_t *sync_lock) */ static void ms_warmup_server(ms_conn_t *c) { - ms_task_t *task; - ms_task_item_t *item; - - /** - * Extra one loop to get the last command returned state. - * Normally it gets the previous command returned state. - */ - if (c->remain_warmup_num >= 0 && - c->remain_warmup_num != c->warmup_num) { - item = ms_get_cur_opt_item(c); - /* only update the set command result state for data verification */ - if (c->precmd.cmd == CMD_SET && c->precmd.retstat == MCD_STORED) { - item->value_offset = item->key_suffix_offset; - /* set success, update counter */ - c->set_cursor++; - } else if (c->precmd.cmd == CMD_SET && c->precmd.retstat != MCD_STORED) { - printf("key: %lx didn't set success\n", item->key_prefix); - } + ms_task_t *task; + ms_task_item_t *item; + + /** + * Extra one loop to get the last command returned state. + * Normally it gets the previous command returned state. + */ + if ((c->remain_warmup_num >= 0) + && (c->remain_warmup_num != c->warmup_num)) + { + item= ms_get_cur_opt_item(c); + /* only update the set command result state for data verification */ + if ((c->precmd.cmd == CMD_SET) && (c->precmd.retstat == MCD_STORED)) + { + item->value_offset= item->key_suffix_offset; + /* set success, update counter */ + c->set_cursor++; } - - /* the last time don't run a task */ - if (c->remain_warmup_num-- > 0) { - /* operate next task item */ - task = ms_get_task(c, true); - item = task->item; - ms_mcd_set(c, item); + else if (c->precmd.cmd == CMD_SET && c->precmd.retstat != MCD_STORED) + { + printf("key: %lx didn't set success\n", item->key_prefix); } + } + + /* the last time don't run a task */ + if (c->remain_warmup_num-- > 0) + { + /* operate next task item */ + task= ms_get_task(c, true); + item= task->item; + ms_mcd_set(c, item); + } + + /** + * finish warming up server, wait all connects initialize + * complete. Then all connects can start do task at the same + * time. + */ + if (c->remain_warmup_num == -1) + { + ms_send_signal(&ms_global.init_lock); + c->remain_warmup_num--; /* never run the if branch */ + } +} /* ms_warmup_server */ - /** - * finish warming up server, wait all connects initialize - * complete. Then all connects can start do task at the same - * time. - */ - if (c->remain_warmup_num == -1) { - ms_send_signal(&ms_global.init_lock); - c->remain_warmup_num--; /* never run the if branch */ - } -} /** * dispatch single get and set task @@ -527,21 +600,26 @@ static void ms_warmup_server(ms_conn_t *c) */ static void ms_single_getset_task_sch(ms_conn_t *c) { - ms_task_t *task; - ms_task_item_t *item; - - /* the last time don't run a task */ - if (c->remain_exec_num-- > 0) { - task = ms_get_task(c, false); - item = task->item; - if (task->cmd == CMD_SET) { - ms_mcd_set(c, item); - } else if (task->cmd == CMD_GET) { - assert(task->cmd == CMD_GET); - ms_mcd_get(c, item, task->verify); - } + ms_task_t *task; + ms_task_item_t *item; + + /* the last time don't run a task */ + if (c->remain_exec_num-- > 0) + { + task= ms_get_task(c, false); + item= task->item; + if (task->cmd == CMD_SET) + { + ms_mcd_set(c, item); } -} + else if (task->cmd == CMD_GET) + { + assert(task->cmd == CMD_GET); + ms_mcd_get(c, item, task->verify); + } + } +} /* ms_single_getset_task_sch */ + /** * dispatch multi-get and set task @@ -550,39 +628,49 @@ static void ms_single_getset_task_sch(ms_conn_t *c) */ static void ms_multi_getset_task_sch(ms_conn_t *c) { - ms_task_t *task; - ms_mlget_task_item_t *mlget_item; - - while (1) { - if (c->remain_exec_num-- > 0) { - task = ms_get_task(c, false); - if (task->cmd == CMD_SET) { /* just do it */ - ms_mcd_set(c, task->item); - break; - } else { - assert(task->cmd == CMD_GET); - mlget_item = &c->mlget_task.mlget_item[c->mlget_task.mlget_num]; - mlget_item->item = task->item; - mlget_item->verify = task->verify; - mlget_item->finish_verify = task->finish_verify; - mlget_item->get_miss = task->get_miss; - c->mlget_task.mlget_num++; - - /* enough multi-get task items can be done */ - if (c->mlget_task.mlget_num >= ms_setting.mult_key_num || - (c->remain_exec_num == 0 && c->mlget_task.mlget_num > 0)) { - ms_mcd_mlget(c); - break; - } - } - } else { - if (c->remain_exec_num <= 0 && c->mlget_task.mlget_num > 0) { - ms_mcd_mlget(c); - } - break; + ms_task_t *task; + ms_mlget_task_item_t *mlget_item; + + while (1) + { + if (c->remain_exec_num-- > 0) + { + task= ms_get_task(c, false); + if (task->cmd == CMD_SET) /* just do it */ + { + ms_mcd_set(c, task->item); + break; + } + else + { + assert(task->cmd == CMD_GET); + mlget_item= &c->mlget_task.mlget_item[c->mlget_task.mlget_num]; + mlget_item->item= task->item; + mlget_item->verify= task->verify; + mlget_item->finish_verify= task->finish_verify; + mlget_item->get_miss= task->get_miss; + c->mlget_task.mlget_num++; + + /* enough multi-get task items can be done */ + if ((c->mlget_task.mlget_num >= ms_setting.mult_key_num) + || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0))) + { + ms_mcd_mlget(c); + break; } + } } -} + else + { + if ((c->remain_exec_num <= 0) && (c->mlget_task.mlget_num > 0)) + { + ms_mcd_mlget(c); + } + break; + } + } +} /* ms_multi_getset_task_sch */ + /** * calculate the difference value of two time points @@ -594,13 +682,14 @@ static void ms_multi_getset_task_sch(ms_conn_t *c) */ int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time) { - int64_t endtime = end_time->tv_sec * 1000000 + end_time->tv_usec; - int64_t starttime = start_time->tv_sec * 1000000 + start_time->tv_usec; + int64_t endtime= end_time->tv_sec * 1000000 + end_time->tv_usec; + int64_t starttime= start_time->tv_sec * 1000000 + start_time->tv_usec; - assert(endtime >= starttime); + assert(endtime >= starttime); + + return endtime - starttime; +} /* ms_time_diff */ - return(endtime - starttime); -} /** * after get the response from server for multi-get, the @@ -611,84 +700,103 @@ int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time) */ static void ms_update_multi_get_result(ms_conn_t *c) { - ms_mlget_task_item_t *mlget_item; - ms_task_item_t *item; - char *orignval = NULL; - char *orignkey = NULL; + ms_mlget_task_item_t *mlget_item; + ms_task_item_t *item; + char *orignval= NULL; + char *orignkey= NULL; + + if (c == NULL) + { + return; + } + assert(c != NULL); + + for (int i= 0; i < c->mlget_task.mlget_num; i++) + { + mlget_item= &c->mlget_task.mlget_item[i]; + item= mlget_item->item; + orignval= &ms_setting.char_block[item->value_offset]; + orignkey= &ms_setting.char_block[item->key_suffix_offset]; - if (c == NULL) { - return; + /* update get miss counter */ + if (mlget_item->get_miss) + { + __sync_fetch_and_add(&ms_stats.get_misses, 1); } - assert(c != NULL); - - for (int i = 0; i < c->mlget_task.mlget_num; i++) { - mlget_item = &c->mlget_task.mlget_item[i]; - item = mlget_item->item; - orignval = &ms_setting.char_block[item->value_offset]; - orignkey = &ms_setting.char_block[item->key_suffix_offset]; - /* update get miss counter */ - if (mlget_item->get_miss) { - __sync_fetch_and_add(&ms_stats.get_misses, 1); + /* get nothing from server for this task item */ + if (mlget_item->verify && ! mlget_item->finish_verify) + { + /* verify expire time if necessary */ + if (item->exp_time > 0) + { + struct timeval curr_time; + gettimeofday(&curr_time, NULL); + + /* object doesn't expire but can't get it now */ + if (curr_time.tv_sec - item->client_time + < item->exp_time - EXPIRE_TIME_ERROR) + { + __sync_fetch_and_add(&ms_stats.unexp_unget, 1); + + if (ms_setting.verbose) + { + char set_time[64]; + char cur_time[64]; + strftime(set_time, 64, "%Y-%m-%d %H:%M:%S", + localtime(&item->client_time)); + strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S", + localtime(&curr_time.tv_sec)); + fprintf(stderr, + "\n\t<%d expire time verification failed, object " + "doesn't expire but can't get it now\n" + "\tkey len: %d\n" + "\tkey: %lx %.*s\n" + "\tset time: %s current time: %s " + "diff time: %d expire time: %d\n" + "\texpected data len: %d\n" + "\texpected data: %.*s\n" + "\treceived data: \n", + c->sfd, + item->key_size, + item->key_prefix, + item->key_size - (int)KEY_PREFIX_SIZE, + orignkey, + set_time, + cur_time, + (int)(curr_time.tv_sec - item->client_time), + item->exp_time, + item->value_size, + item->value_size, + orignval); + fflush(stderr); + } } - - /* get nothing from server for this task item */ - if (mlget_item->verify && !mlget_item->finish_verify) { - /* verify expire time if necessary */ - if (item->exp_time > 0) { - struct timeval curr_time; - gettimeofday(&curr_time, NULL); - - /* object doesn't expire but can't get it now */ - if (curr_time.tv_sec - item->client_time - < item->exp_time - EXPIRE_TIME_ERROR) { - __sync_fetch_and_add(&ms_stats.unexp_unget, 1); - - if (ms_setting.verbose) { - char set_time[64]; - char cur_time[64]; - strftime(set_time, 64, "%Y-%m-%d %H:%M:%S", - localtime(&item->client_time)); - strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S", - localtime(&curr_time.tv_sec)); - fprintf(stderr, "\n\t<%d expire time verification failed, object " - "doesn't expire but can't get it now\n" - "\tkey len: %d\n" - "\tkey: %lx %.*s\n" - "\tset time: %s current time: %s " - "diff time: %d expire time: %d\n" - "\texpected data len: %d\n" - "\texpected data: %.*s\n" - "\treceived data: \n", - c->sfd, item->key_size, item->key_prefix, - item->key_size - (int)KEY_PREFIX_SIZE, - orignkey, set_time, cur_time, - (int)(curr_time.tv_sec - item->client_time), item->exp_time, - item->value_size, item->value_size, orignval); - fflush(stderr); - } - } - } else { - __sync_fetch_and_add(&ms_stats.vef_miss, 1); - - if (ms_setting.verbose) { - fprintf(stderr, "\n<%d data verification failed\n" - "\tkey len: %d\n" - "\tkey: %lx %.*s\n" - "\texpected data len: %d\n" - "\texpected data: %.*s\n" - "\treceived data: \n", - c->sfd, item->key_size, item->key_prefix, - item->key_size - (int)KEY_PREFIX_SIZE, - orignkey, item->value_size, item->value_size, orignval); - fflush(stderr); - } - } + } + else + { + __sync_fetch_and_add(&ms_stats.vef_miss, 1); + + if (ms_setting.verbose) + { + fprintf(stderr, "\n<%d data verification failed\n" + "\tkey len: %d\n" + "\tkey: %lx %.*s\n" + "\texpected data len: %d\n" + "\texpected data: %.*s\n" + "\treceived data: \n", + c->sfd, item->key_size, item->key_prefix, + item->key_size - (int)KEY_PREFIX_SIZE, + orignkey, item->value_size, item->value_size, orignval); + fflush(stderr); } + } } - c->mlget_task.mlget_num = 0; - c->mlget_task.value_index = INVALID_OFFSET; -} + } + c->mlget_task.mlget_num= 0; + c->mlget_task.value_index= INVALID_OFFSET; +} /* ms_update_multi_get_result */ + /** * after get the response from server for single get, the @@ -701,79 +809,96 @@ static void ms_update_multi_get_result(ms_conn_t *c) */ static void ms_update_single_get_result(ms_conn_t *c, ms_task_item_t *item) { - char *orignval = NULL; - char *orignkey = NULL; - - if (c == NULL || item == NULL) { - return; - } - assert(c != NULL); - assert(item != NULL); - - orignval = &ms_setting.char_block[item->value_offset]; - orignkey = &ms_setting.char_block[item->key_suffix_offset]; - - /* update get miss counter */ - if (c->precmd.cmd == CMD_GET && c->curr_task.get_miss) { - __sync_fetch_and_add(&ms_stats.get_misses, 1); + char *orignval= NULL; + char *orignkey= NULL; + + if ((c == NULL) || (item == NULL)) + { + return; + } + assert(c != NULL); + assert(item != NULL); + + orignval= &ms_setting.char_block[item->value_offset]; + orignkey= &ms_setting.char_block[item->key_suffix_offset]; + + /* update get miss counter */ + if ((c->precmd.cmd == CMD_GET) && c->curr_task.get_miss) + { + __sync_fetch_and_add(&ms_stats.get_misses, 1); + } + + /* get nothing from server for this task item */ + if ((c->precmd.cmd == CMD_GET) && c->curr_task.verify + && ! c->curr_task.finish_verify) + { + /* verify expire time if necessary */ + if (item->exp_time > 0) + { + struct timeval curr_time; + gettimeofday(&curr_time, NULL); + + /* object doesn't expire but can't get it now */ + if (curr_time.tv_sec - item->client_time + < item->exp_time - EXPIRE_TIME_ERROR) + { + __sync_fetch_and_add(&ms_stats.unexp_unget, 1); + + if (ms_setting.verbose) + { + char set_time[64]; + char cur_time[64]; + strftime(set_time, 64, "%Y-%m-%d %H:%M:%S", + localtime(&item->client_time)); + strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S", + localtime(&curr_time.tv_sec)); + fprintf(stderr, + "\n\t<%d expire time verification failed, object " + "doesn't expire but can't get it now\n" + "\tkey len: %d\n" + "\tkey: %lx %.*s\n" + "\tset time: %s current time: %s " + "diff time: %d expire time: %d\n" + "\texpected data len: %d\n" + "\texpected data: %.*s\n" + "\treceived data: \n", + c->sfd, + item->key_size, + item->key_prefix, + item->key_size - (int)KEY_PREFIX_SIZE, + orignkey, + set_time, + cur_time, + (int)(curr_time.tv_sec - item->client_time), + item->exp_time, + item->value_size, + item->value_size, + orignval); + fflush(stderr); + } + } } + else + { + __sync_fetch_and_add(&ms_stats.vef_miss, 1); - /* get nothing from server for this task item */ - if (c->precmd.cmd == CMD_GET && c->curr_task.verify - && !c->curr_task.finish_verify) { - - /* verify expire time if necessary */ - if (item->exp_time > 0) { - struct timeval curr_time; - gettimeofday(&curr_time, NULL); - - /* object doesn't expire but can't get it now */ - if (curr_time.tv_sec - item->client_time - < item->exp_time - EXPIRE_TIME_ERROR) { - __sync_fetch_and_add(&ms_stats.unexp_unget, 1); - - if (ms_setting.verbose) { - char set_time[64]; - char cur_time[64]; - strftime(set_time, 64, "%Y-%m-%d %H:%M:%S", - localtime(&item->client_time)); - strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S", - localtime(&curr_time.tv_sec)); - fprintf(stderr, "\n\t<%d expire time verification failed, object " - "doesn't expire but can't get it now\n" - "\tkey len: %d\n" - "\tkey: %lx %.*s\n" - "\tset time: %s current time: %s " - "diff time: %d expire time: %d\n" - "\texpected data len: %d\n" - "\texpected data: %.*s\n" - "\treceived data: \n", - c->sfd, item->key_size, item->key_prefix, - item->key_size - (int)KEY_PREFIX_SIZE, - orignkey, set_time, cur_time, - (int)(curr_time.tv_sec - item->client_time), item->exp_time, - item->value_size, item->value_size, orignval); - fflush(stderr); - } - } - } else { - __sync_fetch_and_add(&ms_stats.vef_miss, 1); - - if (ms_setting.verbose) { - fprintf(stderr, "\n<%d data verification failed\n" + if (ms_setting.verbose) + { + fprintf(stderr, "\n<%d data verification failed\n" "\tkey len: %d\n" "\tkey: %lx %.*s\n" "\texpected data len: %d\n" "\texpected data: %.*s\n" "\treceived data: \n", - c->sfd, item->key_size, item->key_prefix, - item->key_size - (int)KEY_PREFIX_SIZE, - orignkey, item->value_size, item->value_size, orignval); - fflush(stderr); - } - } + c->sfd, item->key_size, item->key_prefix, + item->key_size - (int)KEY_PREFIX_SIZE, + orignkey, item->value_size, item->value_size, orignval); + fflush(stderr); + } } -} + } +} /* ms_update_single_get_result */ + /** * after get the response from server for set the function @@ -785,35 +910,42 @@ static void ms_update_single_get_result(ms_conn_t *c, ms_task_item_t *item) */ static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item) { - if (c == NULL || item == NULL) { - return; - } - assert(c != NULL); - assert(item != NULL); - - if (c->precmd.cmd == CMD_SET) { - switch (c->precmd.retstat) { - case MCD_STORED: - if (item->value_offset == INVALID_OFFSET) { - /* first set with the same offset of key suffix */ - item->value_offset = item->key_suffix_offset; - } else { - /* not first set, just increase the value offset */ - item->value_offset += 1; - } - - /* set successes, update counter */ - c->set_cursor++; - c->curr_task.set_opt++; - c->curr_task.cycle_undo_set--; - break; - - case MCD_SERVER_ERROR: - default: - break; - } - } -} + if ((c == NULL) || (item == NULL)) + { + return; + } + assert(c != NULL); + assert(item != NULL); + + if (c->precmd.cmd == CMD_SET) + { + switch (c->precmd.retstat) + { + case MCD_STORED: + if (item->value_offset == INVALID_OFFSET) + { + /* first set with the same offset of key suffix */ + item->value_offset= item->key_suffix_offset; + } + else + { + /* not first set, just increase the value offset */ + item->value_offset+= 1; + } + + /* set successes, update counter */ + c->set_cursor++; + c->curr_task.set_opt++; + c->curr_task.cycle_undo_set--; + break; + + case MCD_SERVER_ERROR: + default: + break; + } /* switch */ + } +} /* ms_update_set_result */ + /** * update the response time result @@ -822,33 +954,41 @@ static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item) */ static void ms_update_stat_result(ms_conn_t *c) { - bool get_miss = false; + bool get_miss= false; - if (c == NULL) { - return; - } - assert(c != NULL); + if (c == NULL) + { + return; + } + assert(c != NULL); - gettimeofday(&c->end_time, NULL); - uint64_t time_diff = (uint64_t)ms_time_diff(&c->start_time, &c->end_time); + gettimeofday(&c->end_time, NULL); + uint64_t time_diff= (uint64_t)ms_time_diff(&c->start_time, &c->end_time); - pthread_mutex_lock(&ms_statistic.stat_mutex); - switch (c->precmd.cmd) { - case CMD_SET: - ms_record_event(&ms_statistic.set_stat, time_diff, false); - break; - case CMD_GET: - if (c->curr_task.get_miss) { - get_miss = true; - } - ms_record_event(&ms_statistic.get_stat, time_diff, get_miss); - break; - default: - break; + pthread_mutex_lock(&ms_statistic.stat_mutex); + + switch (c->precmd.cmd) + { + case CMD_SET: + ms_record_event(&ms_statistic.set_stat, time_diff, false); + break; + + case CMD_GET: + if (c->curr_task.get_miss) + { + get_miss= true; } - ms_record_event(&ms_statistic.total_stat, time_diff, get_miss); - pthread_mutex_unlock(&ms_statistic.stat_mutex); -} + ms_record_event(&ms_statistic.get_stat, time_diff, get_miss); + break; + + default: + break; + } /* switch */ + + ms_record_event(&ms_statistic.total_stat, time_diff, get_miss); + pthread_mutex_unlock(&ms_statistic.stat_mutex); +} /* ms_update_stat_result */ + /** * after get response from server for the current operation, and @@ -859,34 +999,42 @@ static void ms_update_stat_result(ms_conn_t *c) */ static void ms_update_task_result(ms_conn_t *c) { - ms_task_item_t *item; - if (c == NULL) { - return; - } - assert(c != NULL); - - item = ms_get_cur_opt_item(c); - if (item == NULL) { - return; - } - assert(item != NULL); - - ms_update_set_result(c, item); + ms_task_item_t *item; + + if (c == NULL) + { + return; + } + assert(c != NULL); + + item= ms_get_cur_opt_item(c); + if (item == NULL) + { + return; + } + assert(item != NULL); + + ms_update_set_result(c, item); + + if ((ms_setting.stat_freq > 0) + && ((c->precmd.cmd == CMD_SET) || (c->precmd.cmd == CMD_GET))) + { + ms_update_stat_result(c); + } + + /* update multi-get task item */ + if (((ms_setting.mult_key_num > 1) + && (c->mlget_task.mlget_num >= ms_setting.mult_key_num)) + || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0))) + { + ms_update_multi_get_result(c); + } + else + { + ms_update_single_get_result(c, item); + } +} /* ms_update_task_result */ - if (ms_setting.stat_freq > 0 - && (c->precmd.cmd == CMD_SET || c->precmd.cmd == CMD_GET)) { - ms_update_stat_result(c); - } - - /* update multi-get task item */ - if ((ms_setting.mult_key_num > 1 && - c->mlget_task.mlget_num >= ms_setting.mult_key_num) || - (c->remain_exec_num == 0 && c->mlget_task.mlget_num > 0)) { - ms_update_multi_get_result(c); - } else { - ms_update_single_get_result(c, item); - } -} /** * run get and set operation @@ -897,31 +1045,37 @@ static void ms_update_task_result(ms_conn_t *c) */ static int ms_run_getset_task(ms_conn_t *c) { - /** - * extra one loop to get the last command return state. get the - * last command return state. - */ - if (c->remain_exec_num >= 0 && - c->remain_exec_num != c->exec_num) { - ms_update_task_result(c); - } + /** + * extra one loop to get the last command return state. get the + * last command return state. + */ + if ((c->remain_exec_num >= 0) + && (c->remain_exec_num != c->exec_num)) + { + ms_update_task_result(c); + } + + /* multi-get */ + if (ms_setting.mult_key_num > 1) + { + /* operate next task item */ + ms_multi_getset_task_sch(c); + } + else + { + /* operate next task item */ + ms_single_getset_task_sch(c); + } + + /* no task to do, exit */ + if ((c->remain_exec_num == -1) || ms_global.time_out) + { + return -1; + } + + return 0; +} /* ms_run_getset_task */ - /* multi-get */ - if (ms_setting.mult_key_num > 1) { - /* operate next task item */ - ms_multi_getset_task_sch(c); - } else { - /* operate next task item */ - ms_single_getset_task_sch(c); - } - - /* no task to do, exit */ - if (c->remain_exec_num == -1 || ms_global.time_out) { - return -1; - } - - return 0; -} /** * the state machine call the function to execute task. @@ -932,13 +1086,17 @@ static int ms_run_getset_task(ms_conn_t *c) */ int ms_exec_task(struct conn *c) { - if (!ms_global.finish_warmup) { - ms_warmup_server(c); - } else { - if (ms_run_getset_task(c) != 0) { - return -1; - } + if (! ms_global.finish_warmup) + { + ms_warmup_server(c); + } + else + { + if (ms_run_getset_task(c) != 0) + { + return -1; } + } - return 0; -} + return 0; +} /* ms_exec_task */ diff --git a/clients/ms_task.h b/clients/ms_task.h index 0876fc7d..610f3bc5 100644 --- a/clients/ms_task.h +++ b/clients/ms_task.h @@ -20,55 +20,59 @@ extern "C" { #endif -#define UNIT_ITEMS_COUNT 1024 /* each window unit has 1024 items */ -#define KEY_PREFIX_SIZE (sizeof(uint64_t)) /* key prefix length: 8 bytes */ -#define INVALID_OFFSET (-1) /* invalid offset in the character table */ -#define FIXED_EXPIRE_TIME 60 /* default expire time is 60s */ -#define EXPIRE_TIME_ERROR 5 /* default expire time error is 5s */ +#define UNIT_ITEMS_COUNT 1024 /* each window unit has 1024 items */ +#define KEY_PREFIX_SIZE (sizeof(uint64_t)) /* key prefix length: 8 bytes */ +#define INVALID_OFFSET (-1) /* invalid offset in the character table */ +#define FIXED_EXPIRE_TIME 60 /* default expire time is 60s */ +#define EXPIRE_TIME_ERROR 5 /* default expire time error is 5s */ /* information of a task item(object) */ -typedef struct task_item { - uint64_t key_prefix; /* prefix of the key, 8 bytes, binary */ - int key_size; /* key size */ - int key_suffix_offset; /* suffix offset in the global character table */ +typedef struct task_item +{ + uint64_t key_prefix; /* prefix of the key, 8 bytes, binary */ + int key_size; /* key size */ + int key_suffix_offset; /* suffix offset in the global character table */ - int value_size; /* data size */ - int value_offset; /* data offset in the global character table */ + int value_size; /* data size */ + int value_offset; /* data offset in the global character table */ - time_t client_time; /* the current client time */ - int exp_time; /* expire time */ + time_t client_time; /* the current client time */ + int exp_time; /* expire time */ } ms_task_item_t; /* task item for multi-get */ -typedef struct mlget_task_item { - ms_task_item_t *item; /* task item */ - bool verify; /* whether verify data or not */ - bool finish_verify; /* whether finish data verify or not */ - bool get_miss; /* whether get miss or not */ +typedef struct mlget_task_item +{ + ms_task_item_t *item; /* task item */ + bool verify; /* whether verify data or not */ + bool finish_verify; /* whether finish data verify or not */ + bool get_miss; /* whether get miss or not */ } ms_mlget_task_item_t; /* information of multi-get task */ -typedef struct mlget_task { - ms_mlget_task_item_t *mlget_item; /* multi-get task array */ - int mlget_num; /* how many tasks in mlget_task array */ - int value_index; /* the nth value received by the connect, for multi-get */ +typedef struct mlget_task +{ + ms_mlget_task_item_t *mlget_item; /* multi-get task array */ + int mlget_num; /* how many tasks in mlget_task array */ + int value_index; /* the nth value received by the connect, for multi-get */ } ms_mlget_task_t; /* structure used to store the state of the running task */ -typedef struct task { - int cmd; /* command name */ - bool verify; /* whether verify data or not */ - bool finish_verify; /* whether finish data verify or not */ - bool get_miss; /* whether get miss or not */ - ms_task_item_t *item; /* task item */ - - /* counter for command distribution adjustment */ - uint64_t get_opt; /* number of total get operations */ - uint64_t set_opt; /* number of total set operations, no including warmup set count */ - int cycle_undo_get; /* number of undo get in an adjustment cycle */ - int cycle_undo_set; /* number of undo set in an adjustment cycle */ - uint64_t verified_get; /* number of total verified get operations */ - uint64_t overwrite_set; /* number of total overwrite set operations */ +typedef struct task +{ + int cmd; /* command name */ + bool verify; /* whether verify data or not */ + bool finish_verify; /* whether finish data verify or not */ + bool get_miss; /* whether get miss or not */ + ms_task_item_t *item; /* task item */ + + /* counter for command distribution adjustment */ + uint64_t get_opt; /* number of total get operations */ + uint64_t set_opt; /* number of total set operations, no including warmup set count */ + int cycle_undo_get; /* number of undo get in an adjustment cycle */ + int cycle_undo_set; /* number of undo set in an adjustment cycle */ + uint64_t verified_get; /* number of total verified get operations */ + uint64_t overwrite_set; /* number of total overwrite set operations */ } ms_task_t; struct conn; @@ -76,9 +80,11 @@ struct conn; /* the state machine call the function to execute task.*/ int ms_exec_task(struct conn *c); + /* calculate the difference value of two time points */ int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time); + #ifdef __cplusplus } #endif diff --git a/clients/ms_thread.c b/clients/ms_thread.c index f381c115..f8dc1b01 100644 --- a/clients/ms_thread.c +++ b/clients/ms_thread.c @@ -33,11 +33,12 @@ static void ms_create_worker(void *(*func)(void *), void *arg); */ static void ms_set_current_time() { - struct timeval timer; + struct timeval timer; + + gettimeofday(&timer, NULL); + ms_thread.curr_time= (rel_time_t)timer.tv_sec; +} /* ms_set_current_time */ - gettimeofday(&timer, NULL); - ms_thread.curr_time = (rel_time_t)timer.tv_sec; -} /** * used to check whether UDP of command are waiting timeout @@ -45,36 +46,43 @@ static void ms_set_current_time() */ static void ms_check_sock_timeout(void) { - ms_conn_t *c = NULL; - int time_diff = 0; - - for (int i = 0; i < ms_thread.thread_ctx->nconns; i++) { - c = &ms_thread.conn[i]; - - if (c->udp) { - time_diff = (int)(ms_thread.curr_time - c->start_time.tv_sec); - - /* wait time out */ - if (time_diff > SOCK_WAIT_TIMEOUT) { - /* calculate dropped packets count */ - if (c->recvpkt > 0) { - __sync_fetch_and_add(&ms_stats.pkt_drop, c->packets - c->recvpkt); - } - - __sync_fetch_and_add(&ms_stats.udp_timeout, 1); - ms_reset_conn(c, true); - } + ms_conn_t *c= NULL; + int time_diff= 0; + + for (int i= 0; i < ms_thread.thread_ctx->nconns; i++) + { + c= &ms_thread.conn[i]; + + if (c->udp) + { + time_diff= (int)(ms_thread.curr_time - c->start_time.tv_sec); + + /* wait time out */ + if (time_diff > SOCK_WAIT_TIMEOUT) + { + /* calculate dropped packets count */ + if (c->recvpkt > 0) + { + __sync_fetch_and_add(&ms_stats.pkt_drop, c->packets - c->recvpkt); } + + __sync_fetch_and_add(&ms_stats.udp_timeout, 1); + ms_reset_conn(c, true); + } } -} + } +} /* ms_check_sock_timeout */ + /* if disconnect, the ever-1-second timer will call this function to reconnect */ static void ms_reconn_thread_socks(void) { - for (int i = 0; i < ms_thread.thread_ctx->nconns; i++) { - ms_reconn_socks(&ms_thread.conn[i]); - } -} + for (int i= 0; i < ms_thread.thread_ctx->nconns; i++) + { + ms_reconn_socks(&ms_thread.conn[i]); + } +} /* ms_reconn_thread_socks */ + /** * the handler of the ever-1-second timer @@ -85,28 +93,35 @@ static void ms_reconn_thread_socks(void) */ static void ms_clock_handler(const int fd, const short which, void *arg) { - struct timeval t = {.tv_sec = 1, .tv_usec = 0}; + struct timeval t= + { + .tv_sec= 1, .tv_usec= 0 + }; - UNUSED_ARGUMENT(fd); - UNUSED_ARGUMENT(which); - UNUSED_ARGUMENT(arg); + UNUSED_ARGUMENT(fd); + UNUSED_ARGUMENT(which); + UNUSED_ARGUMENT(arg); - ms_set_current_time(); + ms_set_current_time(); - if (ms_thread.initialized) { - /* only delete the event if it's actually there. */ - evtimer_del(&ms_thread.clock_event); - ms_check_sock_timeout(); - } else { - ms_thread.initialized = true; - } + if (ms_thread.initialized) + { + /* only delete the event if it's actually there. */ + evtimer_del(&ms_thread.clock_event); + ms_check_sock_timeout(); + } + else + { + ms_thread.initialized= true; + } - ms_reconn_thread_socks(); + ms_reconn_thread_socks(); + + evtimer_set(&ms_thread.clock_event, ms_clock_handler, 0); + event_base_set(ms_thread.base, &ms_thread.clock_event); + evtimer_add(&ms_thread.clock_event, &t); +} /* ms_clock_handler */ - evtimer_set(&ms_thread.clock_event, ms_clock_handler, 0); - event_base_set(ms_thread.base, &ms_thread.clock_event); - evtimer_add(&ms_thread.clock_event, &t); -} /** * used to bind thread to CPU if the system supports @@ -117,23 +132,25 @@ static void ms_clock_handler(const int fd, const short which, void *arg) */ static int ms_set_thread_cpu_affinity(int cpu) { - int ret = 0; + int ret= 0; #ifdef HAVE_CPU_SET_T - cpu_set_t cpu_set; - CPU_ZERO(&cpu_set); - CPU_SET(cpu, &cpu_set); - - if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) == -1){ - fprintf(stderr, "WARNING: Could not set CPU Affinity, continuing...\n"); - ret = 1; - } + cpu_set_t cpu_set; + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) == -1) + { + fprintf(stderr, "WARNING: Could not set CPU Affinity, continuing...\n"); + ret= 1; + } #else - UNUSED_ARGUMENT(cpu); -#endif + UNUSED_ARGUMENT(cpu); +#endif + + return ret; +} /* ms_set_thread_cpu_affinity */ - return ret; -} /** * Set up a thread's information. @@ -144,47 +161,57 @@ static int ms_set_thread_cpu_affinity(int cpu) */ static int ms_setup_thread(ms_thread_ctx_t *thread_ctx) { - ms_thread.thread_ctx = thread_ctx; - ms_thread.nactive_conn = thread_ctx->nconns; - ms_thread.initialized = false; - static int cnt = 0; - - gettimeofday(&ms_thread.startup_time, NULL); - - ms_thread.base = event_init(); - if (ms_thread.base == NULL) { - if (__sync_fetch_and_add(&cnt, 1) == 0) { - fprintf(stderr, "Can't allocate event base.\n"); - } - - return -1; + ms_thread.thread_ctx= thread_ctx; + ms_thread.nactive_conn= thread_ctx->nconns; + ms_thread.initialized= false; + static int cnt= 0; + + gettimeofday(&ms_thread.startup_time, NULL); + + ms_thread.base= event_init(); + if (ms_thread.base == NULL) + { + if (__sync_fetch_and_add(&cnt, 1) == 0) + { + fprintf(stderr, "Can't allocate event base.\n"); } - ms_thread.conn = (ms_conn_t *)malloc((size_t)thread_ctx->nconns * sizeof(ms_conn_t)); - if (ms_thread.conn == NULL) { - if (__sync_fetch_and_add(&cnt, 1) == 0) { - fprintf(stderr, "Can't allocate concurrency structure for thread descriptors."); - } - - return -1; + return -1; + } + + ms_thread.conn= + (ms_conn_t *)malloc((size_t)thread_ctx->nconns * sizeof(ms_conn_t)); + if (ms_thread.conn == NULL) + { + if (__sync_fetch_and_add(&cnt, 1) == 0) + { + fprintf( + stderr, + "Can't allocate concurrency structure for thread descriptors."); } - memset(ms_thread.conn, 0, (size_t)thread_ctx->nconns * sizeof(ms_conn_t)); - - for (int i = 0; i < thread_ctx->nconns; i++) { - ms_thread.conn[i].conn_idx = i; - if (ms_setup_conn(&ms_thread.conn[i]) != 0) { - - /* only output this error once */ - if (__sync_fetch_and_add(&cnt, 1) == 0) { - fprintf(stderr, "Initializing connection failed.\n"); - } - return -1; - } + return -1; + } + memset(ms_thread.conn, 0, (size_t)thread_ctx->nconns * sizeof(ms_conn_t)); + + for (int i= 0; i < thread_ctx->nconns; i++) + { + ms_thread.conn[i].conn_idx= i; + if (ms_setup_conn(&ms_thread.conn[i]) != 0) + { + /* only output this error once */ + if (__sync_fetch_and_add(&cnt, 1) == 0) + { + fprintf(stderr, "Initializing connection failed.\n"); + } + + return -1; } + } + + return 0; +} /* ms_setup_thread */ - return 0; -} /** * Worker thread: main event loop @@ -195,27 +222,30 @@ static int ms_setup_thread(ms_thread_ctx_t *thread_ctx) */ static void *ms_worker_libevent(void *arg) { - ms_thread_ctx_t *thread_ctx = (ms_thread_ctx_t *)arg; + ms_thread_ctx_t *thread_ctx= (ms_thread_ctx_t *)arg; - /** - * If system has more than one cpu and supports set cpu - * affinity, try to bind each thread to a cpu core; - */ - if (ms_setting.ncpu > 1) { - ms_set_thread_cpu_affinity(thread_ctx->thd_idx % ms_setting.ncpu); - } + /** + * If system has more than one cpu and supports set cpu + * affinity, try to bind each thread to a cpu core; + */ + if (ms_setting.ncpu > 1) + { + ms_set_thread_cpu_affinity(thread_ctx->thd_idx % ms_setting.ncpu); + } - if (ms_setup_thread(thread_ctx) != 0) { - exit(1); - } + if (ms_setup_thread(thread_ctx) != 0) + { + exit(1); + } + + /* each thread with a timer */ + ms_clock_handler(0, 0, 0); - /* each thread with a timer */ - ms_clock_handler(0, 0, 0); + event_base_loop(ms_thread.base, 0); - event_base_loop(ms_thread.base, 0); + return NULL; +} /* ms_worker_libevent */ - return NULL; -} /** * Creates a worker thread. @@ -225,51 +255,62 @@ static void *ms_worker_libevent(void *arg) */ static void ms_create_worker(void *(*func)(void *), void *arg) { - pthread_t thread; - pthread_attr_t attr; - int ret; + pthread_t thread; + pthread_attr_t attr; + int ret; - pthread_attr_init(&attr); + pthread_attr_init(&attr); + + if ((ret= pthread_create(&thread, &attr, func, arg)) != 0) + { + fprintf(stderr, "Can't create thread: %s.\n", strerror(ret)); + exit(1); + } +} /* ms_create_worker */ - if ((ret = pthread_create(&thread, &attr, func, arg)) != 0) { - fprintf(stderr, "Can't create thread: %s.\n", strerror(ret)); - exit(1); - } -} /* initialize threads */ void ms_thread_init() { - ms_thread_ctx = (ms_thread_ctx_t *)malloc(sizeof(ms_thread_ctx_t) * (size_t)ms_setting.nthreads); - if (ms_thread_ctx == NULL) { - fprintf(stderr, "Can't allocate thread descriptors."); - exit(1); - } + ms_thread_ctx= + (ms_thread_ctx_t *)malloc( + sizeof(ms_thread_ctx_t) * (size_t)ms_setting.nthreads); + if (ms_thread_ctx == NULL) + { + fprintf(stderr, "Can't allocate thread descriptors."); + exit(1); + } + + for (int i= 0; i < ms_setting.nthreads; i++) + { + ms_thread_ctx[i].thd_idx= i; + ms_thread_ctx[i].nconns= ms_setting.nconns / ms_setting.nthreads; - for (int i = 0; i < ms_setting.nthreads; i++) { - ms_thread_ctx[i].thd_idx = i; - ms_thread_ctx[i].nconns = ms_setting.nconns / ms_setting.nthreads; - - /** - * If only one server, all the connections in all threads - * connects the same server. For support multi-servers, simple - * distribute thread to server. - */ - ms_thread_ctx[i].srv_idx = i % ms_setting.srv_cnt; - ms_thread_ctx[i].tps_perconn = ms_setting.expected_tps / ms_setting.nconns; - ms_thread_ctx[i].exec_num_perconn = ms_setting.exec_num / ms_setting.nconns; - } + /** + * If only one server, all the connections in all threads + * connects the same server. For support multi-servers, simple + * distribute thread to server. + */ + ms_thread_ctx[i].srv_idx= i % ms_setting.srv_cnt; + ms_thread_ctx[i].tps_perconn= ms_setting.expected_tps + / ms_setting.nconns; + ms_thread_ctx[i].exec_num_perconn= ms_setting.exec_num + / ms_setting.nconns; + } + + /* Create threads after we've done all the epoll setup. */ + for (int i= 0; i < ms_setting.nthreads; i++) + { + ms_create_worker(ms_worker_libevent, (void *)&ms_thread_ctx[i]); + } +} /* ms_thread_init */ - /* Create threads after we've done all the epoll setup. */ - for (int i = 0; i < ms_setting.nthreads; i++) { - ms_create_worker(ms_worker_libevent, (void *)&ms_thread_ctx[i]); - } -} /* cleanup some resource of threads when all the threads exit */ void ms_thread_cleanup() { - if (ms_thread_ctx != NULL) { - free(ms_thread_ctx); - } -} + if (ms_thread_ctx != NULL) + { + free(ms_thread_ctx); + } +} /* ms_thread_cleanup */ diff --git a/clients/ms_thread.h b/clients/ms_thread.h index 2fa13d57..3eea2563 100644 --- a/clients/ms_thread.h +++ b/clients/ms_thread.h @@ -35,38 +35,42 @@ extern "C" { #endif /** Time relative to server start. Smaller than time_t on 64-bit systems. */ -typedef unsigned int rel_time_t; +typedef unsigned int rel_time_t; /* Used to store the context of each thread */ -typedef struct thread_ctx { - int thd_idx; /* the thread index */ - int nconns; /* how many connections included by the thread */ - int srv_idx; /* index of the thread */ - int tps_perconn; /* expected throughput per connection */ - int64_t exec_num_perconn; /* execute number per connection */ +typedef struct thread_ctx +{ + int thd_idx; /* the thread index */ + int nconns; /* how many connections included by the thread */ + int srv_idx; /* index of the thread */ + int tps_perconn; /* expected throughput per connection */ + int64_t exec_num_perconn; /* execute number per connection */ } ms_thread_ctx_t; /* Used to store the private variables of each thread */ -typedef struct thread { - ms_conn_t *conn; /* conn array to store all the conn in the thread */ - int nactive_conn; /* how many connects are active */ +typedef struct thread +{ + ms_conn_t *conn; /* conn array to store all the conn in the thread */ + int nactive_conn; /* how many connects are active */ - ms_thread_ctx_t *thread_ctx; /* thread context from the caller */ - struct event_base *base; /* libevent handler created by this thread */ + ms_thread_ctx_t *thread_ctx; /* thread context from the caller */ + struct event_base *base; /* libevent handler created by this thread */ - rel_time_t curr_time; /* current time */ - struct event clock_event; /* clock event to time each one second */ - bool initialized; /* whether clock_event has been initialized */ + rel_time_t curr_time; /* current time */ + struct event clock_event; /* clock event to time each one second */ + bool initialized; /* whether clock_event has been initialized */ - struct timeval startup_time; /* start time of the thread */ + struct timeval startup_time; /* start time of the thread */ } ms_thread_t; /* initialize threads */ void ms_thread_init(void); + /* cleanup some resource of threads when all the threads exit */ void ms_thread_cleanup(void); + #ifdef __cplusplus } #endif diff --git a/clients/protocol_binary.h b/clients/protocol_binary.h index 08df72e8..bd080ab8 100644 --- a/clients/protocol_binary.h +++ b/clients/protocol_binary.h @@ -24,6 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + /* * Summary: Constants used by to implement the binary protocol. * @@ -48,313 +49,348 @@ extern "C" { #endif - /** - * Definition of the legal "magic" values used in a packet. - * See section 3.1 Magic byte - */ - typedef enum { - PROTOCOL_BINARY_REQ = 0x80, - PROTOCOL_BINARY_RES = 0x81 - } protocol_binary_magic; - - /** - * Definition of the valid response status numbers. - * See section 3.2 Response Status - */ - typedef enum { - PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00, - PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01, - PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02, - PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03, - PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04, - PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05, - PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81, - PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82 - } protocol_binary_response_status; - - /** - * Defintion of the different command opcodes. - * See section 3.3 Command Opcodes - */ - typedef enum { - PROTOCOL_BINARY_CMD_GET = 0x00, - PROTOCOL_BINARY_CMD_SET = 0x01, - PROTOCOL_BINARY_CMD_ADD = 0x02, - PROTOCOL_BINARY_CMD_REPLACE = 0x03, - PROTOCOL_BINARY_CMD_DELETE = 0x04, - PROTOCOL_BINARY_CMD_INCREMENT = 0x05, - PROTOCOL_BINARY_CMD_DECREMENT = 0x06, - PROTOCOL_BINARY_CMD_QUIT = 0x07, - PROTOCOL_BINARY_CMD_FLUSH = 0x08, - PROTOCOL_BINARY_CMD_GETQ = 0x09, - PROTOCOL_BINARY_CMD_NOOP = 0x0a, - PROTOCOL_BINARY_CMD_VERSION = 0x0b, - PROTOCOL_BINARY_CMD_GETK = 0x0c, - PROTOCOL_BINARY_CMD_GETKQ = 0x0d, - PROTOCOL_BINARY_CMD_APPEND = 0x0e, - PROTOCOL_BINARY_CMD_PREPEND = 0x0f, - PROTOCOL_BINARY_CMD_STAT = 0x10, - PROTOCOL_BINARY_CMD_SETQ = 0x11, - PROTOCOL_BINARY_CMD_ADDQ = 0x12, - PROTOCOL_BINARY_CMD_REPLACEQ = 0x13, - PROTOCOL_BINARY_CMD_DELETEQ = 0x14, - PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15, - PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16, - PROTOCOL_BINARY_CMD_QUITQ = 0x17, - PROTOCOL_BINARY_CMD_FLUSHQ = 0x18, - PROTOCOL_BINARY_CMD_APPENDQ = 0x19, - PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a - } protocol_binary_command; - - /** - * Definition of the data types in the packet - * See section 3.4 Data Types - */ - typedef enum { - PROTOCOL_BINARY_RAW_BYTES = 0x00 - } protocol_binary_datatypes; - - /** - * Definition of the header structure for a request packet. - * See section 2 - */ - typedef union { - struct { - uint8_t magic; - uint8_t opcode; - uint16_t keylen; - uint8_t extlen; - uint8_t datatype; - uint16_t reserved; - uint32_t bodylen; - uint32_t opaque; - uint64_t cas; - } request; - uint8_t bytes[24]; - } protocol_binary_request_header; - - /** - * Definition of the header structure for a response packet. - * See section 2 - */ - typedef union { - struct { - uint8_t magic; - uint8_t opcode; - uint16_t keylen; - uint8_t extlen; - uint8_t datatype; - uint16_t status; - uint32_t bodylen; - uint32_t opaque; - uint64_t cas; - } response; - uint8_t bytes[24]; - } protocol_binary_response_header; - - /** - * Definition of a request-packet containing no extras - */ - typedef union { - struct { - protocol_binary_request_header header; - } message; - uint8_t bytes[sizeof(protocol_binary_request_header)]; - } protocol_binary_request_no_extras; - - /** - * Definition of a response-packet containing no extras - */ - typedef union { - struct { - protocol_binary_response_header header; - } message; - uint8_t bytes[sizeof(protocol_binary_response_header)]; - } protocol_binary_response_no_extras; - - /** - * Definition of the packet used by the get, getq, getk and getkq command. - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_get; - typedef protocol_binary_request_no_extras protocol_binary_request_getq; - typedef protocol_binary_request_no_extras protocol_binary_request_getk; - typedef protocol_binary_request_no_extras protocol_binary_request_getkq; - - /** - * Definition of the packet returned from a successful get, getq, getk and - * getkq. - * See section 4 - */ - typedef union { - struct { - protocol_binary_response_header header; - struct { - uint32_t flags; - } body; - } message; - uint8_t bytes[sizeof(protocol_binary_response_header) + 4]; - } protocol_binary_response_get; - - typedef protocol_binary_response_get protocol_binary_response_getq; - typedef protocol_binary_response_get protocol_binary_response_getk; - typedef protocol_binary_response_get protocol_binary_response_getkq; - - /** - * Definition of the packet used by the delete command - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_delete; - - /** - * Definition of the packet returned by the delete command - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_delete; - - /** - * Definition of the packet used by the flush command - * See section 4 - * Please note that the expiration field is optional, so remember to see - * check the header.bodysize to see if it is present. - */ - typedef union { - struct { - protocol_binary_request_header header; - struct { - uint32_t expiration; - } body; - } message; - uint8_t bytes[sizeof(protocol_binary_request_header) + 4]; - } protocol_binary_request_flush; - - /** - * Definition of the packet returned by the flush command - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_flush; - - /** - * Definition of the packet used by set, add and replace - * See section 4 - */ - typedef union { - struct { - protocol_binary_request_header header; - struct { - uint32_t flags; - uint32_t expiration; - } body; - } message; - uint8_t bytes[sizeof(protocol_binary_request_header) + 8]; - } protocol_binary_request_set; - typedef protocol_binary_request_set protocol_binary_request_add; - typedef protocol_binary_request_set protocol_binary_request_replace; - - /** - * Definition of the packet returned by set, add and replace - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_set; - typedef protocol_binary_response_no_extras protocol_binary_response_add; - typedef protocol_binary_response_no_extras protocol_binary_response_replace; - - /** - * Definition of the noop packet - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_noop; - - /** - * Definition of the packet returned by the noop command - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_noop; - - /** - * Definition of the structure used by the increment and decrement - * command. - * See section 4 - */ - typedef union { - struct { - protocol_binary_request_header header; - struct { - uint64_t delta; - uint64_t initial; - uint32_t expiration; - } body; - } message; - uint8_t bytes[sizeof(protocol_binary_request_header) + 20]; - } protocol_binary_request_incr; - typedef protocol_binary_request_incr protocol_binary_request_decr; - - /** - * Definition of the response from an incr or decr command - * command. - * See section 4 - */ - typedef union { - struct { - protocol_binary_response_header header; - struct { - uint64_t value; - } body; - } message; - uint8_t bytes[sizeof(protocol_binary_response_header) + 8]; - } protocol_binary_response_incr; - typedef protocol_binary_response_incr protocol_binary_response_decr; - - /** - * Definition of the quit - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_quit; - - /** - * Definition of the packet returned by the quit command - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_quit; - - /** - * Definition of the packet used by append and prepend command - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_append; - typedef protocol_binary_request_no_extras protocol_binary_request_prepend; - - /** - * Definition of the packet returned from a successful append or prepend - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_append; - typedef protocol_binary_response_no_extras protocol_binary_response_prepend; - - /** - * Definition of the packet used by the version command - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_version; - - /** - * Definition of the packet returned from a successful version command - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_version; - - - /** - * Definition of the packet used by the stats command. - * See section 4 - */ - typedef protocol_binary_request_no_extras protocol_binary_request_stats; - - /** - * Definition of the packet returned from a successful stats command - * See section 4 - */ - typedef protocol_binary_response_no_extras protocol_binary_response_stats; +/** + * Definition of the legal "magic" values used in a packet. + * See section 3.1 Magic byte + */ +typedef enum +{ + PROTOCOL_BINARY_REQ= 0x80, + PROTOCOL_BINARY_RES= 0x81 +} protocol_binary_magic; + +/** + * Definition of the valid response status numbers. + * See section 3.2 Response Status + */ +typedef enum +{ + PROTOCOL_BINARY_RESPONSE_SUCCESS= 0x00, + PROTOCOL_BINARY_RESPONSE_KEY_ENOENT= 0x01, + PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS= 0x02, + PROTOCOL_BINARY_RESPONSE_E2BIG= 0x03, + PROTOCOL_BINARY_RESPONSE_EINVAL= 0x04, + PROTOCOL_BINARY_RESPONSE_NOT_STORED= 0x05, + PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND= 0x81, + PROTOCOL_BINARY_RESPONSE_ENOMEM= 0x82 +} protocol_binary_response_status; + +/** + * Defintion of the different command opcodes. + * See section 3.3 Command Opcodes + */ +typedef enum +{ + PROTOCOL_BINARY_CMD_GET= 0x00, + PROTOCOL_BINARY_CMD_SET= 0x01, + PROTOCOL_BINARY_CMD_ADD= 0x02, + PROTOCOL_BINARY_CMD_REPLACE= 0x03, + PROTOCOL_BINARY_CMD_DELETE= 0x04, + PROTOCOL_BINARY_CMD_INCREMENT= 0x05, + PROTOCOL_BINARY_CMD_DECREMENT= 0x06, + PROTOCOL_BINARY_CMD_QUIT= 0x07, + PROTOCOL_BINARY_CMD_FLUSH= 0x08, + PROTOCOL_BINARY_CMD_GETQ= 0x09, + PROTOCOL_BINARY_CMD_NOOP= 0x0a, + PROTOCOL_BINARY_CMD_VERSION= 0x0b, + PROTOCOL_BINARY_CMD_GETK= 0x0c, + PROTOCOL_BINARY_CMD_GETKQ= 0x0d, + PROTOCOL_BINARY_CMD_APPEND= 0x0e, + PROTOCOL_BINARY_CMD_PREPEND= 0x0f, + PROTOCOL_BINARY_CMD_STAT= 0x10, + PROTOCOL_BINARY_CMD_SETQ= 0x11, + PROTOCOL_BINARY_CMD_ADDQ= 0x12, + PROTOCOL_BINARY_CMD_REPLACEQ= 0x13, + PROTOCOL_BINARY_CMD_DELETEQ= 0x14, + PROTOCOL_BINARY_CMD_INCREMENTQ= 0x15, + PROTOCOL_BINARY_CMD_DECREMENTQ= 0x16, + PROTOCOL_BINARY_CMD_QUITQ= 0x17, + PROTOCOL_BINARY_CMD_FLUSHQ= 0x18, + PROTOCOL_BINARY_CMD_APPENDQ= 0x19, + PROTOCOL_BINARY_CMD_PREPENDQ= 0x1a +} protocol_binary_command; + +/** + * Definition of the data types in the packet + * See section 3.4 Data Types + */ +typedef enum +{ + PROTOCOL_BINARY_RAW_BYTES= 0x00 +} protocol_binary_datatypes; + +/** + * Definition of the header structure for a request packet. + * See section 2 + */ +typedef union +{ + struct + { + uint8_t magic; + uint8_t opcode; + uint16_t keylen; + uint8_t extlen; + uint8_t datatype; + uint16_t reserved; + uint32_t bodylen; + uint32_t opaque; + uint64_t cas; + } request; + uint8_t bytes[24]; +} protocol_binary_request_header; + +/** + * Definition of the header structure for a response packet. + * See section 2 + */ +typedef union +{ + struct + { + uint8_t magic; + uint8_t opcode; + uint16_t keylen; + uint8_t extlen; + uint8_t datatype; + uint16_t status; + uint32_t bodylen; + uint32_t opaque; + uint64_t cas; + } response; + uint8_t bytes[24]; +} protocol_binary_response_header; + +/** + * Definition of a request-packet containing no extras + */ +typedef union +{ + struct + { + protocol_binary_request_header header; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header)]; +} protocol_binary_request_no_extras; + +/** + * Definition of a response-packet containing no extras + */ +typedef union +{ + struct + { + protocol_binary_response_header header; + } message; + uint8_t bytes[sizeof(protocol_binary_response_header)]; +} protocol_binary_response_no_extras; + +/** + * Definition of the packet used by the get, getq, getk and getkq command. + * See section 4 + */ +typedef protocol_binary_request_no_extras protocol_binary_request_get; +typedef protocol_binary_request_no_extras protocol_binary_request_getq; +typedef protocol_binary_request_no_extras protocol_binary_request_getk; +typedef protocol_binary_request_no_extras protocol_binary_request_getkq; + +/** + * Definition of the packet returned from a successful get, getq, getk and + * getkq. + * See section 4 + */ +typedef union +{ + struct + { + protocol_binary_response_header header; + struct + { + uint32_t flags; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_response_header) + 4]; +} protocol_binary_response_get; + +typedef protocol_binary_response_get protocol_binary_response_getq; +typedef protocol_binary_response_get protocol_binary_response_getk; +typedef protocol_binary_response_get protocol_binary_response_getkq; + +/** + * Definition of the packet used by the delete command + * See section 4 + */ +typedef protocol_binary_request_no_extras protocol_binary_request_delete; + +/** + * Definition of the packet returned by the delete command + * See section 4 + */ +typedef protocol_binary_response_no_extras +protocol_binary_response_delete; + +/** + * Definition of the packet used by the flush command + * See section 4 + * Please note that the expiration field is optional, so remember to see + * check the header.bodysize to see if it is present. + */ +typedef union +{ + struct + { + protocol_binary_request_header header; + struct + { + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 4]; +} protocol_binary_request_flush; + +/** + * Definition of the packet returned by the flush command + * See section 4 + */ +typedef protocol_binary_response_no_extras protocol_binary_response_flush; + +/** + * Definition of the packet used by set, add and replace + * See section 4 + */ +typedef union +{ + struct + { + protocol_binary_request_header header; + struct + { + uint32_t flags; + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 8]; +} protocol_binary_request_set; +typedef protocol_binary_request_set protocol_binary_request_add; +typedef protocol_binary_request_set +protocol_binary_request_replace; + +/** + * Definition of the packet returned by set, add and replace + * See section 4 + */ +typedef protocol_binary_response_no_extras protocol_binary_response_set; +typedef protocol_binary_response_no_extras protocol_binary_response_add; +typedef protocol_binary_response_no_extras +protocol_binary_response_replace; + +/** + * Definition of the noop packet + * See section 4 + */ +typedef protocol_binary_request_no_extras protocol_binary_request_noop; + +/** + * Definition of the packet returned by the noop command + * See section 4 + */ +typedef protocol_binary_response_no_extras protocol_binary_response_noop; + +/** + * Definition of the structure used by the increment and decrement + * command. + * See section 4 + */ +typedef union +{ + struct + { + protocol_binary_request_header header; + struct + { + uint64_t delta; + uint64_t initial; + uint32_t expiration; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_request_header) + 20]; +} protocol_binary_request_incr; +typedef protocol_binary_request_incr protocol_binary_request_decr; + +/** + * Definition of the response from an incr or decr command + * command. + * See section 4 + */ +typedef union +{ + struct + { + protocol_binary_response_header header; + struct + { + uint64_t value; + } body; + } message; + uint8_t bytes[sizeof(protocol_binary_response_header) + 8]; +} protocol_binary_response_incr; +typedef protocol_binary_response_incr protocol_binary_response_decr; + +/** + * Definition of the quit + * See section 4 + */ +typedef protocol_binary_request_no_extras protocol_binary_request_quit; + +/** + * Definition of the packet returned by the quit command + * See section 4 + */ +typedef protocol_binary_response_no_extras protocol_binary_response_quit; + +/** + * Definition of the packet used by append and prepend command + * See section 4 + */ +typedef protocol_binary_request_no_extras protocol_binary_request_append; +typedef protocol_binary_request_no_extras +protocol_binary_request_prepend; + +/** + * Definition of the packet returned from a successful append or prepend + * See section 4 + */ +typedef protocol_binary_response_no_extras +protocol_binary_response_append; +typedef protocol_binary_response_no_extras +protocol_binary_response_prepend; + +/** + * Definition of the packet used by the version command + * See section 4 + */ +typedef protocol_binary_request_no_extras +protocol_binary_request_version; + +/** + * Definition of the packet returned from a successful version command + * See section 4 + */ +typedef protocol_binary_response_no_extras +protocol_binary_response_version; + + +/** + * Definition of the packet used by the stats command. + * See section 4 + */ +typedef protocol_binary_request_no_extras protocol_binary_request_stats; + +/** + * Definition of the packet returned from a successful stats command + * See section 4 + */ +typedef protocol_binary_response_no_extras protocol_binary_response_stats; #ifdef __cplusplus } #endif -- 2.30.2