/*
- * memslap - memslap
+ * memslap
*
* (c) Copyright 2009, Schooner Information Technology, Inc.
* All rights reserved.
#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 */
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[]);
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);
/* 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
*
*/
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
*
*
* @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
*/
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 */
#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);
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);
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
*/
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
*/
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
*
*/
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
*/
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
*
* @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
*/
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
*/
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
*/
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
*/
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
*/
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.
*/
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
*/
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
*/
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.
*/
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
*
* @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
*/
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
*/
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
*
* @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.
*/
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
*/
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.
*/
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
*/
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
*/
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
* (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
*/
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
* @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
*/
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
*/
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.
*/
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.
*/
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
*/
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
*/
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.
*/
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.
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*
* @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
*/
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.
*/
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
*/
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
*/
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 */
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 */
};
/**
* 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
*/
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
#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 */
#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 */
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);
*/
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
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
*/
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
*
* @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
*
* @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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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 */
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;
/* 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
}
#define NO_CPP_DEMANGLE
#ifndef NO_CPP_DEMANGLE
-#include <cxxabi.h>
+# include <cxxabi.h>
#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 */
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
*/
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
*/
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
/* 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
*/
#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);
*/
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
*/
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
*/
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
*/
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
*/
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
* @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 */
#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
}
#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
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);
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)
*
*/
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
*
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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.
*/
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.
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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.
*/
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 */
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;
/* 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
*/
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
*/
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
*/
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
*/
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.
*/
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
*/
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.
*/
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 */
#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
* (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.
*
{
#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