From: Brian Aker Date: Tue, 5 Apr 2011 06:27:24 +0000 (-0700) Subject: Merge in all current libmemcached work, plus restore older, working, X-Git-Tag: 0.51~18 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=4fe35ea1372eda035618c6e961f421187d3ae837;hp=de46e62fe493ce152e1804feec0d19d5d0cfaa9f;p=awesomized%2Flibmemcached Merge in all current libmemcached work, plus restore older, working, memslap. --- diff --git a/.bzrignore b/.bzrignore index 06c56d69..1fe320b9 100644 --- a/.bzrignore +++ b/.bzrignore @@ -20,6 +20,7 @@ Makefile.in TAGS aclocal.m4 autom4te.cache +clients/memaslap clients/memcapable clients/memcat clients/memcp @@ -172,6 +173,7 @@ memflush.pop memrm.pop memslap.pop memstat.pop +out patch patch2 stamp-h1 @@ -181,6 +183,7 @@ support/libmemcached-fc.spec support/libmemcached.pc support/libmemcached.spec tests/atomsmasher +tests/hash_plus tests/hashplus tests/memplus tests/output.cmp diff --git a/ChangeLog b/ChangeLog index 9c0bea9c..828dae77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ * Fix calls to auto methods so that if value is not passed in nothing bad happens. * New parser calls for generating memcached_st objects. * New error system. + * A behavior change has been now made that if you specify a weight for any + server, we enable the weight flag and do weight balancing. 0.48 Tue Mar 15 23:05:18 PDT 2011 * Fix memory leak in server parse. diff --git a/Makefile.am b/Makefile.am index 7a09b51f..b9fec57e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,11 +40,12 @@ endif test-docs: (cd docs && $(MAKE) test-docs) + +include libtest/include.am + include libmemcached/include.am include clients/include.am -include libtest/include.am include libhashkit/include.am -include unittests/include.am include tests/include.am include example/include.am include support/include.am diff --git a/clients/include.am b/clients/include.am index f7503754..07d49a70 100644 --- a/clients/include.am +++ b/clients/include.am @@ -20,11 +20,12 @@ bin_PROGRAMS+= \ clients/memflush \ clients/memparse \ clients/memrm \ + clients/memslap \ clients/memstat if HAVE_LIBEVENT if !BUILD_WIN32_WRAPPERS - bin_PROGRAMS+= clients/memslap + bin_PROGRAMS+= clients/memaslap endif endif @@ -72,15 +73,18 @@ clients_memflush_LDADD= $(CLIENTS_LDADDS) clients_memerror_SOURCES= clients/memerror.c clients_memerror_LDADD= $(CLIENTS_LDADDS) -clients_memslap_SOURCES= \ - clients/memslap.c \ +clients_memslap_SOURCES = clients/memslap.c +clients_memslap_LDADD = $(PTHREAD_LIBS) clients/libgenexec.la $(CLIENTS_LDADDS) + +clients_memaslap_SOURCES= \ + clients/memaslap.c \ clients/ms_conn.c \ clients/ms_setting.c \ clients/ms_sigsegv.c \ clients/ms_stats.c \ clients/ms_task.c \ clients/ms_thread.c -clients_memslap_LDADD= $(LTLIBEVENT) clients/libgenexec.la $(CLIENTS_LDADDS) +clients_memaslap_LDADD= $(LTLIBEVENT) clients/libgenexec.la $(CLIENTS_LDADDS) clients_memcapable_SOURCES= clients/memcapable.c clients_memcapable_LDADD= $(CLIENTS_LDADDS) @@ -94,19 +98,19 @@ test-start-server: clients/memcat --servers=localhost /etc/services clients/memrm --servers=localhost /etc/services clients/memstat --servers=localhost - clients/memslap --servers=localhost - clients/memslap --servers=localhost --concurrency=10 - clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 - clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 - clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=get - clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set - clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set --non-blocking + clients/memaslap --servers=localhost + clients/memaslap --servers=localhost --concurrency=10 + clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 + clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 + clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=get + clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set + clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set --non-blocking client-valgrind: - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=get - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set - libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set --non-blocking + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost --concurrency=10 + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=get + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set + libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memaslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set --non-blocking diff --git a/clients/memaslap.c b/clients/memaslap.c new file mode 100644 index 00000000..37e93ec3 --- /dev/null +++ b/clients/memaslap.c @@ -0,0 +1,908 @@ +/* + * memslap + * + * (c) Copyright 2009, Schooner Information Technology, Inc. + * All rights reserved. + * http://www.schoonerinfotech.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file for full text. + * + * Authors: + * Brian Aker + * Mingqiang Zhuang + * + */ +#include "config.h" + +#include +#include +#include +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + + +#include "ms_sigsegv.h" +#include "ms_setting.h" +#include "ms_thread.h" + +#define PROGRAM_NAME "memslap" +#define PROGRAM_DESCRIPTION \ + "Generates workload against memcached servers." + +#ifdef __sun + /* For some odd reason the option struct on solaris defines the argument + * as char* and not const char* + */ +#define OPTIONSTRING char* +#else +#define OPTIONSTRING const char* +#endif + +/* options */ +static struct option long_options[]= +{ + { (OPTIONSTRING)"servers", required_argument, NULL, + OPT_SERVERS }, + { (OPTIONSTRING)"threads", required_argument, NULL, + OPT_THREAD_NUMBER }, + { (OPTIONSTRING)"concurrency", required_argument, NULL, + OPT_CONCURRENCY }, + { (OPTIONSTRING)"conn_sock", required_argument, NULL, + OPT_SOCK_PER_CONN }, + { (OPTIONSTRING)"execute_number", required_argument, NULL, + OPT_EXECUTE_NUMBER }, + { (OPTIONSTRING)"time", required_argument, NULL, + OPT_TIME }, + { (OPTIONSTRING)"cfg_cmd", required_argument, NULL, + OPT_CONFIG_CMD }, + { (OPTIONSTRING)"win_size", required_argument, NULL, + OPT_WINDOW_SIZE }, + { (OPTIONSTRING)"fixed_size", required_argument, NULL, + OPT_FIXED_LTH }, + { (OPTIONSTRING)"verify", required_argument, NULL, + OPT_VERIFY }, + { (OPTIONSTRING)"division", required_argument, NULL, + OPT_GETS_DIVISION }, + { (OPTIONSTRING)"stat_freq", required_argument, NULL, + OPT_STAT_FREQ }, + { (OPTIONSTRING)"exp_verify", required_argument, NULL, + OPT_EXPIRE }, + { (OPTIONSTRING)"overwrite", required_argument, NULL, + OPT_OVERWRITE }, + { (OPTIONSTRING)"reconnect", no_argument, NULL, + OPT_RECONNECT }, + { (OPTIONSTRING)"udp", no_argument, NULL, + OPT_UDP }, + { (OPTIONSTRING)"facebook", no_argument, NULL, + OPT_FACEBOOK_TEST }, + { (OPTIONSTRING)"binary", no_argument, NULL, + OPT_BINARY_PROTOCOL }, + { (OPTIONSTRING)"tps", required_argument, NULL, + OPT_TPS }, + { (OPTIONSTRING)"rep_write", required_argument, NULL, + OPT_REP_WRITE_SRV }, + { (OPTIONSTRING)"verbose", no_argument, NULL, + OPT_VERBOSE }, + { (OPTIONSTRING)"help", no_argument, NULL, + OPT_HELP }, + { (OPTIONSTRING)"version", no_argument, NULL, + OPT_VERSION }, + { 0, 0, 0, 0 }, +}; + +/* Prototypes */ +static void ms_sync_lock_init(void); +static void ms_sync_lock_destroy(void); +static void ms_global_struct_init(void); +static void ms_global_struct_destroy(void); +static void ms_version_command(const char *command_name); +static const char *ms_lookup_help(ms_options_t option); +static int64_t ms_parse_time(void); +static int64_t ms_parse_size(void); +static void ms_options_parse(int argc, char *argv[]); +static int ms_check_para(void); +static void ms_statistic_init(void); +static void ms_stats_init(void); +static void ms_print_statistics(int in_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.warmup_lock.count = 0; + pthread_mutex_init(&ms_global.warmup_lock.lock, NULL); + pthread_cond_init(&ms_global.warmup_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 */ + + +/* 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.warmup_lock.lock); + pthread_cond_destroy(&ms_global.warmup_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); + + if (ms_setting.stat_freq > 0) + { + pthread_mutex_destroy(&ms_statistic.stat_mutex); + } +} /* ms_sync_lock_destroy */ + + +/* initialize the global structure */ +static void ms_global_struct_init() +{ + 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(); +} + + +/** + * output the version information + * + * @param command_name, the string of this process + */ +static void ms_version_command(const char *command_name) +{ + printf("%s v%u.%u\n", command_name, 1U, 0U); + exit(0); +} + + +/** + * get the description of the option + * + * @param option, option of command line + * + * @return char*, description of the command 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 */ +} /* ms_lookup_help */ + + +/** + * output the help information + * + * @param command_name, the string of this process + * @param description, description of this process + * @param long_options, global options array + */ +void ms_help_command(const char *command_name, const char *description) +{ + char *help_message= NULL; + + printf("%s v%u.%u\n", command_name, 1U, 0U); + 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"); + + exit(0); +} /* ms_help_command */ + + +/* 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; + } /* switch */ + + return ret; +} /* ms_parse_time */ + + +/* 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; + } /* switch */ + + return ret; +} /* ms_parse_size */ + + +/* 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= (uint32_t)strtoul(optarg, (char **) NULL, 10); + 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= (int)strtol(optarg, (char **) NULL, 10); + 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= (uint32_t)strtoul(optarg, (char **) NULL, 10); + 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)strtoull(optarg, (char **) NULL, 10); + 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= (int)strtol(optarg, (char **) NULL, 10); + 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 " + "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 " + "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= (uint32_t)strtoul(optarg, (char **) NULL, 10); + 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= (uint32_t)strtoul(optarg, (char **) NULL, 10); + 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) + { + char *temp; + + if ((temp= getenv("MEMCACHED_SERVERS"))) + { + ms_setting.srv_str= strdup(temp); + } + else + { + fprintf(stderr, "No Servers provided\n\n"); + return -1; + } + } + + if (ms_setting.nconns % (uint32_t)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; + } + + return EXIT_SUCCESS; +} /* ms_check_para */ + + +/* 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"); +} /* 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(); + } +} /* 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); +} /* ms_print_statistics */ + + +/* 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+= snprintf(pos, + sizeof(buf), "cmd_get: %lu\n", + (unsigned long) ms_stats.cmd_get); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "cmd_set: %lu\n", + (unsigned long) ms_stats.cmd_set); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "get_misses: %lu\n", + (unsigned long) ms_stats.get_misses); + + if (ms_setting.verify_percent > 0) + { + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "verify_misses: %lu\n", + (unsigned long) ms_stats.vef_miss); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "verify_failed: %lu\n", + (unsigned long) ms_stats.vef_failed); + } + + if (ms_setting.exp_ver_per > 0) + { + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "expired_get: %lu\n", + (unsigned long) ms_stats.exp_get); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "unexpired_unget: %lu\n", + (unsigned long) ms_stats.unexp_unget); + } + + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "written_bytes: %lu\n", + (unsigned long) ms_stats.bytes_written); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "read_bytes: %lu\n", + (unsigned long) ms_stats.bytes_read); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "object_bytes: %lu\n", + (unsigned long) ms_stats.obj_bytes); + + if (ms_setting.udp || ms_setting.facebook_test) + { + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "packet_disorder: %lu\n", + (unsigned long) ms_stats.pkt_disorder); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "packet_drop: %lu\n", + (unsigned long)ms_stats.pkt_drop); + pos+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "udp_timeout: %lu\n", + (unsigned 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+= snprintf(pos, + sizeof(buf) - (size_t)(pos -buf), + "\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)); + assert(pos <= buf); + + fprintf(stdout, "%s", buf); + fflush(stdout); +} /* ms_print_memslap_stats */ + + +/* 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; + + /* Wait all the threads complete initialization. */ + pthread_mutex_lock(&ms_global.init_lock.lock); + while (ms_global.init_lock.count < ms_setting.nthreads) + { + pthread_cond_wait(&ms_global.init_lock.cond, + &ms_global.init_lock.lock); + } + pthread_mutex_unlock(&ms_global.init_lock.lock); + + /* 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.warmup_lock.lock); + while (ms_global.warmup_lock.count < ms_setting.nconns) + { + pthread_cond_wait(&ms_global.warmup_lock.cond, &ms_global.warmup_lock.lock); + } + pthread_mutex_unlock(&ms_global.warmup_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_stats.active_conns <= INT_MAX)) + { + 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); + } + + ms_print_memslap_stats(&start_time, &end_time); +} /* ms_monitor_slap_mode */ + + +/* 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 EXIT_SUCCESS; +} /* main */ diff --git a/clients/memslap.c b/clients/memslap.c index 37e93ec3..0d77fd6e 100644 --- a/clients/memslap.c +++ b/clients/memslap.c @@ -1,908 +1,495 @@ -/* - * memslap +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library * - * (c) Copyright 2009, Schooner Information Technology, Inc. - * All rights reserved. - * http://www.schoonerinfotech.com/ + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-2009 Brian Aker All rights reserved. * - * Use and distribution licensed under the BSD license. See - * the COPYING file for full text. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: * - * Authors: - * Brian Aker - * Mingqiang Zhuang + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -#include "config.h" + +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include -#include -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - - -#include "ms_sigsegv.h" -#include "ms_setting.h" -#include "ms_thread.h" - -#define PROGRAM_NAME "memslap" -#define PROGRAM_DESCRIPTION \ - "Generates workload against memcached servers." - -#ifdef __sun - /* For some odd reason the option struct on solaris defines the argument - * as char* and not const char* - */ -#define OPTIONSTRING char* -#else -#define OPTIONSTRING const char* -#endif +#include +#include + +#include + +#include "client_options.h" +#include "utilities.h" +#include "generator.h" +#include "execute.h" + +#define DEFAULT_INITIAL_LOAD 10000 +#define DEFAULT_EXECUTE_NUMBER 10000 +#define DEFAULT_CONCURRENCY 1 + +#define PROGRAM_NAME "memslap" +#define PROGRAM_DESCRIPTION "Generates a load against a memcached custer of servers." + +/* Global Thread counter */ +volatile unsigned int thread_counter; +pthread_mutex_t counter_mutex; +pthread_cond_t count_threshhold; +volatile unsigned int master_wakeup; +pthread_mutex_t sleeper_mutex; +pthread_cond_t sleep_threshhold; + +void *run_task(void *p); + +/* Types */ +typedef struct conclusions_st conclusions_st; +typedef struct thread_context_st thread_context_st; +typedef enum { + SET_TEST, + GET_TEST, + MGET_TEST +} test_type; + +struct thread_context_st { + unsigned int key_count; + pairs_st *initial_pairs; + unsigned int initial_number; + pairs_st *execute_pairs; + unsigned int execute_number; + char **keys; + size_t *key_lengths; + test_type test; + memcached_st *memc; +}; -/* options */ -static struct option long_options[]= -{ - { (OPTIONSTRING)"servers", required_argument, NULL, - OPT_SERVERS }, - { (OPTIONSTRING)"threads", required_argument, NULL, - OPT_THREAD_NUMBER }, - { (OPTIONSTRING)"concurrency", required_argument, NULL, - OPT_CONCURRENCY }, - { (OPTIONSTRING)"conn_sock", required_argument, NULL, - OPT_SOCK_PER_CONN }, - { (OPTIONSTRING)"execute_number", required_argument, NULL, - OPT_EXECUTE_NUMBER }, - { (OPTIONSTRING)"time", required_argument, NULL, - OPT_TIME }, - { (OPTIONSTRING)"cfg_cmd", required_argument, NULL, - OPT_CONFIG_CMD }, - { (OPTIONSTRING)"win_size", required_argument, NULL, - OPT_WINDOW_SIZE }, - { (OPTIONSTRING)"fixed_size", required_argument, NULL, - OPT_FIXED_LTH }, - { (OPTIONSTRING)"verify", required_argument, NULL, - OPT_VERIFY }, - { (OPTIONSTRING)"division", required_argument, NULL, - OPT_GETS_DIVISION }, - { (OPTIONSTRING)"stat_freq", required_argument, NULL, - OPT_STAT_FREQ }, - { (OPTIONSTRING)"exp_verify", required_argument, NULL, - OPT_EXPIRE }, - { (OPTIONSTRING)"overwrite", required_argument, NULL, - OPT_OVERWRITE }, - { (OPTIONSTRING)"reconnect", no_argument, NULL, - OPT_RECONNECT }, - { (OPTIONSTRING)"udp", no_argument, NULL, - OPT_UDP }, - { (OPTIONSTRING)"facebook", no_argument, NULL, - OPT_FACEBOOK_TEST }, - { (OPTIONSTRING)"binary", no_argument, NULL, - OPT_BINARY_PROTOCOL }, - { (OPTIONSTRING)"tps", required_argument, NULL, - OPT_TPS }, - { (OPTIONSTRING)"rep_write", required_argument, NULL, - OPT_REP_WRITE_SRV }, - { (OPTIONSTRING)"verbose", no_argument, NULL, - OPT_VERBOSE }, - { (OPTIONSTRING)"help", no_argument, NULL, - OPT_HELP }, - { (OPTIONSTRING)"version", no_argument, NULL, - OPT_VERSION }, - { 0, 0, 0, 0 }, +struct conclusions_st { + long int load_time; + long int read_time; + unsigned int rows_loaded; + unsigned int rows_read; }; /* Prototypes */ -static void ms_sync_lock_init(void); -static void ms_sync_lock_destroy(void); -static void ms_global_struct_init(void); -static void ms_global_struct_destroy(void); -static void ms_version_command(const char *command_name); -static const char *ms_lookup_help(ms_options_t option); -static int64_t ms_parse_time(void); -static int64_t ms_parse_size(void); -static void ms_options_parse(int argc, char *argv[]); -static int ms_check_para(void); -static void ms_statistic_init(void); -static void ms_stats_init(void); -static void ms_print_statistics(int in_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.warmup_lock.count = 0; - pthread_mutex_init(&ms_global.warmup_lock.lock, NULL); - pthread_cond_init(&ms_global.warmup_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 */ +void options_parse(int argc, char *argv[]); +void conclusions_print(conclusions_st *conclusion); +void scheduler(memcached_server_st *servers, conclusions_st *conclusion); +pairs_st *load_create_data(memcached_st *memc, unsigned int number_of, + unsigned int *actual_loaded); +void flush_all(memcached_st *memc); + +static int opt_binary= 0; +static int opt_verbose= 0; +static int opt_flush= 0; +static int opt_non_blocking_io= 0; +static int opt_tcp_nodelay= 0; +static unsigned int opt_execute_number= 0; +static unsigned int opt_createial_load= 0; +static unsigned int opt_concurrency= 0; +static int opt_displayflag= 0; +static char *opt_servers= NULL; +static int opt_udp_io= 0; +test_type opt_test= SET_TEST; - -/* destroy the global locks */ -static void ms_sync_lock_destroy() +int main(int argc, char *argv[]) { - pthread_mutex_destroy(&ms_global.init_lock.lock); - pthread_cond_destroy(&ms_global.init_lock.cond); + conclusions_st conclusion; + memcached_server_st *servers; - pthread_mutex_destroy(&ms_global.warmup_lock.lock); - pthread_cond_destroy(&ms_global.warmup_lock.cond); + memset(&conclusion, 0, sizeof(conclusions_st)); - 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); + srandom((unsigned int)time(NULL)); + options_parse(argc, argv); - if (ms_setting.stat_freq > 0) + if (!opt_servers) { - pthread_mutex_destroy(&ms_statistic.stat_mutex); + char *temp; + + if ((temp= getenv("MEMCACHED_SERVERS"))) + opt_servers= strdup(temp); + else + { + fprintf(stderr, "No Servers provided\n"); + exit(1); + } } -} /* ms_sync_lock_destroy */ + servers= memcached_servers_parse(opt_servers); -/* initialize the global structure */ -static void ms_global_struct_init() -{ - ms_sync_lock_init(); - ms_global.finish_warmup= false; - ms_global.time_out= false; -} + pthread_mutex_init(&counter_mutex, NULL); + pthread_cond_init(&count_threshhold, NULL); + pthread_mutex_init(&sleeper_mutex, NULL); + pthread_cond_init(&sleep_threshhold, NULL); + scheduler(servers, &conclusion); -/* destroy the global structure */ -static void ms_global_struct_destroy() -{ - ms_sync_lock_destroy(); -} + free(opt_servers); + (void)pthread_mutex_destroy(&counter_mutex); + (void)pthread_cond_destroy(&count_threshhold); + (void)pthread_mutex_destroy(&sleeper_mutex); + (void)pthread_cond_destroy(&sleep_threshhold); + conclusions_print(&conclusion); + memcached_server_list_free(servers); -/** - * output the version information - * - * @param command_name, the string of this process - */ -static void ms_version_command(const char *command_name) -{ - printf("%s v%u.%u\n", command_name, 1U, 0U); - exit(0); + return 0; } - -/** - * get the description of the option - * - * @param option, option of command line - * - * @return char*, description of the command option - */ -static const char *ms_lookup_help(ms_options_t option) +void scheduler(memcached_server_st *servers, conclusions_st *conclusion) { - 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."; + unsigned int actual_loaded= 0; /* Fix warning */ + memcached_st *memc; - 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."; + struct timeval start_time, end_time; + pthread_t mainthread; /* Thread descriptor */ + pthread_attr_t attr; /* Thread attributes */ + pairs_st *pairs= NULL; - case OPT_TPS: - return "Expected throughput, suffix: K, e.g.: --tps=10k."; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, + PTHREAD_CREATE_DETACHED); - case OPT_REP_WRITE_SRV: - return "The first nth servers can write data, e.g.: --rep_write=2."; + memc= memcached_create(NULL); - default: - return "Forgot to document this option :)"; - } /* switch */ -} /* ms_lookup_help */ + /* We need to set udp behavior before adding servers to the client */ + if (opt_udp_io) + { + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, + (uint64_t)opt_udp_io); + for (uint32_t x= 0; x < memcached_server_list_count(servers); x++ ) + { + servers[x].type= MEMCACHED_CONNECTION_UDP; + } + } + memcached_server_push(memc, servers); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, + (uint64_t)opt_binary); -/** - * output the help information - * - * @param command_name, the string of this process - * @param description, description of this process - * @param long_options, global options array - */ -void ms_help_command(const char *command_name, const char *description) -{ - char *help_message= NULL; + if (opt_flush) + flush_all(memc); + if (opt_createial_load) + pairs= load_create_data(memc, opt_createial_load, &actual_loaded); - printf("%s v%u.%u\n", command_name, 1U, 0U); - printf(" %s\n\n", description); - printf( - "Usage:\n" - " memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n" - "Options:\n"); + char **keys= calloc(actual_loaded, sizeof(char*)); + size_t *key_lengths= calloc(actual_loaded, sizeof(size_t)); - for (int x= 0; long_options[x].name; x++) + if (keys == NULL || key_lengths == NULL) { - 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) + free(keys); + free(key_lengths); + keys= NULL; + key_lengths= NULL; + } + else + { + for (uint32_t x= 0; x < actual_loaded; ++x) { - printf(" %s\n", help_message); + keys[x]= pairs[x].key; + key_lengths[x]= pairs[x].key_length; } } - 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 */ - + /* We set this after we have loaded */ + { + if (opt_non_blocking_io) + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); + if (opt_tcp_nodelay) + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); + } -/* used to parse the time string */ -static int64_t ms_parse_time() -{ - int64_t ret= 0; - char unit= optarg[strlen(optarg) - 1]; + pthread_mutex_lock(&counter_mutex); + thread_counter= 0; - optarg[strlen(optarg) - 1]= '\0'; - ret= atoi(optarg); + pthread_mutex_lock(&sleeper_mutex); + master_wakeup= 1; + pthread_mutex_unlock(&sleeper_mutex); - switch (unit) + for (uint32_t x= 0; x < opt_concurrency; x++) { - case 'd': - case 'D': - ret*= 24; - - case 'h': - case 'H': - ret*= 60; + thread_context_st *context; + context= (thread_context_st *)calloc(1, sizeof(thread_context_st)); - case 'm': - case 'M': - ret*= 60; + context->memc= memcached_clone(NULL, memc); + context->test= opt_test; - case 's': - case 'S': - break; + context->initial_pairs= pairs; + context->initial_number= actual_loaded; + context->keys= keys; + context->key_lengths= key_lengths; - default: - ret= -1; - break; - } /* switch */ + if (opt_test == SET_TEST) + { + context->execute_pairs= pairs_generate(opt_execute_number, 400); + context->execute_number= opt_execute_number; + } - return ret; -} /* ms_parse_time */ + /* now you create the thread */ + if (pthread_create(&mainthread, &attr, run_task, + (void *)context) != 0) + { + fprintf(stderr,"Could not create thread\n"); + exit(1); + } + thread_counter++; + } + pthread_mutex_unlock(&counter_mutex); + pthread_attr_destroy(&attr); + + pthread_mutex_lock(&sleeper_mutex); + master_wakeup= 0; + pthread_mutex_unlock(&sleeper_mutex); + pthread_cond_broadcast(&sleep_threshhold); + + gettimeofday(&start_time, NULL); + /* + We loop until we know that all children have cleaned up. + */ + pthread_mutex_lock(&counter_mutex); + while (thread_counter) + pthread_cond_wait(&count_threshhold, &counter_mutex); + pthread_mutex_unlock(&counter_mutex); + + gettimeofday(&end_time, NULL); + + conclusion->load_time= timedif(end_time, start_time); + conclusion->read_time= timedif(end_time, start_time); + free(keys); + free(key_lengths); + pairs_free(pairs); + memcached_free(memc); +} -/* used to parse the size string */ -static int64_t ms_parse_size() +void options_parse(int argc, char *argv[]) { - int64_t ret= -1; - char unit= optarg[strlen(optarg) - 1]; - - optarg[strlen(optarg) - 1]= '\0'; - ret= strtoll(optarg, (char **)NULL, 10); - - switch (unit) + memcached_programs_help_st help_options[]= { - 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 */ + {0}, + }; + static struct option long_options[]= + { + {(OPTIONSTRING)"concurrency", required_argument, NULL, OPT_SLAP_CONCURRENCY}, + {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG}, + {(OPTIONSTRING)"execute-number", required_argument, NULL, OPT_SLAP_EXECUTE_NUMBER}, + {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG}, + {(OPTIONSTRING)"flush", no_argument, &opt_flush, OPT_FLUSH}, + {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP}, + {(OPTIONSTRING)"initial-load", required_argument, NULL, OPT_SLAP_INITIAL_LOAD}, /* Number to load initially */ + {(OPTIONSTRING)"non-blocking", no_argument, &opt_non_blocking_io, OPT_SLAP_NON_BLOCK}, + {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS}, + {(OPTIONSTRING)"tcp-nodelay", no_argument, &opt_tcp_nodelay, OPT_SLAP_TCP_NODELAY}, + {(OPTIONSTRING)"test", required_argument, NULL, OPT_SLAP_TEST}, + {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE}, + {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION}, + {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY}, + {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP}, + {0, 0, 0, 0}, + }; -/* 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) + while (1) { + option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index); + if (option_rv == -1) break; 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= (uint32_t)strtoul(optarg, (char **) NULL, 10); - 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= (int)strtol(optarg, (char **) NULL, 10); - 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= (uint32_t)strtoul(optarg, (char **) NULL, 10); - 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)strtoull(optarg, (char **) NULL, 10); - 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)) + case OPT_UDP: + if (opt_test == GET_TEST) { - fprintf(stderr, "Data verification rate must be " - "greater than 0 and less than 1.0. :-)\n"); + fprintf(stderr, "You can not run a get test in UDP mode. UDP mode " + "does not currently support get ops.\n"); exit(1); } + opt_udp_io= 1; break; - - case OPT_GETS_DIVISION: /* --division or -d */ - ms_setting.mult_key_num= (int)strtol(optarg, (char **) NULL, 10); - if (ms_setting.mult_key_num <= 0) - { - fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n"); - exit(1); - } + case OPT_BINARY: + opt_binary = 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); - } + case OPT_VERBOSE: /* --verbose or -v */ + opt_verbose = OPT_VERBOSE; break; - - case OPT_CONFIG_CMD: /* --cfg_cmd or -F */ - ms_setting.cfg_file= strdup(optarg); + case OPT_DEBUG: /* --debug or -d */ + opt_verbose = OPT_DEBUG; 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); - } + case OPT_VERSION: /* --version or -V */ + version_command(PROGRAM_NAME); break; - - case OPT_UDP: /* --udp or -U*/ - ms_setting.udp= true; + case OPT_HELP: /* --help or -h */ + help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options); 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); - } + case OPT_SERVERS: /* --servers or -s */ + opt_servers= strdup(optarg); 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)) + case OPT_SLAP_TEST: + if (!strcmp(optarg, "get")) { - fprintf(stderr, "Objects overwrite rate must be " - "greater than 0 and less than 1.0. :-)\n"); - exit(1); + if (opt_udp_io == 1) + { + fprintf(stderr, "You can not run a get test in UDP mode. UDP mode " + "does not currently support get ops.\n"); + exit(1); + } + opt_test= GET_TEST ; } - break; - - case OPT_STAT_FREQ: /* --stat_freq or -S */ - ms_setting.stat_freq= (int)ms_parse_time(); - if (ms_setting.stat_freq == -1) + else if (!strcmp(optarg, "set")) + opt_test= SET_TEST; + else if (!strcmp(optarg, "mget")) { - 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); + opt_test= MGET_TEST; } - - if (ms_setting.stat_freq == 0) + else { - fprintf(stderr, "The frequency of dumping statistic information " - "can not be 0. :-)\n"); + fprintf(stderr, "Your test, %s, is not a known test\n", optarg); exit(1); } break; - - case OPT_SOCK_PER_CONN: /* --conn_sock or -n */ - ms_setting.sock_per_conn= (uint32_t)strtoul(optarg, (char **) NULL, 10); - 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; + case OPT_SLAP_CONCURRENCY: + opt_concurrency= (unsigned int)strtoul(optarg, (char **)NULL, 10); break; - - case OPT_BINARY_PROTOCOL: /* --binary or -B */ - ms_setting.binary_prot= true; + case OPT_SLAP_EXECUTE_NUMBER: + opt_execute_number= (unsigned int)strtoul(optarg, (char **)NULL, 10); 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); - } + case OPT_SLAP_INITIAL_LOAD: + opt_createial_load= (unsigned int)strtoul(optarg, (char **)NULL, 10); break; - - case OPT_REP_WRITE_SRV: /* --rep_write or -p */ - ms_setting.rep_write_srv= (uint32_t)strtoul(optarg, (char **) NULL, 10); - 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) - { - char *temp; - - if ((temp= getenv("MEMCACHED_SERVERS"))) - { - ms_setting.srv_str= strdup(temp); - } - else - { - fprintf(stderr, "No Servers provided\n\n"); - return -1; } } - if (ms_setting.nconns % (uint32_t)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; - } - - return EXIT_SUCCESS; -} /* ms_check_para */ - - -/* 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"); -} /* ms_statistic_init */ - + if ((opt_test == GET_TEST || opt_test == MGET_TEST) && opt_createial_load == 0) + opt_createial_load= DEFAULT_INITIAL_LOAD; -/* 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(); - } -} /* ms_stats_init */ + if (opt_execute_number == 0) + opt_execute_number= DEFAULT_EXECUTE_NUMBER; + if (opt_concurrency == 0) + opt_concurrency= DEFAULT_CONCURRENCY; +} -/* use to output the statistic */ -static void ms_print_statistics(int in_time) +void conclusions_print(conclusions_st *conclusion) { - 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); -} /* ms_print_statistics */ - + printf("\tThreads connecting to servers %u\n", opt_concurrency); +#ifdef NOT_FINISHED + printf("\tLoaded %u rows\n", conclusion->rows_loaded); + printf("\tRead %u rows\n", conclusion->rows_read); +#endif + if (opt_test == SET_TEST) + printf("\tTook %ld.%03ld seconds to load data\n", conclusion->load_time / 1000, + conclusion->load_time % 1000); + else + printf("\tTook %ld.%03ld seconds to read data\n", conclusion->read_time / 1000, + conclusion->read_time % 1000); +} -/* used to print the states of memslap */ -static void ms_print_memslap_stats(struct timeval *start_time, - struct timeval *end_time) +void *run_task(void *p) { - char buf[1024]; - char *pos= buf; - - pos+= snprintf(pos, - sizeof(buf), "cmd_get: %lu\n", - (unsigned long) ms_stats.cmd_get); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "cmd_set: %lu\n", - (unsigned long) ms_stats.cmd_set); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "get_misses: %lu\n", - (unsigned long) ms_stats.get_misses); - - if (ms_setting.verify_percent > 0) - { - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "verify_misses: %lu\n", - (unsigned long) ms_stats.vef_miss); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "verify_failed: %lu\n", - (unsigned long) ms_stats.vef_failed); - } - - if (ms_setting.exp_ver_per > 0) - { - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "expired_get: %lu\n", - (unsigned long) ms_stats.exp_get); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "unexpired_unget: %lu\n", - (unsigned long) ms_stats.unexp_unget); - } + thread_context_st *context= (thread_context_st *)p; + memcached_st *memc; - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "written_bytes: %lu\n", - (unsigned long) ms_stats.bytes_written); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "read_bytes: %lu\n", - (unsigned long) ms_stats.bytes_read); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "object_bytes: %lu\n", - (unsigned long) ms_stats.obj_bytes); - - if (ms_setting.udp || ms_setting.facebook_test) - { - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "packet_disorder: %lu\n", - (unsigned long) ms_stats.pkt_disorder); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "packet_drop: %lu\n", - (unsigned long)ms_stats.pkt_drop); - pos+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "udp_timeout: %lu\n", - (unsigned 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+= snprintf(pos, - sizeof(buf) - (size_t)(pos -buf), - "\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)); - assert(pos <= buf); - - fprintf(stdout, "%s", buf); - fflush(stdout); -} /* ms_print_memslap_stats */ - - -/* 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; + memc= context->memc; - /* Wait all the threads complete initialization. */ - pthread_mutex_lock(&ms_global.init_lock.lock); - while (ms_global.init_lock.count < ms_setting.nthreads) + pthread_mutex_lock(&sleeper_mutex); + while (master_wakeup) { - pthread_cond_wait(&ms_global.init_lock.cond, - &ms_global.init_lock.lock); + pthread_cond_wait(&sleep_threshhold, &sleeper_mutex); } - pthread_mutex_unlock(&ms_global.init_lock.lock); + pthread_mutex_unlock(&sleeper_mutex); - /* only when there is no set operation it need warm up */ - if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR) + /* Do Stuff */ + switch (context->test) { - /* Wait all the connects complete warm up. */ - pthread_mutex_lock(&ms_global.warmup_lock.lock); - while (ms_global.warmup_lock.count < ms_setting.nconns) - { - pthread_cond_wait(&ms_global.warmup_lock.cond, &ms_global.warmup_lock.lock); - } - pthread_mutex_unlock(&ms_global.warmup_lock.lock); + case SET_TEST: + assert(context->execute_pairs); + execute_set(memc, context->execute_pairs, context->execute_number); + break; + case GET_TEST: + execute_get(memc, context->initial_pairs, context->initial_number); + break; + case MGET_TEST: + execute_mget(memc, (const char*const*)context->keys, context->key_lengths, + context->initial_number); + break; + default: + WATCHPOINT_ASSERT(context->test); + 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++; + memcached_free(memc); - if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0) - && (ms_stats.active_conns >= ms_setting.nconns) - && (ms_stats.active_conns <= INT_MAX)) - { - ms_print_statistics(second); - } + if (context->execute_pairs) + pairs_free(context->execute_pairs); - if (ms_setting.run_time <= second) - { - ms_global.time_out= true; - break; - } + free(context); - /* 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); - } + pthread_mutex_lock(&counter_mutex); + thread_counter--; + pthread_cond_signal(&count_threshhold); + pthread_mutex_unlock(&counter_mutex); - ms_print_memslap_stats(&start_time, &end_time); -} /* ms_monitor_slap_mode */ + return NULL; +} +void flush_all(memcached_st *memc) +{ + memcached_flush(memc, 0); +} -/* the main function */ -int main(int argc, char *argv[]) +pairs_st *load_create_data(memcached_st *memc, unsigned int number_of, + unsigned int *actual_loaded) { - srandom((unsigned int)time(NULL)); - ms_global_struct_init(); + memcached_st *memc_clone; + pairs_st *pairs; - /* 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(); + memc_clone= memcached_clone(NULL, memc); + /* We always used non-blocking IO for load since it is faster */ + memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NO_BLOCK, 0); - /* waiting work thread complete its task */ - ms_monitor_slap_mode(); + pairs= pairs_generate(number_of, 400); + *actual_loaded= execute_set(memc_clone, pairs, number_of); - /* clean up */ - ms_thread_cleanup(); - ms_global_struct_destroy(); - ms_setting_cleanup(); + memcached_free(memc_clone); - return EXIT_SUCCESS; -} /* main */ + return pairs; +} diff --git a/docs/Makefile.am b/docs/Makefile.am index e97ff32a..2d1c2829 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -61,6 +61,7 @@ GENERIC_PAGES= \ memerror.pop \ memflush.pop \ memrm.pop \ + memaslap.pop \ memslap.pop \ memstat.pop BUILT_SOURCES += ${GENERIC_PAGES} @@ -287,6 +288,7 @@ HTML_FILES= \ memerror.html \ memflush.html \ memrm.html \ + memaslap.html \ memslap.html \ memstat.html @@ -328,6 +330,7 @@ POD_FILES= \ memerror.pod \ memflush.pod \ memrm.pod \ + memaslap.pod \ memslap.pod \ memstat.pod EXTRA_DIST+= $(POD_FILES) @@ -418,6 +421,7 @@ man_MANS = \ memerror.1 \ memflush.1 \ memrm.1 \ + memaslap.1 \ memslap.1 \ memstat.1 diff --git a/docs/memaslap.pod b/docs/memaslap.pod new file mode 100644 index 00000000..c5de6f7c --- /dev/null +++ b/docs/memaslap.pod @@ -0,0 +1,1007 @@ +=head1 NAME + +memaslap - Load testing and benchmarking tool for memcached + +=head1 SYNOPSIS + + memaslap [options] + +=head1 DESCRIPTION + +B is a load generation and benchmark tool for memcached(1) +servers. It generates configurable workload such as threads, concurrencies, connections, +run time, overwrite, miss rate, key size, value size, get/set proportion, +expected throughput, and so on. Furthermore, it also supports data +verification, expire-time verification, UDP, binary protocol, facebook test, +replication test, multi-get and reconnection, etc. + +Memslap manages network connections like memcached with +libevent. Each thread of memaslap is bound with a CPU core, all +the threads don't communicate with each other, and there are several socket +connections in each thread. Each connection keeps key size distribution, +value size distribution, and command distribution by itself. + +You can specify servers via the B<--servers> option or via the +environment variable C. + + +=head1 FEATURES + +Memslap is developed to for the following purposes: + +=over + +=item Manages network connections with libevent asynchronously. + +=item Set both TCP and UDP up to use non-blocking IO. + +=item Improves parallelism: higher performance in multi-threads environments. + +=item Improves time efficiency: faster processing speed. + +=item Generates key and value more efficiently; key size distribution and value size distribution are configurable. + +=item Supports get, multi-get, and set commands; command distribution is configurable. + +=item Supports controllable miss rate and overwrite rate. + +=item Supports data and expire-time verification. + +=item Supports dumping statistic information periodically. + +=item Supports thousands of TCP connections. + +=item Supports binary protocol. + +=item Supports facebook test (set with TCP and multi-get with UDP) and replication test. + +=back + +=head1 DETAILS + +=head2 Effective implementation of network. + +For memaslap, both TCP and UDP use non-blocking network IO. All +the network events are managed by libevent as memcached. The network module +of memaslap is similar to memcached. Libevent can ensure +memaslap can handle network very efficiently. + +=head2 Effective implementation of multi-threads and concurrency + +Memslap has the similar implementation of multi-threads to +memcached. Memslap creates one or more self-governed threads; +each thread is bound with one CPU core if the system supports setting CPU +core affinity. + +In addition, each thread has a libevent to manage the events of the network; +each thread has one or more self-governed concurrencies; and each +concurrency has one or more socket connections. All the concurrencies don’t +communicate with each other even though they are in the same thread. + +Memslap can create thousands of socket connections, and each +concurrency has tens of socket connections. Each concurrency randomly or +sequentially selects one socket connection from its socket connection pool +to run, so memaslap can ensure each concurrency handles one +socket connection at any given time. Users can specify the number of +concurrency and socket connections of each concurrency according to their +expected workload. + +=head2 Effective implementation of generating key and value + +In order to improve time efficiency and space efficiency, +memaslap creates a random characters table with 10M characters. All the +suffixes of keys and values are generated from this random characters table. + +Memslap uses the offset in the character table and the length +of the string to identify a string. It can save much memory. +Each key contains two parts, a prefix and a suffix. The prefix is an +uint64_t, 8 bytes. In order to verify the data set before, +memaslap need to ensure each key is unique, so it uses the prefix to identify +a key. The prefix cannot include illegal characters, such as ‘\r’, ‘\n’, +‘\0’ and ‘ ‘. And memaslap has an algorithm to ensure that. + +Memslap doesn’t generate all the objects (key-value pairs) at +the beginning. It only generates enough objects to fill the task window +(default 10K objects) of each concurrency. Each object has the following +basic information, key prefix, key suffix offset in the character table, key +length, value offset in the character table, and value length. + +In the work process, each concurrency sequentially or randomly selects an +object from the window to do set operation or get operation. At the same +time, each concurrency kicks objects out of its window and adds new object +into it. + +=head2 Simple but useful task scheduling + +Memslap uses libevent to schedule all the concurrencies of +threads, and each concurrency schedules tasks based on the local task +window. Memslap assumes that if each concurrency keeps the same +key distribution, value distribution and commands distribution, from +outside, memaslap keeps all the distribution as a whole. +Each task window includes a lot of objects, each object stores its basic +information, such as key, value, expire time, and so on. At any time, all +the objects in the window keep the same and fixed key and value +distribution. If an object is overwritten, the value of the object will be +updated. Memslap verifies the data or expire-time according to +the object information stored in the task window. + +Libevent selects which concurrency to handle based on a specific network +event. Then the concurrency selects which command (get or set) to operate +based on the command distribution. If it needs to kick out an old object and +add a new object, in order to keep the same key and value distribution, the +new object must have the same key length and value length. + +If memcached server has two cache layers (memory and SSD), running +memaslap with different window sizes can get different cache +miss rates. If memaslap adds enough objects into the windows at +the beginning, and the cache of memcached cannot store all the objects +initialized, then memaslap will get some objects from the second +cache layer. It causes the first cache layer to miss. So the user can +specify the window size to get the expected miss rate of the first cache +layer. + +=head2 Useful implementation of multi-servers , UDP, TCP, multi-get and binary protocol + +Because each thread is self-governed, memaslap can assign +different threads to handle different memcached servers. This is just one of +the ways in which memaslap supports multiple servers. The only +limitation is that the number of servers cannot be greater than the number +of threads. The other way to support multiple servers is for replication +test. Each concurrency has one socket connection to each memcached server. +For the implementation, memaslap can set some objects to one +memcached server, and get these objects from the other servers. + +By default, Memslap does single get. If the user specifies +multi-get option, memaslap will collect enough get commands and +pack and send the commands together. + +Memslap supports both the ASCII protocol and binary protocol, +but it runs on the ASCII protocol by default. +Memslap by default runs on the TCP protocol, but it also +supports UDP. Because UDP is unreliable, dropped packages and out-of-order +packages may occur. Memslap creates a memory buffer to handle +these problems. Memslap tries to read all the response data of +one command from the server and reorders the response data. If some packages +get lost, the waiting timeout mechanism can ensure half-baked packages will +be discarded and the next command will be sent. + + +=head1 USAGE + +Below are some usage samples: + +=over 4 + +=item memaslap -s 127.0.0.1:11211 -S 5s + +=item memaslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b + +=item memaslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2 + +=item memaslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k + +=item memaslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40 + +=item memaslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m + +=item memaslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2 + +=back + +The user must specify one server at least to run memaslap. The +rest of the parameters have default values, as shown below: + +Thread number = 1 Concurrency = 16 + +Run time = 600 seconds Configuration file = NULL + +Key size = 64 Value size = 1024 + +Get/set = 9:1 Window size = 10k + +Execute number = 0 Single get = true + +Multi-get = false Number of sockets of each concurrency = 1 + +Reconnect = false Data verification = false + +Expire-time verification = false ASCII protocol = true + +Binary protocol = false Dumping statistic information + +periodically = false + +Overwrite proportion = 0% UDP = false + +TCP = true Limit throughput = false + +Facebook test = false Replication test = false + +=head2 Key size, value size and command distribution. + +All the distributions are read from the configuration file specified by user +with “—cfg_cmd” option. If the user does not specify a configuration file, +memaslap will run with the default distribution (key size = 64, +value size = 1024, get/set = 9:1). For information on how to edit the +configuration file, refer to the “Configuration File” section. + +The minimum key size is 16 bytes; the maximum key size is 250 bytes. The +precision of proportion is 0.001. The proportion of distribution will be +rounded to 3 decimal places. + +The minimum value size is 1 bytes; the maximum value size is 1M bytes. The +precision of proportion is 0.001. The proportion of distribution will be +rounded to 3 decimal places. +Currently, memaslap only supports set and get commands. And it +supports 100% set and 100% get. For 100% get, it will preset some objects to +the server. + +=head2 Multi-thread and concurrency + +The high performance of memaslap benefits from the special +schedule of thread and concurrency. It’s important to specify the proper +number of them. The default number of threads is 1; the default number of +concurrency is 16. The user can use “—threads” and “--concurrency” to +specify these variables. + +If the system supports setting CPU affinity and the number of threads +specified by the user is greater than 1, memaslap will try to +bind each thread to a different CPU core. So if you want to get the best +performance memaslap, it is better to specify the number of +thread equal to the number of CPU cores. The number of threads specified by +the user can also be less or greater than the number of CPU cores. Because +of the limitation of implementation, the number of concurrencies could be +the multiple of the number of threads. + +1. For 8 CPU cores system + +For example: + +--threads=2 --concurrency=128 + +--threads=8 --concurrency=128 + +--threads=8 --concurrency=256 + +--threads=12 --concurrency=144 + +2. For 16 CPU cores system + +For example: + +--threads=8 --concurrency=128 + +--threads=16 --concurrency=256 + +--threads=16 --concurrency=512 + +--threads=24 --concurrency=288 + +The memaslap performs very well, when +used to test the performance of memcached servers. +Most of the time, the bottleneck is the network or +the server. If for some reason the user wants to +limit the performance of memaslap, there +are two ways to do this: + +Decrease the number of threads and concurrencies. +Use the option “--tps” that memaslap +provides to limit the throughput. This option allows +the user to get the expected throughput. For +example, assume that the maximum throughput is 50 +kops/s for a specific configuration, you can specify +the throughput equal to or less than the maximum +throughput using “--tps” option. + +=head2 Window size + +Most of the time, the user does not need to specify the window size. The +default window size is 10k. For Schooner Memcached, the user can specify +different window sizes to get different cache miss rates based on the test +case. Memslap supports cache miss rate between 0% and 100%. +If you use this utility to test the performance of Schooner Memcached, you +can specify a proper window size to get the expected cache miss rate. The +formula for calculating window size is as follows: + +Assume that the key size is 128 bytes, and the value size is 2048 bytes, and +concurrency=128. + +1. Small cache cache_size=1M, 100% cache miss (all data get from SSD). +win_size=10k + +2. cache_size=4G + +(1). cache miss rate 0% + +win_size=8k + +(2). cache miss rate 5% + +win_size=11k + +3. cache_size=16G + +(1). cache miss rate 0% + +win_size=32k + +(2). cache miss + +rate 5% + +win_size=46k + +The formula for calculating window size for cache miss rate 0%: + +cache_size / concurrency / (key_size + value_size) * 0.5 + +The formula for calculating window size for cache miss rate 5%: + +cache_size / concurrency / (key_size + value_size) * 0.7 + +=head2 Verification + +Memslap supports both data verification and expire-time +verification. The user can use "--verify=" or "-v" to specify the proportion +of data verification. In theory, it supports 100% data verification. The +user can use "--exp_verify=" or "-e" to specify the proportion of +expire-time verification. In theory, it supports 100% expire-time +verification. Specify the "--verbose" options to get more detailed error +information. + +For example: --exp_verify=0.01 –verify=0.1 , it means that 1% of the objects +set with expire-time, 10% of the objects gotten will be verified. If the +objects are gotten, memaslap will verify the expire-time and +value. + +=head2 multi-servers and multi-clients + +Memslap supports multi-servers based on self-governed thread. +There is a limitation that the number of servers cannot be greater than the +number of threads. Memslap assigns one thread to handle one +server at least. The user can use the "--servers=" or "-s" option to specify +multi-servers. + +For example: + +--servers=10.1.1.1:11211,10.1.1.2:11212,10.1.1.3:11213 --threads=6 --concurrency=36 + +The above command means that there are 6 threads, with each thread having 6 +concurrencies and that threads 0 and 3 handle server 0 (10.1.1.1); threads 1 +and 4 handle server 1 (10.1.1.2); and thread 2 and 5 handle server 2 +(10.1.1.3). + +All the threads and concurrencies in memaslap are self-governed. + +So is memaslap. The user can start up several +memaslap instances. The user can run memaslap on different client +machines to communicate with the same memcached server at the same. It is +recommended that the user start different memaslap on different +machines using the same configuration. + +=head2 Run with execute number mode or time mode + +The default memaslap runs with time mode. The default run time +is 10 minutes. If it times out, memaslap will exit. Do not +specify both execute number mode and time mode at the same time; just +specify one instead. + +For example: + +--time=30s (It means the test will run 30 seconds.) + +--execute_number=100000 (It means that after running 100000 commands, the test will exit.) + +=head2 Dump statistic information periodically. + +The user can use "--stat_freq=" or "-S" to specify the frequency. + +For example: + +--stat_freq=20s + +Memslap will dump the statistics of the commands (get and set) at the frequency of every 20 +seconds. + +For more information on the format of dumping statistic information, refer to “Format of Output” section. + +=head2 Multi-get + +The user can use "--division=" or "-d" to specify multi-get keys count. +Memslap by default does single get with TCP. Memslap also supports data +verification and expire-time verification for multi-get. + +Memslap supports multi-get with both TCP and UDP. Because of +the different implementation of the ASCII protocol and binary protocol, +there are some differences between the two. For the ASCII protocol, +memaslap sends one “multi-get” to the server once. For the +binary protocol, memaslap sends several single get commands +together as “multi-get” to the server. + +=head2 UDP and TCP + +Memslap supports both UDP and TCP. For TCP, +memaslap does not reconnect the memcached server if socket connections are +lost. If all the socket connections are lost or memcached server crashes, +memaslap will exit. If the user specifies the “--reconnect” +option when socket connections are lost, it will reconnect them. + +User can use “--udp” to enable the UDP feature, but UDP comes with some +limitations: + +UDP cannot set data more than 1400 bytes. + +UDP is not supported by the binary protocol because the binary protocol of +memcached does not support that. + +UDP doesn’t support reconnection. + +=head2 Facebook test + +Set data with TCP and multi-get with UDP. Specify the following options: + +"--facebook --division=50" + +If you want to create thousands of TCP connections, specify the + +"--conn_sock=" option. + +For example: --facebook --division=50 --conn_sock=200 + +The above command means that memaslap will do facebook test, +each concurrency has 200 socket TCP connections and one UDP socket. + +Memslap sets objects with the TCP socket, and multi-gets 50 +objects once with the UDP socket. + +If you specify "--division=50", the key size must be less that 25 bytes +because the UDP packet size is 1400 bytes. + +=head2 Replication test + +For replication test, the user must specify at least two memcached servers. +The user can use “—rep_write=” option to enable feature. + +For example: + +--servers=10.1.1.1:11211,10.1.1.2:11212 –rep_write=2 + +The above command means that there are 2 replication memcached servers, +memaslap will set objects to both server 0 and server 1, get +objects which are set to server 0 before from server 1, and also get objects +which are set to server 1 before from server 0. If server 0 crashes, +memaslap will only get objects from server 1. If server 0 comes +back to life again, memaslap will reconnect server 0. If both +server 0 and server 1 crash, memaslap will exit. + +=head2 Supports thousands of TCP connections + +Start memaslap with "--conn_sock=" or "-n" to enable this +feature. Make sure that your system can support opening thousands of files +and creating thousands of sockets. However, this feature does not support +reconnection if sockets disconnect. + +For example: + +--threads=8 --concurrency=128 --conn_sock=128 + +The above command means that memaslap starts up 8 threads, each +thread has 16 concurrencies, each concurrency has 128 TCP socket +connections, and the total number of TCP socket connections is 128 * 128 = +16384. + +=head2 Supports binary protocol + +Start memaslap with "--binary" or "-B" options to enable this +feature. It supports all the above features except UDP, because the latest +memcached 1.3.3 does not implement binary UDP protocol. + +For example: + +--binary + +Since memcached 1.3.3 doesn't implement binary UDP protocol, +memaslap does not support UDP. In addition, memcached 1.3.3 does not support +multi-get. If you specify "--division=50" option, it just sends 50 get +commands together as “mulit-get” to the server. + +=head1 Configuration file + +This section describes the format of the configuration file. By default +when no configuration file is specified memaslap reads the default +one located at ~/.memaslap.cnf. + +Below is a sample configuration file: + + *************************************************************************** + #comments should start with '#' + #key + #start_len end_len proportion + # + #key length range from start_len to end_len + #start_len must be equal to or greater than 16 + #end_len must be equal to or less than 250 + #start_len must be equal to or greater than end_len + #memaslap will generate keys according to the key range + #proportion: indicates keys generated from one range accounts for the total + generated keys + # + #example1: key range 16~100 accounts for 80% + # key range 101~200 accounts for 10% + # key range 201~250 accounts for 10% + # total should be 1 (0.8+0.1+0.1 = 1) + # + # 16 100 0.8 + # 101 200 0.1 + # 201 249 0.1 + # + #example2: all keys length are 128 bytes + # + # 128 128 1 + key + 128 128 1 + #value + #start_len end_len proportion + # + #value length range from start_len to end_len + #start_len must be equal to or greater than 1 + #end_len must be equal to or less than 1M + #start_len must be equal to or greater than end_len + #memaslap will generate values according to the value range + #proportion: indicates values generated from one range accounts for the + total generated values + # + #example1: value range 1~1000 accounts for 80% + # value range 1001~10000 accounts for 10% + # value range 10001~100000 accounts for 10% + # total should be 1 (0.8+0.1+0.1 = 1) + # + # 1 1000 0.8 + # 1001 10000 0.1 + # 10001 100000 0.1 + # + #example2: all value length are 128 bytes + # + # 128 128 1 + value + 2048 2048 1 + #cmd + #cmd_type cmd_proportion + # + #currently memaslap only supports get and set command. + # + #cmd_type + #set 0 + #get 1 + # + #example: set command accounts for 50% + # get command accounts for 50% + # total should be 1 (0.5+0.5 = 1) + # + # cmd + # 0 0.5 + # 1 0.5 + cmd + 0 0.1 + 1.0 0.9 + + + +=head1 Format of output + +At the beginning, memaslap displays some configuration information as follows: + +=over 4 + +=item servers : 127.0.0.1:11211 + +=item threads count: 1 + +=item concurrency: 16 + +=item run time: 20s + +=item windows size: 10k + +=item set proportion: set_prop=0.10 + +=item get proportion: get_prop=0.90 + +=back + +=head2 Where + +=over 4 + +=item servers : "servers" + +The servers used by memaslap. + +=item threads count + +The number of threads memaslap runs with. + +=item concurrency + +The number of concurrencies memaslap runs with. + +=item run time + +How long to run memaslap. + +=item windows size + +The task window size of each concurrency. + +=item set proportion + +The proportion of set command. + +=item get proportion + +The proportion of get command. + +=back + +The output of dynamic statistics is something like this: + + --------------------------------------------------------------------------------------------------------------------------------- + Get Statistics + Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) + Avg(us) Std_dev Geo_dist + Period 5 345826 69165 65.3 0 27 2198 203 + 95.43 177.29 + Global 20 1257935 62896 71.8 0 26 3791 224 + 117.79 192.60 + + + Set Statistics + Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) + Avg(us) Std_dev Geo_dist + Period 5 38425 7685 7.3 0 42 628 240 + 88.05 220.21 + Global 20 139780 6989 8.0 0 37 3790 253 + 117.93 224.83 + + + Total Statistics + Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) + Avg(us) Std_dev Geo_dist + Period 5 384252 76850 72.5 0 27 2198 207 + 94.72 181.18 + Global 20 1397720 69886 79.7 0 26 3791 227 + 117.93 195.60 + --------------------------------------------------------------------------------------------------------------------------------- + +=head2 Where + +=over 4 + +=item Get Statistics + +Statistics information of get command + +=item Set Statistics + +Statistics information of set command + +=item Total Statistics + +Statistics information of both get and set command + +=item Period + +Result within a period + +=item Global + +Accumulated results + +=item Ops + +Total operations + +=item TPS + +Throughput, operations/second + +=item Net + +The rate of network + +=item Get_miss + +How many objects can’t be gotten + +=item Min + +The minimum response time + +=item Max + +The maximum response time + +=item Avg: + +The average response time + +=item Std_dev + +Standard deviation of response time + +=item Geo_dist + +Geometric distribution based on natural exponential function + +=back + +At the end, memaslap will output something like this: + + --------------------------------------------------------------------------------------------------------------------------------- + Get Statistics (1257956 events) + Min: 26 + Max: 3791 + Avg: 224 + Geo: 192.60 + Std: 116.23 + Log2 Dist: + 4: 0 10 84490 215345 + 8: 484890 459823 12543 824 + 12: 31 + + Set Statistics (139782 events) + Min: 37 + Max: 3790 + Avg: 253 + Geo: 224.84 + Std: 116.83 + Log2 Dist: + 4: 0 0 4200 16988 + 8: 50784 65574 2064 167 + 12: 5 + + Total Statistics (1397738 events) + Min: 26 + Max: 3791 + Avg: 227 + Geo: 195.60 + Std: 116.60 + Log2 Dist: + 4: 0 10 88690 232333 + 8: 535674 525397 14607 991 + 12: 36 + + cmd_get: 1257969 + cmd_set: 139785 + get_misses: 0 + verify_misses: 0 + verify_failed: 0 + expired_get: 0 + unexpired_unget: 0 + written_bytes: 242516030 + read_bytes: 1003702556 + object_bytes: 152086080 + packet_disorder: 0 + packet_drop: 0 + udp_timeout: 0 + + Run time: 20.0s Ops: 1397754 TPS: 69817 Net_rate: 59.4M/s + --------------------------------------------------------------------------------------------------------------------------------- + +=head2 Where + +=over 4 + +=item Get Statistics + +Get statistics of response time + +=item Set Statistics + +Set statistics of response time + +=item Total Statistics + +Both get and set statistics of response time + +=item Min + +The accumulated and minimum response time + +=item Max + +The accumulated and maximum response time + +=item Avg + +The accumulated and average response time + +=item Std + +Standard deviation of response time + +=item Log2 Dist + +Geometric distribution based on logarithm 2 + +=item cmd_get + +Total get commands done + +=item cmd_set + +Total set commands done + +=item get_misses + +How many objects can’t be gotten from server + +=item verify_misses + +How many objects need to verify but can’t get them + +=item verify_failed + +How many objects with insistent value + +=item expired_get + +How many objects are expired but we get them + +=item unexpired_unget + +How many objects are unexpired but we can’t get them + +=item written_bytes + +Total written bytes + +=item read_bytes + +Total read bytes + +=item object_bytes + +Total object bytes + +=item packet_disorder + +How many UDP packages are disorder + +=item packet_drop + +How many UDP packages are lost + +=item udp_timeout + +How many times UDP time out happen + +=item Run time + +Total run time + +=item Ops + +Total operations + +=item TPS + +Throughput, operations/second + +=item Net_rate + +The average rate of network + +=back + +=head1 OPTIONS + +-s, --servers= + List one or more servers to connect. Servers count must be less than + threads count. e.g.: --servers=localhost:1234,localhost:11211 + +-T, --threads= + Number of threads to startup, better equal to CPU numbers. Default 8. + +-c, --concurrency= + Number of concurrency to simulate with load. Default 128. + +-n, --conn_sock= + Number of TCP socks per concurrency. Default 1. + +-x, --execute_number= + Number of operations(get and set) to execute for the + given test. Default 1000000. + +-t, --time= + How long the test to run, suffix: s-seconds, m-minutes, h-hours, + d-days e.g.: --time=2h. + +-F, --cfg_cmd= + Load the configure file to get command,key and value distribution list. + +-w, --win_size= + Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k. + Default 10k. + +-X, --fixed_size= + Fixed length of value. + +-v, --verify= + The proportion of date verification, e.g.: --verify=0.01 + +-d, --division= + Number of keys to multi-get once. Default 1, means single get. + +-S, --stat_freq= + Frequency of dumping statistic information. suffix: s-seconds, + m-minutes, e.g.: --resp_freq=10s. + +-e, --exp_verify= + The proportion of objects with expire time, e.g.: --exp_verify=0.01. + Default no object with expire time + +-o, --overwrite= + The proportion of objects need overwrite, e.g.: --overwrite=0.01. + Default never overwrite object. + +-R, --reconnect + Reconnect support, when connection is closed it will be reconnected. + +-U, --udp + UDP support, default memaslap uses TCP, TCP port and UDP port of + server must be same. + +-a, --facebook + Whether it enables facebook test feature, set with TCP and multi-get with UDP. + +-B, --binary + Whether it enables binary protocol. Default with ASCII protocol. + +-P, --tps= + Expected throughput, suffix: K, e.g.: --tps=10k. + +-p, --rep_write= + The first nth servers can write data, e.g.: --rep_write=2. + +-b, --verbose + Whether it outputs detailed information when verification fails. + +-h, --help + Display this message and then exit. + +-V, --version + Display the version of the application and then exit. + +=head1 EXAMPLES + +memaslap -s 127.0.0.1:11211 -S 5s + +memaslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b + +memaslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2 + +memaslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k + +memaslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40 + +memaslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m + +memaslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2 + +=head1 HOME + +To find out more information please check: +L + +=head1 AUTHORS + +Mingqiang Zhuang Emingqiangzhuang@hengtiansoft.comE (Schooner Technolgy) +Brian Aker, Ebrian@tangent.orgE + +=head1 SEE ALSO + +memcached(1) libmemcached(3) + +=cut + diff --git a/docs/memslap.pod b/docs/memslap.pod index 462f67fe..43f714cc 100644 --- a/docs/memslap.pod +++ b/docs/memslap.pod @@ -9,994 +9,20 @@ memslap - Load testing and benchmarking tool for memcached =head1 DESCRIPTION B is a load generation and benchmark tool for memcached(1) -servers. It generates configurable workload such as threads, concurrencies, connections, -run time, overwrite, miss rate, key size, value size, get/set proportion, -expected throughput, and so on. Furthermore, it also supports data -verification, expire-time verification, UDP, binary protocol, facebook test, -replication test, multi-get and reconnection, etc. - -Memslap manages network connections like memcached with -libevent. Each thread of memslap is bound with a CPU core, all -the threads don't communicate with each other, and there are several socket -connections in each thread. Each connection keeps key size distribution, -value size distribution, and command distribution by itself. +servers. It simulates loads on memcached server clusters. You can specify servers via the B<--servers> option or via the environment variable C. - -=head1 FEATURES - -Memslap is developed to for the following purposes: - -=over - -=item Manages network connections with libevent asynchronously. - -=item Set both TCP and UDP up to use non-blocking IO. - -=item Improves parallelism: higher performance in multi-threads environments. - -=item Improves time efficiency: faster processing speed. - -=item Generates key and value more efficiently; key size distribution and value size distribution are configurable. - -=item Supports get, multi-get, and set commands; command distribution is configurable. - -=item Supports controllable miss rate and overwrite rate. - -=item Supports data and expire-time verification. - -=item Supports dumping statistic information periodically. - -=item Supports thousands of TCP connections. - -=item Supports binary protocol. - -=item Supports facebook test (set with TCP and multi-get with UDP) and replication test. - -=back - -=head1 DETAILS - -=head2 Effective implementation of network. - -For memslap, both TCP and UDP use non-blocking network IO. All -the network events are managed by libevent as memcached. The network module -of memslap is similar to memcached. Libevent can ensure -memslap can handle network very efficiently. - -=head2 Effective implementation of multi-threads and concurrency - -Memslap has the similar implementation of multi-threads to -memcached. Memslap creates one or more self-governed threads; -each thread is bound with one CPU core if the system supports setting CPU -core affinity. - -In addition, each thread has a libevent to manage the events of the network; -each thread has one or more self-governed concurrencies; and each -concurrency has one or more socket connections. All the concurrencies don’t -communicate with each other even though they are in the same thread. - -Memslap can create thousands of socket connections, and each -concurrency has tens of socket connections. Each concurrency randomly or -sequentially selects one socket connection from its socket connection pool -to run, so memslap can ensure each concurrency handles one -socket connection at any given time. Users can specify the number of -concurrency and socket connections of each concurrency according to their -expected workload. - -=head2 Effective implementation of generating key and value - -In order to improve time efficiency and space efficiency, -memslap creates a random characters table with 10M characters. All the -suffixes of keys and values are generated from this random characters table. - -Memslap uses the offset in the character table and the length -of the string to identify a string. It can save much memory. -Each key contains two parts, a prefix and a suffix. The prefix is an -uint64_t, 8 bytes. In order to verify the data set before, -memslap need to ensure each key is unique, so it uses the prefix to identify -a key. The prefix cannot include illegal characters, such as ‘\r’, ‘\n’, -‘\0’ and ‘ ‘. And memslap has an algorithm to ensure that. - -Memslap doesn’t generate all the objects (key-value pairs) at -the beginning. It only generates enough objects to fill the task window -(default 10K objects) of each concurrency. Each object has the following -basic information, key prefix, key suffix offset in the character table, key -length, value offset in the character table, and value length. - -In the work process, each concurrency sequentially or randomly selects an -object from the window to do set operation or get operation. At the same -time, each concurrency kicks objects out of its window and adds new object -into it. - -=head2 Simple but useful task scheduling - -Memslap uses libevent to schedule all the concurrencies of -threads, and each concurrency schedules tasks based on the local task -window. Memslap assumes that if each concurrency keeps the same -key distribution, value distribution and commands distribution, from -outside, memslap keeps all the distribution as a whole. -Each task window includes a lot of objects, each object stores its basic -information, such as key, value, expire time, and so on. At any time, all -the objects in the window keep the same and fixed key and value -distribution. If an object is overwritten, the value of the object will be -updated. Memslap verifies the data or expire-time according to -the object information stored in the task window. - -Libevent selects which concurrency to handle based on a specific network -event. Then the concurrency selects which command (get or set) to operate -based on the command distribution. If it needs to kick out an old object and -add a new object, in order to keep the same key and value distribution, the -new object must have the same key length and value length. - -If memcached server has two cache layers (memory and SSD), running -memslap with different window sizes can get different cache -miss rates. If memslap adds enough objects into the windows at -the beginning, and the cache of memcached cannot store all the objects -initialized, then memslap will get some objects from the second -cache layer. It causes the first cache layer to miss. So the user can -specify the window size to get the expected miss rate of the first cache -layer. - -=head2 Useful implementation of multi-servers , UDP, TCP, multi-get and binary protocol - -Because each thread is self-governed, memslap can assign -different threads to handle different memcached servers. This is just one of -the ways in which memslap supports multiple servers. The only -limitation is that the number of servers cannot be greater than the number -of threads. The other way to support multiple servers is for replication -test. Each concurrency has one socket connection to each memcached server. -For the implementation, memslap can set some objects to one -memcached server, and get these objects from the other servers. - -By default, Memslap does single get. If the user specifies -multi-get option, memslap will collect enough get commands and -pack and send the commands together. - -Memslap supports both the ASCII protocol and binary protocol, -but it runs on the ASCII protocol by default. -Memslap by default runs on the TCP protocol, but it also -supports UDP. Because UDP is unreliable, dropped packages and out-of-order -packages may occur. Memslap creates a memory buffer to handle -these problems. Memslap tries to read all the response data of -one command from the server and reorders the response data. If some packages -get lost, the waiting timeout mechanism can ensure half-baked packages will -be discarded and the next command will be sent. - - -=head1 USAGE - -Below are some usage samples: - -=over 4 - -=item memslap -s 127.0.0.1:11211 -S 5s - -=item memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b - -=item memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2 - -=item memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k - -=item memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40 - -=item memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m - -=item memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2 - -=back - -The user must specify one server at least to run memslap. The -rest of the parameters have default values, as shown below: - -Thread number = 1 Concurrency = 16 - -Run time = 600 seconds Configuration file = NULL - -Key size = 64 Value size = 1024 - -Get/set = 9:1 Window size = 10k - -Execute number = 0 Single get = true - -Multi-get = false Number of sockets of each concurrency = 1 - -Reconnect = false Data verification = false - -Expire-time verification = false ASCII protocol = true - -Binary protocol = false Dumping statistic information - -periodically = false - -Overwrite proportion = 0% UDP = false - -TCP = true Limit throughput = false - -Facebook test = false Replication test = false - -=head2 Key size, value size and command distribution. - -All the distributions are read from the configuration file specified by user -with “—cfg_cmd” option. If the user does not specify a configuration file, -memslap will run with the default distribution (key size = 64, -value size = 1024, get/set = 9:1). For information on how to edit the -configuration file, refer to the “Configuration File” section. - -The minimum key size is 16 bytes; the maximum key size is 250 bytes. The -precision of proportion is 0.001. The proportion of distribution will be -rounded to 3 decimal places. - -The minimum value size is 1 bytes; the maximum value size is 1M bytes. The -precision of proportion is 0.001. The proportion of distribution will be -rounded to 3 decimal places. -Currently, memslap only supports set and get commands. And it -supports 100% set and 100% get. For 100% get, it will preset some objects to -the server. - -=head2 Multi-thread and concurrency - -The high performance of memslap benefits from the special -schedule of thread and concurrency. It’s important to specify the proper -number of them. The default number of threads is 1; the default number of -concurrency is 16. The user can use “—threads” and “--concurrency” to -specify these variables. - -If the system supports setting CPU affinity and the number of threads -specified by the user is greater than 1, memslap will try to -bind each thread to a different CPU core. So if you want to get the best -performance memslap, it is better to specify the number of -thread equal to the number of CPU cores. The number of threads specified by -the user can also be less or greater than the number of CPU cores. Because -of the limitation of implementation, the number of concurrencies could be -the multiple of the number of threads. - -1. For 8 CPU cores system - -For example: - ---threads=2 --concurrency=128 - ---threads=8 --concurrency=128 - ---threads=8 --concurrency=256 - ---threads=12 --concurrency=144 - -2. For 16 CPU cores system - -For example: - ---threads=8 --concurrency=128 - ---threads=16 --concurrency=256 - ---threads=16 --concurrency=512 - ---threads=24 --concurrency=288 - -The memslap performs very well, when -used to test the performance of memcached servers. -Most of the time, the bottleneck is the network or -the server. If for some reason the user wants to -limit the performance of memslap, there -are two ways to do this: - -Decrease the number of threads and concurrencies. -Use the option “--tps” that memslap -provides to limit the throughput. This option allows -the user to get the expected throughput. For -example, assume that the maximum throughput is 50 -kops/s for a specific configuration, you can specify -the throughput equal to or less than the maximum -throughput using “--tps” option. - -=head2 Window size - -Most of the time, the user does not need to specify the window size. The -default window size is 10k. For Schooner Memcached, the user can specify -different window sizes to get different cache miss rates based on the test -case. Memslap supports cache miss rate between 0% and 100%. -If you use this utility to test the performance of Schooner Memcached, you -can specify a proper window size to get the expected cache miss rate. The -formula for calculating window size is as follows: - -Assume that the key size is 128 bytes, and the value size is 2048 bytes, and -concurrency=128. - -1. Small cache cache_size=1M, 100% cache miss (all data get from SSD). -win_size=10k - -2. cache_size=4G - -(1). cache miss rate 0% - -win_size=8k - -(2). cache miss rate 5% - -win_size=11k - -3. cache_size=16G - -(1). cache miss rate 0% - -win_size=32k - -(2). cache miss - -rate 5% - -win_size=46k - -The formula for calculating window size for cache miss rate 0%: - -cache_size / concurrency / (key_size + value_size) * 0.5 - -The formula for calculating window size for cache miss rate 5%: - -cache_size / concurrency / (key_size + value_size) * 0.7 - -=head2 Verification - -Memslap supports both data verification and expire-time -verification. The user can use "--verify=" or "-v" to specify the proportion -of data verification. In theory, it supports 100% data verification. The -user can use "--exp_verify=" or "-e" to specify the proportion of -expire-time verification. In theory, it supports 100% expire-time -verification. Specify the "--verbose" options to get more detailed error -information. - -For example: --exp_verify=0.01 –verify=0.1 , it means that 1% of the objects -set with expire-time, 10% of the objects gotten will be verified. If the -objects are gotten, memslap will verify the expire-time and -value. - -=head2 multi-servers and multi-clients - -Memslap supports multi-servers based on self-governed thread. -There is a limitation that the number of servers cannot be greater than the -number of threads. Memslap assigns one thread to handle one -server at least. The user can use the "--servers=" or "-s" option to specify -multi-servers. - -For example: - ---servers=10.1.1.1:11211,10.1.1.2:11212,10.1.1.3:11213 --threads=6 --concurrency=36 - -The above command means that there are 6 threads, with each thread having 6 -concurrencies and that threads 0 and 3 handle server 0 (10.1.1.1); threads 1 -and 4 handle server 1 (10.1.1.2); and thread 2 and 5 handle server 2 -(10.1.1.3). - -All the threads and concurrencies in memslap are self-governed. - -So is memslap. The user can start up several -memslap instances. The user can run memslap on different client -machines to communicate with the same memcached server at the same. It is -recommended that the user start different memslap on different -machines using the same configuration. - -=head2 Run with execute number mode or time mode - -The default memslap runs with time mode. The default run time -is 10 minutes. If it times out, memslap will exit. Do not -specify both execute number mode and time mode at the same time; just -specify one instead. - -For example: - ---time=30s (It means the test will run 30 seconds.) - ---execute_number=100000 (It means that after running 100000 commands, the test will exit.) - -=head2 Dump statistic information periodically. - -The user can use "--stat_freq=" or "-S" to specify the frequency. - -For example: - ---stat_freq=20s - -Memslap will dump the statistics of the commands (get and set) at the frequency of every 20 -seconds. - -For more information on the format of dumping statistic information, refer to “Format of Output” section. - -=head2 Multi-get - -The user can use "--division=" or "-d" to specify multi-get keys count. -Memslap by default does single get with TCP. Memslap also supports data -verification and expire-time verification for multi-get. - -Memslap supports multi-get with both TCP and UDP. Because of -the different implementation of the ASCII protocol and binary protocol, -there are some differences between the two. For the ASCII protocol, -memslap sends one “multi-get” to the server once. For the -binary protocol, memslap sends several single get commands -together as “multi-get” to the server. - -=head2 UDP and TCP - -Memslap supports both UDP and TCP. For TCP, -memslap does not reconnect the memcached server if socket connections are -lost. If all the socket connections are lost or memcached server crashes, -memslap will exit. If the user specifies the “--reconnect” -option when socket connections are lost, it will reconnect them. - -User can use “--udp” to enable the UDP feature, but UDP comes with some -limitations: - -UDP cannot set data more than 1400 bytes. - -UDP is not supported by the binary protocol because the binary protocol of -memcached does not support that. - -UDP doesn’t support reconnection. - -=head2 Facebook test - -Set data with TCP and multi-get with UDP. Specify the following options: - -"--facebook --division=50" - -If you want to create thousands of TCP connections, specify the - -"--conn_sock=" option. - -For example: --facebook --division=50 --conn_sock=200 - -The above command means that memslap will do facebook test, -each concurrency has 200 socket TCP connections and one UDP socket. - -Memslap sets objects with the TCP socket, and multi-gets 50 -objects once with the UDP socket. - -If you specify "--division=50", the key size must be less that 25 bytes -because the UDP packet size is 1400 bytes. - -=head2 Replication test - -For replication test, the user must specify at least two memcached servers. -The user can use “—rep_write=” option to enable feature. - -For example: - ---servers=10.1.1.1:11211,10.1.1.2:11212 –rep_write=2 - -The above command means that there are 2 replication memcached servers, -memslap will set objects to both server 0 and server 1, get -objects which are set to server 0 before from server 1, and also get objects -which are set to server 1 before from server 0. If server 0 crashes, -memslap will only get objects from server 1. If server 0 comes -back to life again, memslap will reconnect server 0. If both -server 0 and server 1 crash, memslap will exit. - -=head2 Supports thousands of TCP connections - -Start memslap with "--conn_sock=" or "-n" to enable this -feature. Make sure that your system can support opening thousands of files -and creating thousands of sockets. However, this feature does not support -reconnection if sockets disconnect. - -For example: - ---threads=8 --concurrency=128 --conn_sock=128 - -The above command means that memslap starts up 8 threads, each -thread has 16 concurrencies, each concurrency has 128 TCP socket -connections, and the total number of TCP socket connections is 128 * 128 = -16384. - -=head2 Supports binary protocol - -Start memslap with "--binary" or "-B" options to enable this -feature. It supports all the above features except UDP, because the latest -memcached 1.3.3 does not implement binary UDP protocol. - -For example: - ---binary - -Since memcached 1.3.3 doesn't implement binary UDP protocol, -memslap does not support UDP. In addition, memcached 1.3.3 does not support -multi-get. If you specify "--division=50" option, it just sends 50 get -commands together as “mulit-get” to the server. - -=head1 Configuration file - -This section describes the format of the configuration file. By default -when no configuration file is specified memslap reads the default -one located at ~/.memslap.cnf. - -Below is a sample configuration file: - - *************************************************************************** - #comments should start with '#' - #key - #start_len end_len proportion - # - #key length range from start_len to end_len - #start_len must be equal to or greater than 16 - #end_len must be equal to or less than 250 - #start_len must be equal to or greater than end_len - #memslap will generate keys according to the key range - #proportion: indicates keys generated from one range accounts for the total - generated keys - # - #example1: key range 16~100 accounts for 80% - # key range 101~200 accounts for 10% - # key range 201~250 accounts for 10% - # total should be 1 (0.8+0.1+0.1 = 1) - # - # 16 100 0.8 - # 101 200 0.1 - # 201 249 0.1 - # - #example2: all keys length are 128 bytes - # - # 128 128 1 - key - 128 128 1 - #value - #start_len end_len proportion - # - #value length range from start_len to end_len - #start_len must be equal to or greater than 1 - #end_len must be equal to or less than 1M - #start_len must be equal to or greater than end_len - #memslap will generate values according to the value range - #proportion: indicates values generated from one range accounts for the - total generated values - # - #example1: value range 1~1000 accounts for 80% - # value range 1001~10000 accounts for 10% - # value range 10001~100000 accounts for 10% - # total should be 1 (0.8+0.1+0.1 = 1) - # - # 1 1000 0.8 - # 1001 10000 0.1 - # 10001 100000 0.1 - # - #example2: all value length are 128 bytes - # - # 128 128 1 - value - 2048 2048 1 - #cmd - #cmd_type cmd_proportion - # - #currently memslap only supports get and set command. - # - #cmd_type - #set 0 - #get 1 - # - #example: set command accounts for 50% - # get command accounts for 50% - # total should be 1 (0.5+0.5 = 1) - # - # cmd - # 0 0.5 - # 1 0.5 - cmd - 0 0.1 - 1.0 0.9 - - - -=head1 Format of output - -At the beginning, memslap displays some configuration information as follows: - -=over 4 - -=item servers : 127.0.0.1:11211 - -=item threads count: 1 - -=item concurrency: 16 - -=item run time: 20s - -=item windows size: 10k - -=item set proportion: set_prop=0.10 - -=item get proportion: get_prop=0.90 - -=back - -=head2 Where - -=over 4 - -=item servers : "servers" - -The servers used by memslap. - -=item threads count - -The number of threads memslap runs with. - -=item concurrency - -The number of concurrencies memslap runs with. - -=item run time - -How long to run memslap. - -=item windows size - -The task window size of each concurrency. - -=item set proportion - -The proportion of set command. - -=item get proportion - -The proportion of get command. - -=back - -The output of dynamic statistics is something like this: - - --------------------------------------------------------------------------------------------------------------------------------- - Get Statistics - Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) - Avg(us) Std_dev Geo_dist - Period 5 345826 69165 65.3 0 27 2198 203 - 95.43 177.29 - Global 20 1257935 62896 71.8 0 26 3791 224 - 117.79 192.60 - - - Set Statistics - Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) - Avg(us) Std_dev Geo_dist - Period 5 38425 7685 7.3 0 42 628 240 - 88.05 220.21 - Global 20 139780 6989 8.0 0 37 3790 253 - 117.93 224.83 - - - Total Statistics - Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) - Avg(us) Std_dev Geo_dist - Period 5 384252 76850 72.5 0 27 2198 207 - 94.72 181.18 - Global 20 1397720 69886 79.7 0 26 3791 227 - 117.93 195.60 - --------------------------------------------------------------------------------------------------------------------------------- - -=head2 Where - -=over 4 - -=item Get Statistics - -Statistics information of get command - -=item Set Statistics - -Statistics information of set command - -=item Total Statistics - -Statistics information of both get and set command - -=item Period - -Result within a period - -=item Global - -Accumulated results - -=item Ops - -Total operations - -=item TPS - -Throughput, operations/second - -=item Net - -The rate of network - -=item Get_miss - -How many objects can’t be gotten - -=item Min - -The minimum response time - -=item Max - -The maximum response time - -=item Avg: - -The average response time - -=item Std_dev - -Standard deviation of response time - -=item Geo_dist - -Geometric distribution based on natural exponential function - -=back - -At the end, memslap will output something like this: - - --------------------------------------------------------------------------------------------------------------------------------- - Get Statistics (1257956 events) - Min: 26 - Max: 3791 - Avg: 224 - Geo: 192.60 - Std: 116.23 - Log2 Dist: - 4: 0 10 84490 215345 - 8: 484890 459823 12543 824 - 12: 31 - - Set Statistics (139782 events) - Min: 37 - Max: 3790 - Avg: 253 - Geo: 224.84 - Std: 116.83 - Log2 Dist: - 4: 0 0 4200 16988 - 8: 50784 65574 2064 167 - 12: 5 - - Total Statistics (1397738 events) - Min: 26 - Max: 3791 - Avg: 227 - Geo: 195.60 - Std: 116.60 - Log2 Dist: - 4: 0 10 88690 232333 - 8: 535674 525397 14607 991 - 12: 36 - - cmd_get: 1257969 - cmd_set: 139785 - get_misses: 0 - verify_misses: 0 - verify_failed: 0 - expired_get: 0 - unexpired_unget: 0 - written_bytes: 242516030 - read_bytes: 1003702556 - object_bytes: 152086080 - packet_disorder: 0 - packet_drop: 0 - udp_timeout: 0 - - Run time: 20.0s Ops: 1397754 TPS: 69817 Net_rate: 59.4M/s - --------------------------------------------------------------------------------------------------------------------------------- - -=head2 Where - -=over 4 - -=item Get Statistics - -Get statistics of response time - -=item Set Statistics - -Set statistics of response time - -=item Total Statistics - -Both get and set statistics of response time - -=item Min - -The accumulated and minimum response time - -=item Max - -The accumulated and maximum response time - -=item Avg - -The accumulated and average response time - -=item Std - -Standard deviation of response time - -=item Log2 Dist - -Geometric distribution based on logarithm 2 - -=item cmd_get - -Total get commands done - -=item cmd_set - -Total set commands done - -=item get_misses - -How many objects can’t be gotten from server - -=item verify_misses - -How many objects need to verify but can’t get them - -=item verify_failed - -How many objects with insistent value - -=item expired_get - -How many objects are expired but we get them - -=item unexpired_unget - -How many objects are unexpired but we can’t get them - -=item written_bytes - -Total written bytes - -=item read_bytes - -Total read bytes - -=item object_bytes - -Total object bytes - -=item packet_disorder - -How many UDP packages are disorder - -=item packet_drop - -How many UDP packages are lost - -=item udp_timeout - -How many times UDP time out happen - -=item Run time - -Total run time - -=item Ops - -Total operations - -=item TPS - -Throughput, operations/second - -=item Net_rate - -The average rate of network - -=back - -=head1 OPTIONS - --s, --servers= - List one or more servers to connect. Servers count must be less than - threads count. e.g.: --servers=localhost:1234,localhost:11211 - --T, --threads= - Number of threads to startup, better equal to CPU numbers. Default 8. - --c, --concurrency= - Number of concurrency to simulate with load. Default 128. - --n, --conn_sock= - Number of TCP socks per concurrency. Default 1. - --x, --execute_number= - Number of operations(get and set) to execute for the - given test. Default 1000000. - --t, --time= - How long the test to run, suffix: s-seconds, m-minutes, h-hours, - d-days e.g.: --time=2h. - --F, --cfg_cmd= - Load the configure file to get command,key and value distribution list. - --w, --win_size= - Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k. - Default 10k. - --X, --fixed_size= - Fixed length of value. - --v, --verify= - The proportion of date verification, e.g.: --verify=0.01 - --d, --division= - Number of keys to multi-get once. Default 1, means single get. - --S, --stat_freq= - Frequency of dumping statistic information. suffix: s-seconds, - m-minutes, e.g.: --resp_freq=10s. - --e, --exp_verify= - The proportion of objects with expire time, e.g.: --exp_verify=0.01. - Default no object with expire time - --o, --overwrite= - The proportion of objects need overwrite, e.g.: --overwrite=0.01. - Default never overwrite object. - --R, --reconnect - Reconnect support, when connection is closed it will be reconnected. - --U, --udp - UDP support, default memslap uses TCP, TCP port and UDP port of - server must be same. - --a, --facebook - Whether it enables facebook test feature, set with TCP and multi-get with UDP. - --B, --binary - Whether it enables binary protocol. Default with ASCII protocol. - --P, --tps= - Expected throughput, suffix: K, e.g.: --tps=10k. - --p, --rep_write= - The first nth servers can write data, e.g.: --rep_write=2. - --b, --verbose - Whether it outputs detailed information when verification fails. - --h, --help - Display this message and then exit. - --V, --version - Display the version of the application and then exit. - -=head1 EXAMPLES - -memslap -s 127.0.0.1:11211 -S 5s - -memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b - -memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2 - -memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k - -memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40 - -memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m - -memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2 +For a full list of operations run the tool with the B<--help> option. =head1 HOME To find out more information please check: -L +L -=head1 AUTHORS +=head1 AUTHOR -Mingqiang Zhuang Emingqiangzhuang@hengtiansoft.comE (Schooner Technolgy) Brian Aker, Ebrian@tangent.orgE =head1 SEE ALSO diff --git a/libhashkit/algorithm.c b/libhashkit/algorithm.c index 0f0f9f01..de00081d 100644 --- a/libhashkit/algorithm.c +++ b/libhashkit/algorithm.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length) { diff --git a/libhashkit/behavior.c b/libhashkit/behavior.c index 683798ea..ee0efcf3 100644 --- a/libhashkit/behavior.c +++ b/libhashkit/behavior.c @@ -6,4 +6,4 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include diff --git a/libhashkit/common.h b/libhashkit/common.h index dff3ab0b..73b198f5 100644 --- a/libhashkit/common.h +++ b/libhashkit/common.h @@ -9,7 +9,7 @@ #ifndef HASHKIT_COMMON_H #define HASHKIT_COMMON_H -#include "config.h" +#include #include #include @@ -17,7 +17,7 @@ #include #include -#include "hashkit.h" +#include #ifdef __cplusplus extern "C" { diff --git a/libhashkit/crc32.c b/libhashkit/crc32.c index b4ad8ec3..f07958ca 100644 --- a/libhashkit/crc32.c +++ b/libhashkit/crc32.c @@ -4,7 +4,7 @@ * src/usr.bin/cksum/crc32.c. */ -#include "common.h" +#include static const uint32_t crc32tab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, diff --git a/libhashkit/digest.c b/libhashkit/digest.c index 4ff6de29..e1559819 100644 --- a/libhashkit/digest.c +++ b/libhashkit/digest.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length) { diff --git a/libhashkit/fnv.c b/libhashkit/fnv.c index 41243813..fffb94a4 100644 --- a/libhashkit/fnv.c +++ b/libhashkit/fnv.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include /* FNV hash'es lifted from Dustin Sallings work */ static uint64_t FNV_64_INIT= UINT64_C(0xcbf29ce484222325); diff --git a/libhashkit/function.c b/libhashkit/function.c index a779bb63..3560abd7 100644 --- a/libhashkit/function.c +++ b/libhashkit/function.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include static hashkit_return_t _set_function(struct hashkit_function_st *self, hashkit_hash_algorithm_t hash_algorithm) { diff --git a/libhashkit/hashkit.c b/libhashkit/hashkit.c index 47c9e580..7214c144 100644 --- a/libhashkit/hashkit.c +++ b/libhashkit/hashkit.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include static const hashkit_st global_default_hash= { .base_hash= { diff --git a/libhashkit/hashkit.h b/libhashkit/hashkit.h index 45133307..2d8ad3a2 100644 --- a/libhashkit/hashkit.h +++ b/libhashkit/hashkit.h @@ -22,12 +22,10 @@ #include #include #include +#include #include #ifdef __cplusplus - -#include - extern "C" { #endif @@ -67,57 +65,63 @@ struct hashkit_st }; #ifdef __cplusplus -class Hashkit : private hashkit_st { + +#include + +class Hashkit { public: Hashkit() { - hashkit_create(this); + hashkit_create(&self); } Hashkit(const Hashkit& source) { - hashkit_clone(this, &source); + hashkit_clone(&self, &source.self); } Hashkit& operator=(const Hashkit& source) { - hashkit_free(this); - hashkit_clone(this, &source); + hashkit_free(&self); + hashkit_clone(&self, &source.self); return *this; } friend bool operator==(const Hashkit &left, const Hashkit &right) { - return hashkit_compare(&left, &right); + return hashkit_compare(&left.self, &right.self); } uint32_t digest(std::string& str) { - return hashkit_digest(this, str.c_str(), str.length()); + return hashkit_digest(&self, str.c_str(), str.length()); } uint32_t digest(const char *key, size_t key_length) { - return hashkit_digest(this, key, key_length); + return hashkit_digest(&self, key, key_length); } hashkit_return_t set_function(hashkit_hash_algorithm_t hash_algorithm) { - return hashkit_set_function(this, hash_algorithm); + return hashkit_set_function(&self, hash_algorithm); } hashkit_return_t set_distribution_function(hashkit_hash_algorithm_t hash_algorithm) { - return hashkit_set_function(this, hash_algorithm); + return hashkit_set_function(&self, hash_algorithm); } ~Hashkit() { - hashkit_free(this); + hashkit_free(&self); } +private: + + hashkit_st self; }; #endif diff --git a/libhashkit/hsieh.c b/libhashkit/hsieh.c index ba46ed2c..35a2e209 100644 --- a/libhashkit/hsieh.c +++ b/libhashkit/hsieh.c @@ -5,7 +5,7 @@ * http://www.azillionmonkeys.com/qed/hash.html */ -#include "common.h" +#include #undef get16bits #if (defined(__GNUC__) && defined(__i386__)) diff --git a/libhashkit/include.am b/libhashkit/include.am index f0adcdc9..12575dfb 100644 --- a/libhashkit/include.am +++ b/libhashkit/include.am @@ -23,6 +23,7 @@ nobase_include_HEADERS+= \ libhashkit/function.h \ libhashkit/hashkit.h \ libhashkit/strerror.h \ + libhashkit/str_algorithm.h \ libhashkit/types.h \ libhashkit/visibility.h @@ -33,14 +34,15 @@ libhashkit_libhashkit_la_SOURCES= \ libhashkit/algorithm.c \ libhashkit/behavior.c \ libhashkit/crc32.c \ - libhashkit/fnv.c \ libhashkit/digest.c \ + libhashkit/fnv.c \ libhashkit/function.c \ libhashkit/hashkit.c \ libhashkit/jenkins.c \ libhashkit/ketama.c \ libhashkit/md5.c \ libhashkit/one_at_a_time.c \ + libhashkit/str_algorithm.c \ libhashkit/strerror.c if INCLUDE_HSIEH_SRC diff --git a/libhashkit/jenkins.c b/libhashkit/jenkins.c index 53e35a82..c2001cb5 100644 --- a/libhashkit/jenkins.c +++ b/libhashkit/jenkins.c @@ -11,7 +11,7 @@ * Add big endian support */ -#include "common.h" +#include #define hashsize(n) ((uint32_t)1<<(n)) #define hashmask(n) (hashsize(n)-1) diff --git a/libhashkit/ketama.c b/libhashkit/ketama.c index a510e57a..45052c22 100644 --- a/libhashkit/ketama.c +++ b/libhashkit/ketama.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include #include #if 0 diff --git a/libhashkit/md5.c b/libhashkit/md5.c index 025c6662..1af5e6c0 100644 --- a/libhashkit/md5.c +++ b/libhashkit/md5.c @@ -29,7 +29,7 @@ These notices must be retained in any copies of any part of this documentation and/or software. */ -#include "common.h" +#include #include #include diff --git a/libhashkit/murmur.c b/libhashkit/murmur.c index 78d7f193..a40b11b7 100644 --- a/libhashkit/murmur.c +++ b/libhashkit/murmur.c @@ -15,7 +15,7 @@ Updated to murmur2 hash - BP */ -#include "common.h" +#include uint32_t hashkit_murmur(const char *key, size_t length, void *context) { diff --git a/libhashkit/one_at_a_time.c b/libhashkit/one_at_a_time.c index 0c9ec31a..aeb11b12 100644 --- a/libhashkit/one_at_a_time.c +++ b/libhashkit/one_at_a_time.c @@ -11,7 +11,7 @@ http://en.wikipedia.org/wiki/Jenkins_hash_function */ -#include "common.h" +#include uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context) { diff --git a/libhashkit/str_algorithm.c b/libhashkit/str_algorithm.c new file mode 100644 index 00000000..0a0613bc --- /dev/null +++ b/libhashkit/str_algorithm.c @@ -0,0 +1,57 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * HashKit + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +const char * libhashkit_string_hash(hashkit_hash_algorithm_t type) +{ + switch(type) + { + case HASHKIT_HASH_DEFAULT: return "DEFAULT"; + case HASHKIT_HASH_MD5: return "MD5"; + case HASHKIT_HASH_CRC: return "CRC"; + case HASHKIT_HASH_FNV1_64: return "FNV1_64"; + case HASHKIT_HASH_FNV1A_64: return "FNV1A_64"; + case HASHKIT_HASH_FNV1_32: return "FNV1_32"; + case HASHKIT_HASH_FNV1A_32: return "FNV1A_32"; + case HASHKIT_HASH_HSIEH: return "HSIEH"; + case HASHKIT_HASH_MURMUR: return "MURMUR"; + case HASHKIT_HASH_JENKINS: return "JENKINS"; + case HASHKIT_HASH_CUSTOM: return "CUSTOM"; + default: + case HASHKIT_HASH_MAX: return "INVALID"; + } +} diff --git a/libhashkit/str_algorithm.h b/libhashkit/str_algorithm.h new file mode 100644 index 00000000..bb05eb51 --- /dev/null +++ b/libhashkit/str_algorithm.h @@ -0,0 +1,48 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * HashKit + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +HASHKIT_API +const char *libhashkit_string_hash(hashkit_hash_algorithm_t type); + +#ifdef __cplusplus +} +#endif diff --git a/libhashkit/strerror.c b/libhashkit/strerror.c index 50532e1d..8d7246c6 100644 --- a/libhashkit/strerror.c +++ b/libhashkit/strerror.c @@ -6,7 +6,7 @@ * the COPYING file in the parent directory for full text. */ -#include "common.h" +#include const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc) { diff --git a/libhashkit/types.h b/libhashkit/types.h index 255620b8..23bd9d5c 100644 --- a/libhashkit/types.h +++ b/libhashkit/types.h @@ -1,12 +1,41 @@ - -/* HashKit - * Copyright (C) 2009 Brian Aker - * All rights reserved. +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * HashKit + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2009 Brian Aker All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. */ + #ifndef HASHKIT_TYPES_H #define HASHKIT_TYPES_H diff --git a/libmemcached/behavior.c b/libmemcached/behavior.c index 0df96033..8a9869f3 100644 --- a/libmemcached/behavior.c +++ b/libmemcached/behavior.c @@ -115,13 +115,14 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data)); case MEMCACHED_BEHAVIOR_KETAMA_HASH: return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data)); + case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: - ptr->flags.use_cache_lookups= set_flag(data); - memcached_quit(ptr); - break; + return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, + memcached_string_with_size("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated.")); + case MEMCACHED_BEHAVIOR_VERIFY_KEY: if (ptr->flags.binary_protocol) - return memcached_set_error_string(ptr, MEMCACHED_FAILURE, + return memcached_set_error_string(ptr, MEMCACHED_INVALID_ARGUMENTS, memcached_string_with_size("MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled.")); ptr->flags.verify_key= set_flag(data); break; @@ -154,7 +155,7 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, memcached_quit(ptr); break; case MEMCACHED_BEHAVIOR_USER_DATA: - return memcached_set_error_string(ptr, MEMCACHED_FAILURE, + return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, memcached_string_with_size("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: ptr->flags.hash_with_prefix_key= set_flag(data); @@ -171,12 +172,8 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, break; case MEMCACHED_BEHAVIOR_CORK: { -#ifdef HAVE_MSG_MORE - break; -#else - return memcached_set_error_string(ptr, MEMCACHED_NOT_SUPPORTED, - memcached_string_with_size("MEMCACHED_BEHAVIOR_CORK is not supported on this platform.")); -#endif + return memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, + memcached_string_with_size("MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default.")); } break; case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: @@ -215,8 +212,10 @@ uint64_t memcached_behavior_get(memcached_st *ptr, return ptr->flags.binary_protocol; case MEMCACHED_BEHAVIOR_SUPPORT_CAS: return ptr->flags.support_cas; + case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: - return ptr->flags.use_cache_lookups; + return true; + case MEMCACHED_BEHAVIOR_NO_BLOCK: return ptr->flags.no_block; case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: @@ -325,8 +324,9 @@ uint64_t memcached_behavior_get(memcached_st *ptr, return (uint64_t) sock_size; } case MEMCACHED_BEHAVIOR_USER_DATA: - return memcached_set_error_string(ptr, MEMCACHED_FAILURE, - memcached_string_with_size("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); + memcached_set_error_string(ptr, MEMCACHED_DEPRECATED, + memcached_string_with_size("MEMCACHED_BEHAVIOR_USER_DATA deprecated.")); + return 0; case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: return ptr->flags.hash_with_prefix_key; case MEMCACHED_BEHAVIOR_NOREPLY: diff --git a/libmemcached/connect.c b/libmemcached/connect.c index 58a6cfd2..9f17f0c3 100644 --- a/libmemcached/connect.c +++ b/libmemcached/connect.c @@ -9,7 +9,8 @@ * */ -#include "common.h" +#include +#include #include #include @@ -86,10 +87,16 @@ static memcached_return_t connect_poll(memcached_server_st *ptr) static memcached_return_t set_hostinfo(memcached_server_st *server) { - struct addrinfo *ai; struct addrinfo hints; char str_port[NI_MAXSERV]; - uint32_t counter= 5; + + assert(! server->address_info); // We cover the case where a programming mistake has been made. + if (server->address_info) + { + freeaddrinfo(server->address_info); + server->address_info= NULL; + server->address_info_next= NULL; + } int length= snprintf(str_port, NI_MAXSERV, "%u", (uint32_t)server->port); if (length >= NI_MAXSERV || length < 0) @@ -97,7 +104,9 @@ static memcached_return_t set_hostinfo(memcached_server_st *server) memset(&hints, 0, sizeof(hints)); - // hints.ai_family= AF_INET; +#if 0 + hints.ai_family= AF_INET; +#endif if (server->type == MEMCACHED_CONNECTION_UDP) { hints.ai_protocol= IPPROTO_UDP; @@ -109,9 +118,10 @@ static memcached_return_t set_hostinfo(memcached_server_st *server) hints.ai_protocol= IPPROTO_TCP; } + uint32_t counter= 5; while (--counter) { - int e= getaddrinfo(server->hostname, str_port, &hints, &ai); + int e= getaddrinfo(server->hostname, str_port, &hints, &server->address_info); if (e == 0) { @@ -137,12 +147,7 @@ static memcached_return_t set_hostinfo(memcached_server_st *server) } } - if (server->address_info) - { - freeaddrinfo(server->address_info); - server->address_info= NULL; - } - server->address_info= ai; + server->address_info_next= server->address_info; return MEMCACHED_SUCCESS; } @@ -370,34 +375,29 @@ static memcached_return_t network_connect(memcached_server_st *ptr) { bool timeout_error_occured= false; - WATCHPOINT_ASSERT(ptr->fd == INVALID_SOCKET); WATCHPOINT_ASSERT(ptr->cursor_active == 0); - if (! ptr->options.sockaddr_inited || (!(ptr->root->flags.use_cache_lookups))) + if (! ptr->address_info) { - memcached_return_t rc; - - rc= set_hostinfo(ptr); + memcached_return_t rc= set_hostinfo(ptr); if (rc != MEMCACHED_SUCCESS) return rc; - ptr->options.sockaddr_inited= true; } - struct addrinfo *use= ptr->address_info; /* Create the socket */ - while (use != NULL) + while (ptr->address_info_next && ptr->fd == INVALID_SOCKET) { /* Memcache server does not support IPV6 in udp mode, so skip if not ipv4 */ - if (ptr->type == MEMCACHED_CONNECTION_UDP && use->ai_family != AF_INET) + if (ptr->type == MEMCACHED_CONNECTION_UDP && ptr->address_info_next->ai_family != AF_INET) { - use= use->ai_next; + ptr->address_info_next= ptr->address_info_next->ai_next; continue; } - if ((ptr->fd= socket(use->ai_family, - use->ai_socktype, - use->ai_protocol)) < 0) + if ((ptr->fd= socket(ptr->address_info_next->ai_family, + ptr->address_info_next->ai_socktype, + ptr->address_info_next->ai_protocol)) < 0) { ptr->cached_errno= get_socket_errno(); WATCHPOINT_ERRNO(get_socket_errno()); @@ -407,40 +407,43 @@ static memcached_return_t network_connect(memcached_server_st *ptr) (void)set_socket_options(ptr); /* connect to server */ - if ((connect(ptr->fd, use->ai_addr, use->ai_addrlen) != SOCKET_ERROR)) + if ((connect(ptr->fd, ptr->address_info_next->ai_addr, ptr->address_info_next->ai_addrlen) != SOCKET_ERROR)) { break; // Success } /* An error occurred */ ptr->cached_errno= get_socket_errno(); - if (ptr->cached_errno == EWOULDBLOCK || - ptr->cached_errno == EINPROGRESS || /* nonblocking mode - first return, */ - ptr->cached_errno == EALREADY) /* nonblocking mode - subsequent returns */ + switch (ptr->cached_errno) { - memcached_return_t rc; - rc= connect_poll(ptr); + case EWOULDBLOCK: + case EINPROGRESS: // nonblocking mode - first return + case EALREADY: // nonblocking mode - subsequent returns + { + memcached_return_t rc; + rc= connect_poll(ptr); - if (rc == MEMCACHED_TIMEOUT) - timeout_error_occured= true; + if (rc == MEMCACHED_TIMEOUT) + timeout_error_occured= true; - if (rc == MEMCACHED_SUCCESS) - break; - } - else if (get_socket_errno() == EISCONN) /* we are connected :-) */ - { + if (rc == MEMCACHED_SUCCESS) + break; + } + + case EISCONN: // we are connected :-) break; - } - else if (get_socket_errno() == EINTR) // Special case, we retry ai_addr - { + + case EINTR: // Special case, we retry ai_addr (void)closesocket(ptr->fd); ptr->fd= INVALID_SOCKET; continue; - } - (void)closesocket(ptr->fd); - ptr->fd= INVALID_SOCKET; - use= use->ai_next; + default: + (void)closesocket(ptr->fd); + ptr->fd= INVALID_SOCKET; + ptr->address_info_next= ptr->address_info_next->ai_next; + break; + } } if (ptr->fd == INVALID_SOCKET) diff --git a/libmemcached/constants.h b/libmemcached/constants.h index e2d69448..516e50ee 100644 --- a/libmemcached/constants.h +++ b/libmemcached/constants.h @@ -76,6 +76,7 @@ enum memcached_return_t { MEMCACHED_AUTH_CONTINUE, MEMCACHED_PARSE_ERROR, MEMCACHED_PARSE_USER_ERROR, + MEMCACHED_DEPRECATED, MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */ }; diff --git a/libmemcached/hash.c b/libmemcached/hash.c index bf946423..e5f87a75 100644 --- a/libmemcached/hash.c +++ b/libmemcached/hash.c @@ -172,20 +172,5 @@ memcached_return_t memcached_set_hashkit(memcached_st *self, hashkit_st *hashk) const char * libmemcached_string_hash(memcached_hash_t type) { - switch (type) - { - case MEMCACHED_HASH_DEFAULT: return "MEMCACHED_HASH_DEFAULT"; - case MEMCACHED_HASH_MD5: return "MEMCACHED_HASH_MD5"; - case MEMCACHED_HASH_CRC: return "MEMCACHED_HASH_CRC"; - case MEMCACHED_HASH_FNV1_64: return "MEMCACHED_HASH_FNV1_64"; - case MEMCACHED_HASH_FNV1A_64: return "MEMCACHED_HASH_FNV1A_64"; - case MEMCACHED_HASH_FNV1_32: return "MEMCACHED_HASH_FNV1_32"; - case MEMCACHED_HASH_FNV1A_32: return "MEMCACHED_HASH_FNV1A_32"; - case MEMCACHED_HASH_HSIEH: return "MEMCACHED_HASH_HSIEH"; - case MEMCACHED_HASH_MURMUR: return "MEMCACHED_HASH_MURMUR"; - case MEMCACHED_HASH_JENKINS: return "MEMCACHED_HASH_JENKINS"; - case MEMCACHED_HASH_CUSTOM: return "MEMCACHED_HASH_CUSTOM"; - default: - case MEMCACHED_HASH_MAX: return "INVALID memcached_hash_t"; - } + return libhashkit_string_hash((hashkit_hash_algorithm_t)type); } diff --git a/libmemcached/hosts.c b/libmemcached/hosts.c index d1fe29b8..65a4cd41 100644 --- a/libmemcached/hosts.c +++ b/libmemcached/hosts.c @@ -104,18 +104,11 @@ static int continuum_item_cmp(const void *t1, const void *t2) static memcached_return_t update_continuum(memcached_st *ptr) { - uint32_t host_index; uint32_t continuum_index= 0; - uint32_t value; memcached_server_st *list; - uint32_t pointer_index; uint32_t pointer_counter= 0; uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER; uint32_t pointer_per_hash= 1; - uint64_t total_weight= 0; - uint64_t is_ketama_weighted= 0; - uint64_t is_auto_ejecting= 0; - uint32_t points_per_server= 0; uint32_t live_servers= 0; struct timeval now; @@ -125,15 +118,15 @@ static memcached_return_t update_continuum(memcached_st *ptr) return MEMCACHED_ERRNO; } - list = memcached_server_list(ptr); + list= memcached_server_list(ptr); /* count live servers (those without a retry delay set) */ - is_auto_ejecting= _is_auto_eject_host(ptr); + bool is_auto_ejecting= _is_auto_eject_host(ptr); if (is_auto_ejecting) { live_servers= 0; ptr->ketama.next_distribution_rebuild= 0; - for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index) + for (uint32_t host_index= 0; host_index < memcached_server_count(ptr); ++host_index) { if (list[host_index].next_retry <= now.tv_sec) live_servers++; @@ -149,8 +142,8 @@ static memcached_return_t update_continuum(memcached_st *ptr) live_servers= memcached_server_count(ptr); } - is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); - points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER); + uint64_t is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); + uint32_t points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER); if (live_servers == 0) return MEMCACHED_SUCCESS; @@ -169,20 +162,19 @@ static memcached_return_t update_continuum(memcached_st *ptr) ptr->ketama.continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION; } + uint64_t total_weight= 0; if (is_ketama_weighted) { - for (host_index = 0; host_index < memcached_server_count(ptr); ++host_index) + for (uint32_t host_index = 0; host_index < memcached_server_count(ptr); ++host_index) { - if (list[host_index].weight == 0) - { - list[host_index].weight = 1; - } if (! is_auto_ejecting || list[host_index].next_retry <= now.tv_sec) + { total_weight += list[host_index].weight; + } } } - for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index) + for (uint32_t host_index= 0; host_index < memcached_server_count(ptr); ++host_index) { if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec) continue; @@ -204,7 +196,7 @@ static memcached_return_t update_continuum(memcached_st *ptr) if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY) { - for (pointer_index= 0; + for (uint32_t pointer_index= 0; pointer_index < pointer_per_server / pointer_per_hash; pointer_index++) { @@ -233,14 +225,14 @@ static memcached_return_t update_continuum(memcached_st *ptr) { for (uint32_t x= 0; x < pointer_per_hash; x++) { - value= ketama_server_hash(sort_host, (size_t)sort_host_length, x); - ptr->ketama.continuum[continuum_index].index= host_index; - ptr->ketama.continuum[continuum_index++].value= value; + uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x); + ptr->ketama.continuum[continuum_index].index= host_index; + ptr->ketama.continuum[continuum_index++].value= value; } } else { - value= hashkit_digest(&ptr->distribution_hashkit, sort_host, (size_t)sort_host_length); + uint32_t value= hashkit_digest(&ptr->distribution_hashkit, sort_host, (size_t)sort_host_length); ptr->ketama.continuum[continuum_index].index= host_index; ptr->ketama.continuum[continuum_index++].value= value; } @@ -248,7 +240,7 @@ static memcached_return_t update_continuum(memcached_st *ptr) } else { - for (pointer_index= 1; + for (uint32_t pointer_index= 1; pointer_index <= pointer_per_server / pointer_per_hash; pointer_index++) { @@ -282,14 +274,14 @@ static memcached_return_t update_continuum(memcached_st *ptr) { for (uint32_t x = 0; x < pointer_per_hash; x++) { - value= ketama_server_hash(sort_host, (size_t)sort_host_length, x); - ptr->ketama.continuum[continuum_index].index= host_index; - ptr->ketama.continuum[continuum_index++].value= value; + uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x); + ptr->ketama.continuum[continuum_index].index= host_index; + ptr->ketama.continuum[continuum_index++].value= value; } } else { - value= hashkit_digest(&ptr->distribution_hashkit, sort_host, (size_t)sort_host_length); + uint32_t value= hashkit_digest(&ptr->distribution_hashkit, sort_host, (size_t)sort_host_length); ptr->ketama.continuum[continuum_index].index= host_index; ptr->ketama.continuum[continuum_index++].value= value; } @@ -306,7 +298,7 @@ static memcached_return_t update_continuum(memcached_st *ptr) qsort(ptr->ketama.continuum, ptr->ketama.continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp); #ifdef DEBUG - for (pointer_index= 0; memcached_server_count(ptr) && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) + for (uint32_t pointer_index= 0; memcached_server_count(ptr) && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) { WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value); } diff --git a/libmemcached/memcached.c b/libmemcached/memcached.c index 149437af..3d2539eb 100644 --- a/libmemcached/memcached.c +++ b/libmemcached/memcached.c @@ -55,7 +55,6 @@ static const memcached_st global_copy= { .reuse_memory= false, .support_cas= false, .tcp_nodelay= false, - .use_cache_lookups= false, .use_sort_hosts= false, .use_udp= false, .verify_key= false, diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 311d5f26..10ff26df 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -212,35 +212,5 @@ uint32_t memcached_server_count(const memcached_st *); } // extern "C" #endif - -#ifdef __cplusplus -class Memcached : private memcached_st { -public: - - Memcached() - { - memcached_create(this); - } - - ~Memcached() - { - memcached_free(this); - } - - Memcached(const Memcached& source) - { - memcached_clone(this, &source); - } - - Memcached& operator=(const Memcached& source) - { - memcached_free(this); - memcached_clone(this, &source); - - return *this; - } -}; -#endif - #endif /* __LIBMEMCACHED_MEMCACHED_H__ */ diff --git a/libmemcached/memcached.hpp b/libmemcached/memcached.hpp index a8390262..55f96c7e 100644 --- a/libmemcached/memcached.hpp +++ b/libmemcached/memcached.hpp @@ -12,6 +12,7 @@ * @brief Libmemcached C++ interface */ +#pragma once #ifndef LIBMEMCACHEDPP_H #define LIBMEMCACHEDPP_H @@ -241,7 +242,7 @@ public: { ret_val.reserve(value_length); ret_val.assign(value, value + value_length); - key.assign(ret_key); + key.assign(ret_key, key_length); free(value); } else if (value) diff --git a/libmemcached/options/context.h b/libmemcached/options/context.h index 9e4ecb3a..d65f8ede 100644 --- a/libmemcached/options/context.h +++ b/libmemcached/options/context.h @@ -49,8 +49,10 @@ public: pos(0), memc(NULL), rc(rc_arg), + _is_server(false), _end(false) { + _hostname[0]= 0; buf= option_string; length= option_string_length; memc= memc_arg; @@ -71,6 +73,35 @@ public: _end= true; } + void set_server() + { + _is_server= true; + } + + void unset_server() + { + _is_server= false; + } + + bool is_server() + { + return _is_server; + } + + const char *set_hostname(const char *str, size_t size) + { + size_t copy_length= std::min((size_t)NI_MAXHOST, size); + memcpy(_hostname, str, copy_length); + _hostname[copy_length]= 0; + + return _hostname; + } + + const char *hostname() + { + return _hostname; + } + ~Context() { destroy_scanner(); @@ -89,5 +120,7 @@ protected: void destroy_scanner(); private: + bool _is_server; bool _end; + char _hostname[NI_MAXHOST]; }; diff --git a/libmemcached/options/include.am b/libmemcached/options/include.am index 067c387c..040c1c1e 100644 --- a/libmemcached/options/include.am +++ b/libmemcached/options/include.am @@ -22,3 +22,5 @@ libmemcached_libmemcached_la_SOURCES+= \ libmemcached/options/build.cc \ libmemcached/options/parser.cc \ libmemcached/options/scanner.cc + +include libmemcached/options/parser.am diff --git a/libmemcached/options/parser.am b/libmemcached/options/parser.am new file mode 100644 index 00000000..e69de29b diff --git a/libmemcached/options/parser.cc b/libmemcached/options/parser.cc index 8b7134a9..c5a671d5 100644 --- a/libmemcached/options/parser.cc +++ b/libmemcached/options/parser.cc @@ -148,58 +148,57 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error) AUTO_EJECT_HOSTS = 271, BINARY_PROTOCOL = 272, BUFFER_REQUESTS = 273, - CACHE_LOOKUPS = 274, - CONNECT_TIMEOUT = 275, - DISTRIBUTION = 276, - HASH = 277, - HASH_WITH_PREFIX_KEY = 278, - IO_BYTES_WATERMARK = 279, - IO_KEY_PREFETCH = 280, - IO_MSG_WATERMARK = 281, - KETAMA_HASH = 282, - KETAMA_WEIGHTED = 283, - NOREPLY = 284, - NUMBER_OF_REPLICAS = 285, - POLL_TIMEOUT = 286, - RANDOMIZE_REPLICA_READ = 287, - RCV_TIMEOUT = 288, - RETRY_TIMEOUT = 289, - SERVER_FAILURE_LIMIT = 290, - SND_TIMEOUT = 291, - SOCKET_RECV_SIZE = 292, - SOCKET_SEND_SIZE = 293, - SORT_HOSTS = 294, - SUPPORT_CAS = 295, - _TCP_NODELAY = 296, - _TCP_KEEPALIVE = 297, - _TCP_KEEPIDLE = 298, - USER_DATA = 299, - USE_UDP = 300, - VERIFY_KEY = 301, - PREFIX_KEY = 302, - MD5 = 303, - CRC = 304, - FNV1_64 = 305, - FNV1A_64 = 306, - FNV1_32 = 307, - FNV1A_32 = 308, - HSIEH = 309, - MURMUR = 310, - JENKINS = 311, - CONSISTENT = 312, - MODULA = 313, - RANDOM = 314, - TRUE = 315, - FALSE = 316, + CONNECT_TIMEOUT = 274, + DISTRIBUTION = 275, + HASH = 276, + HASH_WITH_PREFIX_KEY = 277, + IO_BYTES_WATERMARK = 278, + IO_KEY_PREFETCH = 279, + IO_MSG_WATERMARK = 280, + KETAMA_HASH = 281, + KETAMA_WEIGHTED = 282, + NOREPLY = 283, + NUMBER_OF_REPLICAS = 284, + POLL_TIMEOUT = 285, + RANDOMIZE_REPLICA_READ = 286, + RCV_TIMEOUT = 287, + RETRY_TIMEOUT = 288, + SERVER_FAILURE_LIMIT = 289, + SND_TIMEOUT = 290, + SOCKET_RECV_SIZE = 291, + SOCKET_SEND_SIZE = 292, + SORT_HOSTS = 293, + SUPPORT_CAS = 294, + _TCP_NODELAY = 295, + _TCP_KEEPALIVE = 296, + _TCP_KEEPIDLE = 297, + USER_DATA = 298, + USE_UDP = 299, + VERIFY_KEY = 300, + PREFIX_KEY = 301, + MD5 = 302, + CRC = 303, + FNV1_64 = 304, + FNV1A_64 = 305, + FNV1_32 = 306, + FNV1A_32 = 307, + HSIEH = 308, + MURMUR = 309, + JENKINS = 310, + CONSISTENT = 311, + MODULA = 312, + RANDOM = 313, + TRUE = 314, + FALSE = 315, + FLOAT = 316, NUMBER = 317, - FLOAT = 318, - HOSTNAME = 319, - HOSTNAME_WITH_PORT = 320, - IPADDRESS = 321, - IPADDRESS_WITH_PORT = 322, - STRING = 323, - QUOTED_STRING = 324, - FILE_PATH = 325 + PORT = 318, + WEIGHT_START = 319, + IPADDRESS = 320, + HOSTNAME = 321, + STRING = 322, + QUOTED_STRING = 323, + FILE_PATH = 324 }; #endif @@ -216,7 +215,7 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error) /* Line 264 of yacc.c */ -#line 220 "libmemcached/options/parser.cc" +#line 219 "libmemcached/options/parser.cc" #ifdef short # undef short @@ -429,22 +428,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 75 +#define YYFINAL 66 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 73 +#define YYLAST 72 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 74 +#define YYNTOKENS 73 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 12 /* YYNRULES -- Number of rules. */ -#define YYNRULES 70 +#define YYNRULES 65 /* YYNRULES -- Number of states. */ -#define YYNSTATES 86 +#define YYNSTATES 79 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 325 +#define YYMAXUTOK 324 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -455,10 +454,10 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 73, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 62, 2, 2, 2, 2, 2, + 2, 2, 72, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 61, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 63, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 62, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -483,8 +482,8 @@ static const yytype_uint8 yytranslate[] = 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 64, 65, 66, - 67, 68, 69, 70, 71, 72 + 55, 56, 57, 58, 59, 60, 63, 64, 65, 66, + 67, 68, 69, 70, 71 }; #if YYDEBUG @@ -493,47 +492,44 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint8 yyprhs[] = { 0, 0, 3, 5, 9, 11, 13, 15, 17, 19, - 21, 23, 27, 30, 33, 36, 38, 41, 44, 49, - 52, 55, 57, 59, 61, 63, 65, 67, 69, 71, - 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, - 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, - 113, 115, 119, 122, 124, 126, 129, 131, 133, 135, - 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, - 157 + 21, 23, 27, 32, 37, 40, 42, 45, 48, 53, + 56, 59, 61, 63, 65, 67, 69, 71, 73, 75, + 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99, 101, 103, 105, 107, 109, 111, 113, 114, + 116, 117, 119, 121, 123, 125, 127, 129, 131, 133, + 135, 137, 139, 141, 143, 145 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 75, 0, -1, 76, -1, 75, 73, 76, -1, 77, + 74, 0, -1, 75, -1, 74, 72, 75, -1, 76, -1, 3, -1, 10, -1, 4, -1, 5, -1, 6, - -1, 7, -1, 8, 73, 84, -1, 11, 82, -1, - 13, 81, -1, 9, 84, -1, 78, -1, 47, 84, - -1, 21, 85, -1, 21, 85, 62, 83, -1, 22, - 83, -1, 79, 64, -1, 80, -1, 44, -1, 20, - -1, 26, -1, 24, -1, 25, -1, 30, -1, 31, - -1, 33, -1, 34, -1, 35, -1, 36, -1, 37, - -1, 38, -1, 16, -1, 17, -1, 18, -1, 19, - -1, 23, -1, 28, -1, 29, -1, 32, -1, 39, - -1, 40, -1, 41, -1, 42, -1, 43, -1, 45, - -1, 46, -1, 82, -1, 81, 62, 82, -1, 67, - 64, -1, 66, -1, 70, -1, 69, 64, -1, 68, + -1, 7, -1, 8, 72, 83, -1, 11, 68, 80, + 81, -1, 11, 67, 80, 81, -1, 9, 83, -1, + 77, -1, 46, 83, -1, 20, 84, -1, 20, 84, + 61, 82, -1, 21, 82, -1, 78, 64, -1, 79, + -1, 43, -1, 19, -1, 25, -1, 23, -1, 24, + -1, 29, -1, 30, -1, 32, -1, 33, -1, 34, + -1, 35, -1, 36, -1, 37, -1, 16, -1, 17, + -1, 18, -1, 22, -1, 28, -1, 31, -1, 38, + -1, 39, -1, 40, -1, 41, -1, 42, -1, 44, + -1, 45, -1, -1, 65, -1, -1, 66, -1, 47, -1, 48, -1, 49, -1, 50, -1, 51, -1, 52, - -1, 53, -1, 54, -1, 55, -1, 56, -1, 70, - -1, 71, -1, 57, -1, 58, -1, 59, -1 + -1, 53, -1, 54, -1, 55, -1, 69, -1, 70, + -1, 56, -1, 57, -1, 58, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 157, 157, 158, 162, 164, 166, 168, 173, 178, - 182, 186, 197, 204, 207, 211, 215, 222, 229, 240, - 247, 254, 261, 267, 271, 275, 279, 283, 287, 291, - 295, 299, 303, 307, 311, 318, 322, 326, 330, 334, - 338, 342, 346, 350, 354, 358, 362, 366, 370, 374, - 381, 388, 398, 404, 410, 416, 422, 431, 435, 439, - 443, 447, 451, 455, 459, 463, 470, 474, 482, 486, - 490 + 0, 155, 155, 156, 160, 162, 164, 166, 171, 176, + 180, 184, 195, 203, 211, 215, 219, 226, 233, 244, + 251, 258, 265, 271, 275, 279, 283, 287, 291, 295, + 299, 303, 307, 311, 315, 322, 326, 330, 334, 338, + 342, 346, 350, 354, 358, 362, 366, 370, 377, 378, + 383, 384, 389, 393, 397, 401, 405, 409, 413, 417, + 421, 428, 432, 440, 444, 448 }; #endif @@ -546,21 +542,20 @@ static const char *const yytname[] = "PARSER_DEBUG", "INCLUDE", "CONFIGURE_FILE", "EMPTY_LINE", "SERVER", "SERVERS", "SERVERS_OPTION", "UNKNOWN_OPTION", "UNKNOWN", "AUTO_EJECT_HOSTS", "BINARY_PROTOCOL", "BUFFER_REQUESTS", - "CACHE_LOOKUPS", "CONNECT_TIMEOUT", "DISTRIBUTION", "HASH", - "HASH_WITH_PREFIX_KEY", "IO_BYTES_WATERMARK", "IO_KEY_PREFETCH", - "IO_MSG_WATERMARK", "KETAMA_HASH", "KETAMA_WEIGHTED", "NOREPLY", - "NUMBER_OF_REPLICAS", "POLL_TIMEOUT", "RANDOMIZE_REPLICA_READ", - "RCV_TIMEOUT", "RETRY_TIMEOUT", "SERVER_FAILURE_LIMIT", "SND_TIMEOUT", - "SOCKET_RECV_SIZE", "SOCKET_SEND_SIZE", "SORT_HOSTS", "SUPPORT_CAS", - "_TCP_NODELAY", "_TCP_KEEPALIVE", "_TCP_KEEPIDLE", "USER_DATA", - "USE_UDP", "VERIFY_KEY", "PREFIX_KEY", "MD5", "CRC", "FNV1_64", - "FNV1A_64", "FNV1_32", "FNV1A_32", "HSIEH", "MURMUR", "JENKINS", - "CONSISTENT", "MODULA", "RANDOM", "TRUE", "FALSE", "','", "'='", - "NUMBER", "FLOAT", "HOSTNAME", "HOSTNAME_WITH_PORT", "IPADDRESS", - "IPADDRESS_WITH_PORT", "STRING", "QUOTED_STRING", "FILE_PATH", "' '", + "CONNECT_TIMEOUT", "DISTRIBUTION", "HASH", "HASH_WITH_PREFIX_KEY", + "IO_BYTES_WATERMARK", "IO_KEY_PREFETCH", "IO_MSG_WATERMARK", + "KETAMA_HASH", "KETAMA_WEIGHTED", "NOREPLY", "NUMBER_OF_REPLICAS", + "POLL_TIMEOUT", "RANDOMIZE_REPLICA_READ", "RCV_TIMEOUT", "RETRY_TIMEOUT", + "SERVER_FAILURE_LIMIT", "SND_TIMEOUT", "SOCKET_RECV_SIZE", + "SOCKET_SEND_SIZE", "SORT_HOSTS", "SUPPORT_CAS", "_TCP_NODELAY", + "_TCP_KEEPALIVE", "_TCP_KEEPIDLE", "USER_DATA", "USE_UDP", "VERIFY_KEY", + "PREFIX_KEY", "MD5", "CRC", "FNV1_64", "FNV1A_64", "FNV1_32", "FNV1A_32", + "HSIEH", "MURMUR", "JENKINS", "CONSISTENT", "MODULA", "RANDOM", "TRUE", + "FALSE", "','", "'='", "FLOAT", "NUMBER", "PORT", "WEIGHT_START", + "IPADDRESS", "HOSTNAME", "STRING", "QUOTED_STRING", "FILE_PATH", "' '", "$accept", "begin", "statement", "expression", "behaviors", - "behavior_number", "behavior_boolean", "server_list", "server", "hash", - "string", "distribution", 0 + "behavior_number", "behavior_boolean", "optional_port", + "optional_weight", "hash", "string", "distribution", 0 }; #endif @@ -575,35 +570,33 @@ static const yytype_uint16 yytoknum[] = 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 44, 61, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 32 + 315, 44, 61, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 32 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 74, 75, 75, 76, 76, 76, 76, 76, 76, - 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, - 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 81, 81, 82, 82, 82, 82, 82, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 84, 84, 85, 85, - 85 + 0, 73, 74, 74, 75, 75, 75, 75, 75, 75, + 75, 75, 76, 76, 76, 76, 77, 77, 77, 77, + 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, + 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 83, 83, 84, 84, 84 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 3, 1, 1, 1, 1, 1, 1, - 1, 3, 2, 2, 2, 1, 2, 2, 4, 2, + 1, 3, 4, 4, 2, 1, 2, 2, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 2, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1 + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -612,44 +605,42 @@ static const yytype_uint8 yyr2[] = static const yytype_uint8 yydefact[] = { 0, 5, 7, 8, 9, 10, 0, 0, 6, 0, - 0, 35, 36, 37, 38, 23, 0, 0, 39, 25, - 26, 24, 40, 41, 27, 28, 42, 29, 30, 31, - 32, 33, 34, 43, 44, 45, 46, 47, 22, 48, - 49, 0, 0, 2, 4, 15, 0, 21, 0, 66, - 67, 14, 53, 0, 56, 0, 54, 12, 13, 50, - 68, 69, 70, 17, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 19, 16, 1, 0, 20, 11, 52, - 55, 0, 0, 3, 51, 18 + 35, 36, 37, 23, 0, 0, 38, 25, 26, 24, + 39, 27, 28, 40, 29, 30, 31, 32, 33, 34, + 41, 42, 43, 44, 45, 22, 46, 47, 0, 0, + 2, 4, 15, 0, 21, 0, 61, 62, 14, 48, + 48, 63, 64, 65, 17, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 19, 16, 1, 0, 20, 11, + 49, 50, 50, 0, 3, 51, 13, 12, 18 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 42, 43, 44, 45, 46, 47, 58, 57, 73, - 51, 63 + -1, 39, 40, 41, 42, 43, 44, 71, 76, 64, + 48, 54 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -63 +#define YYPACT_NINF -60 static const yytype_int8 yypact[] = { - -1, -63, -63, -63, -63, -63, -62, -57, -63, -7, - -7, -63, -63, -63, -63, -63, 9, 1, -63, -63, - -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -57, 0, -63, -63, -63, -38, -63, -57, -63, - -63, -63, -63, -17, -63, -16, -63, -63, 2, -63, - -63, -63, -63, 7, -63, -63, -63, -63, -63, -63, - -63, -63, -63, -63, -63, -63, -1, -63, -63, -63, - -63, -7, 1, -63, -63, -63 + -2, -60, -60, -60, -60, -60, -59, -45, -60, -11, + -60, -60, -60, -60, -46, -1, -60, -60, -60, -60, + -60, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, -60, -60, -60, -60, -60, -60, -60, -45, 0, + -60, -60, -60, -19, -60, -45, -60, -60, -60, -7, + -7, -60, -60, -60, 2, -60, -60, -60, -60, -60, + -60, -60, -60, -60, -60, -60, -60, -2, -60, -60, + -60, -6, -6, -1, -60, -60, -60, -60, -60 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -63, -63, -6, -63, -63, -63, -63, -63, -9, -11, - 17, -63 + -60, -60, -8, -60, -60, -60, -60, 11, -5, -9, + 17, -60 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -659,26 +650,26 @@ static const yytype_int8 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { - 75, 59, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 48, 10, 49, 50, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 77, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 79, 80, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 74, 52, - 53, 54, 55, 56, 81, 78, 60, 61, 62, 82, - 83, 85, 84, 76 + 66, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 51, 52, 53, 45, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 46, 47, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 68, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 65, 49, 50, 70, 74, + 75, 72, 69, 73, 78, 0, 0, 77, 0, 0, + 0, 0, 67 }; -static const yytype_uint8 yycheck[] = +static const yytype_int8 yycheck[] = { - 0, 10, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 73, 13, 70, 71, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 64, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 64, 64, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 41, 66, - 67, 68, 69, 70, 62, 48, 57, 58, 59, 62, - 76, 82, 81, 73 + 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 56, 57, 58, 72, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 69, 70, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 64, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 38, 67, 68, 65, 67, + 66, 50, 45, 61, 73, -1, -1, 72, -1, -1, + -1, -1, 72 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -686,14 +677,13 @@ static const yytype_uint8 yycheck[] = static const yytype_uint8 yystos[] = { 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 75, 76, 77, 78, 79, 80, 73, 70, - 71, 84, 66, 67, 68, 69, 70, 82, 81, 82, - 57, 58, 59, 85, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 83, 84, 0, 73, 64, 84, 64, - 64, 62, 62, 76, 82, 83 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 74, + 75, 76, 77, 78, 79, 72, 69, 70, 83, 67, + 68, 56, 57, 58, 84, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 82, 83, 0, 72, 64, 83, + 65, 80, 80, 61, 75, 66, 81, 81, 82 }; #define yyerrok (yyerrstatus = 0) @@ -1528,28 +1518,28 @@ yyreduce: case 4: /* Line 1464 of yacc.c */ -#line 163 "libmemcached/options/parser.yy" +#line 161 "libmemcached/options/parser.yy" { ;} break; case 5: /* Line 1464 of yacc.c */ -#line 165 "libmemcached/options/parser.yy" +#line 163 "libmemcached/options/parser.yy" { ;} break; case 6: /* Line 1464 of yacc.c */ -#line 167 "libmemcached/options/parser.yy" +#line 165 "libmemcached/options/parser.yy" { ;} break; case 7: /* Line 1464 of yacc.c */ -#line 169 "libmemcached/options/parser.yy" +#line 167 "libmemcached/options/parser.yy" { context->set_end(); YYACCEPT; @@ -1559,7 +1549,7 @@ yyreduce: case 8: /* Line 1464 of yacc.c */ -#line 174 "libmemcached/options/parser.yy" +#line 172 "libmemcached/options/parser.yy" { context->rc= MEMCACHED_PARSE_USER_ERROR; parser_abort(context, NULL); @@ -1569,7 +1559,7 @@ yyreduce: case 9: /* Line 1464 of yacc.c */ -#line 179 "libmemcached/options/parser.yy" +#line 177 "libmemcached/options/parser.yy" { memcached_reset(context->memc); ;} @@ -1578,7 +1568,7 @@ yyreduce: case 10: /* Line 1464 of yacc.c */ -#line 183 "libmemcached/options/parser.yy" +#line 181 "libmemcached/options/parser.yy" { yydebug= 1; ;} @@ -1587,7 +1577,7 @@ yyreduce: case 11: /* Line 1464 of yacc.c */ -#line 187 "libmemcached/options/parser.yy" +#line 185 "libmemcached/options/parser.yy" { if ((context->rc= memcached_parse_configure_file(context->memc, (yyvsp[(3) - (3)].string).c_str, (yyvsp[(3) - (3)].string).length)) != MEMCACHED_SUCCESS) { @@ -1599,27 +1589,33 @@ yyreduce: case 12: /* Line 1464 of yacc.c */ -#line 198 "libmemcached/options/parser.yy" - { - if ((context->rc= memcached_server_add_parsed(context->memc, (yyvsp[(2) - (2)].server).c_str, (yyvsp[(2) - (2)].server).length, (yyvsp[(2) - (2)].server).port, 0)) != MEMCACHED_SUCCESS) +#line 196 "libmemcached/options/parser.yy" + { + if ((context->rc= memcached_server_add_with_weight(context->memc, (yyvsp[(2) - (4)].server).c_str, (yyvsp[(2) - (4)].server).port, (yyvsp[(2) - (4)].server).weight)) != MEMCACHED_SUCCESS) { parser_abort(context, NULL); } + context->unset_server(); ;} break; case 13: /* Line 1464 of yacc.c */ -#line 205 "libmemcached/options/parser.yy" +#line 204 "libmemcached/options/parser.yy" { + if ((context->rc= memcached_server_add_with_weight(context->memc, (yyvsp[(2) - (4)].server).c_str, (yyvsp[(2) - (4)].server).port, (yyvsp[(2) - (4)].server).weight)) != MEMCACHED_SUCCESS) + { + parser_abort(context, NULL); + } + context->unset_server(); ;} break; case 14: /* Line 1464 of yacc.c */ -#line 208 "libmemcached/options/parser.yy" +#line 212 "libmemcached/options/parser.yy" { memcached_set_configuration_file(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).length); ;} @@ -1628,7 +1624,7 @@ yyreduce: case 16: /* Line 1464 of yacc.c */ -#line 216 "libmemcached/options/parser.yy" +#line 220 "libmemcached/options/parser.yy" { if ((context->rc= memcached_set_prefix_key(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).length)) != MEMCACHED_SUCCESS) { @@ -1640,7 +1636,7 @@ yyreduce: case 17: /* Line 1464 of yacc.c */ -#line 223 "libmemcached/options/parser.yy" +#line 227 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, (yyvsp[(2) - (2)].distribution))) != MEMCACHED_SUCCESS) { @@ -1652,7 +1648,7 @@ yyreduce: case 18: /* Line 1464 of yacc.c */ -#line 230 "libmemcached/options/parser.yy" +#line 234 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, (yyvsp[(2) - (4)].distribution))) != MEMCACHED_SUCCESS) { @@ -1668,7 +1664,7 @@ yyreduce: case 19: /* Line 1464 of yacc.c */ -#line 241 "libmemcached/options/parser.yy" +#line 245 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_HASH, (yyvsp[(2) - (2)].hash))) != MEMCACHED_SUCCESS) { @@ -1680,7 +1676,7 @@ yyreduce: case 20: /* Line 1464 of yacc.c */ -#line 248 "libmemcached/options/parser.yy" +#line 252 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, (yyvsp[(1) - (2)].behavior), (yyvsp[(2) - (2)].number))) != MEMCACHED_SUCCESS) { @@ -1692,7 +1688,7 @@ yyreduce: case 21: /* Line 1464 of yacc.c */ -#line 255 "libmemcached/options/parser.yy" +#line 259 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, (yyvsp[(1) - (1)].behavior), true)) != MEMCACHED_SUCCESS) { @@ -1704,7 +1700,7 @@ yyreduce: case 22: /* Line 1464 of yacc.c */ -#line 262 "libmemcached/options/parser.yy" +#line 266 "libmemcached/options/parser.yy" { ;} break; @@ -1712,7 +1708,7 @@ yyreduce: case 23: /* Line 1464 of yacc.c */ -#line 268 "libmemcached/options/parser.yy" +#line 272 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT; ;} @@ -1721,7 +1717,7 @@ yyreduce: case 24: /* Line 1464 of yacc.c */ -#line 272 "libmemcached/options/parser.yy" +#line 276 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK; ;} @@ -1730,7 +1726,7 @@ yyreduce: case 25: /* Line 1464 of yacc.c */ -#line 276 "libmemcached/options/parser.yy" +#line 280 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK; ;} @@ -1739,7 +1735,7 @@ yyreduce: case 26: /* Line 1464 of yacc.c */ -#line 280 "libmemcached/options/parser.yy" +#line 284 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH; ;} @@ -1748,7 +1744,7 @@ yyreduce: case 27: /* Line 1464 of yacc.c */ -#line 284 "libmemcached/options/parser.yy" +#line 288 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS; ;} @@ -1757,7 +1753,7 @@ yyreduce: case 28: /* Line 1464 of yacc.c */ -#line 288 "libmemcached/options/parser.yy" +#line 292 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_POLL_TIMEOUT; ;} @@ -1766,7 +1762,7 @@ yyreduce: case 29: /* Line 1464 of yacc.c */ -#line 292 "libmemcached/options/parser.yy" +#line 296 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_RCV_TIMEOUT; ;} @@ -1775,7 +1771,7 @@ yyreduce: case 30: /* Line 1464 of yacc.c */ -#line 296 "libmemcached/options/parser.yy" +#line 300 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT; ;} @@ -1784,7 +1780,7 @@ yyreduce: case 31: /* Line 1464 of yacc.c */ -#line 300 "libmemcached/options/parser.yy" +#line 304 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT; ;} @@ -1793,7 +1789,7 @@ yyreduce: case 32: /* Line 1464 of yacc.c */ -#line 304 "libmemcached/options/parser.yy" +#line 308 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SND_TIMEOUT; ;} @@ -1802,7 +1798,7 @@ yyreduce: case 33: /* Line 1464 of yacc.c */ -#line 308 "libmemcached/options/parser.yy" +#line 312 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE; ;} @@ -1811,7 +1807,7 @@ yyreduce: case 34: /* Line 1464 of yacc.c */ -#line 312 "libmemcached/options/parser.yy" +#line 316 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE; ;} @@ -1820,7 +1816,7 @@ yyreduce: case 35: /* Line 1464 of yacc.c */ -#line 319 "libmemcached/options/parser.yy" +#line 323 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS; ;} @@ -1829,7 +1825,7 @@ yyreduce: case 36: /* Line 1464 of yacc.c */ -#line 323 "libmemcached/options/parser.yy" +#line 327 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL; ;} @@ -1838,7 +1834,7 @@ yyreduce: case 37: /* Line 1464 of yacc.c */ -#line 327 "libmemcached/options/parser.yy" +#line 331 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS; ;} @@ -1847,312 +1843,243 @@ yyreduce: case 38: /* Line 1464 of yacc.c */ -#line 331 "libmemcached/options/parser.yy" +#line 335 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_CACHE_LOOKUPS; + (yyval.behavior)= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY; ;} break; case 39: /* Line 1464 of yacc.c */ -#line 335 "libmemcached/options/parser.yy" +#line 339 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY; + (yyval.behavior)= MEMCACHED_BEHAVIOR_NOREPLY; ;} break; case 40: /* Line 1464 of yacc.c */ -#line 339 "libmemcached/options/parser.yy" +#line 343 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED; + (yyval.behavior)= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ; ;} break; case 41: /* Line 1464 of yacc.c */ -#line 343 "libmemcached/options/parser.yy" +#line 347 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_NOREPLY; + (yyval.behavior)= MEMCACHED_BEHAVIOR_SORT_HOSTS; ;} break; case 42: /* Line 1464 of yacc.c */ -#line 347 "libmemcached/options/parser.yy" +#line 351 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ; + (yyval.behavior)= MEMCACHED_BEHAVIOR_SUPPORT_CAS; ;} break; case 43: /* Line 1464 of yacc.c */ -#line 351 "libmemcached/options/parser.yy" +#line 355 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_SORT_HOSTS; + (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_NODELAY; ;} break; case 44: /* Line 1464 of yacc.c */ -#line 355 "libmemcached/options/parser.yy" +#line 359 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_SUPPORT_CAS; + (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE; ;} break; case 45: /* Line 1464 of yacc.c */ -#line 359 "libmemcached/options/parser.yy" +#line 363 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_NODELAY; + (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE; ;} break; case 46: /* Line 1464 of yacc.c */ -#line 363 "libmemcached/options/parser.yy" +#line 367 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE; + (yyval.behavior)= MEMCACHED_BEHAVIOR_USE_UDP; ;} break; case 47: /* Line 1464 of yacc.c */ -#line 367 "libmemcached/options/parser.yy" +#line 371 "libmemcached/options/parser.yy" { - (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE; + (yyval.behavior)= MEMCACHED_BEHAVIOR_VERIFY_KEY; ;} break; case 48: /* Line 1464 of yacc.c */ -#line 371 "libmemcached/options/parser.yy" - { - (yyval.behavior)= MEMCACHED_BEHAVIOR_USE_UDP; - ;} +#line 377 "libmemcached/options/parser.yy" + { ;} break; case 49: /* Line 1464 of yacc.c */ -#line 375 "libmemcached/options/parser.yy" - { - (yyval.behavior)= MEMCACHED_BEHAVIOR_VERIFY_KEY; - ;} +#line 379 "libmemcached/options/parser.yy" + { ;} break; case 50: /* Line 1464 of yacc.c */ -#line 382 "libmemcached/options/parser.yy" - { - if ((context->rc= memcached_server_add_parsed(context->memc, (yyvsp[(1) - (1)].server).c_str, (yyvsp[(1) - (1)].server).length, (yyvsp[(1) - (1)].server).port, 0)) != MEMCACHED_SUCCESS) - { - parser_abort(context, NULL);; - } - ;} +#line 383 "libmemcached/options/parser.yy" + { ;} break; case 51: /* Line 1464 of yacc.c */ -#line 389 "libmemcached/options/parser.yy" - { - if ((context->rc= memcached_server_add_parsed(context->memc, (yyvsp[(3) - (3)].server).c_str, (yyvsp[(3) - (3)].server).length, (yyvsp[(3) - (3)].server).port, 0)) != MEMCACHED_SUCCESS) - { - parser_abort(context, NULL);; - } - ;} +#line 385 "libmemcached/options/parser.yy" + { ;} break; case 52: /* Line 1464 of yacc.c */ -#line 399 "libmemcached/options/parser.yy" - { - (yyval.server).c_str= (yyvsp[(1) - (2)].string).c_str; - (yyval.server).length= (yyvsp[(1) - (2)].string).length -1; // -1 to remove : - (yyval.server).port= (yyvsp[(2) - (2)].number); - ;} - break; - - case 53: - -/* Line 1464 of yacc.c */ -#line 405 "libmemcached/options/parser.yy" - { - (yyval.server).c_str= (yyvsp[(1) - (1)].string).c_str; - (yyval.server).length= (yyvsp[(1) - (1)].string).length; - (yyval.server).port= MEMCACHED_DEFAULT_PORT; - ;} - break; - - case 54: - -/* Line 1464 of yacc.c */ -#line 411 "libmemcached/options/parser.yy" - { - (yyval.server).c_str= (yyvsp[(1) - (1)].string).c_str; - (yyval.server).length= (yyvsp[(1) - (1)].string).length; - (yyval.server).port= MEMCACHED_DEFAULT_PORT; - ;} - break; - - case 55: - -/* Line 1464 of yacc.c */ -#line 417 "libmemcached/options/parser.yy" - { - (yyval.server).c_str= (yyvsp[(1) - (2)].string).c_str; - (yyval.server).length= (yyvsp[(1) - (2)].string).length -1; // -1 to remove : - (yyval.server).port= (yyvsp[(2) - (2)].number); - ;} - break; - - case 56: - -/* Line 1464 of yacc.c */ -#line 423 "libmemcached/options/parser.yy" - { - (yyval.server).c_str= (yyvsp[(1) - (1)].string).c_str; - (yyval.server).length= (yyvsp[(1) - (1)].string).length; - (yyval.server).port= MEMCACHED_DEFAULT_PORT; - ;} - break; - - case 57: - -/* Line 1464 of yacc.c */ -#line 432 "libmemcached/options/parser.yy" +#line 390 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_MD5; ;} break; - case 58: + case 53: /* Line 1464 of yacc.c */ -#line 436 "libmemcached/options/parser.yy" +#line 394 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_CRC; ;} break; - case 59: + case 54: /* Line 1464 of yacc.c */ -#line 440 "libmemcached/options/parser.yy" +#line 398 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1_64; ;} break; - case 60: + case 55: /* Line 1464 of yacc.c */ -#line 444 "libmemcached/options/parser.yy" +#line 402 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1A_64; ;} break; - case 61: + case 56: /* Line 1464 of yacc.c */ -#line 448 "libmemcached/options/parser.yy" +#line 406 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1_32; ;} break; - case 62: + case 57: /* Line 1464 of yacc.c */ -#line 452 "libmemcached/options/parser.yy" +#line 410 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1A_32; ;} break; - case 63: + case 58: /* Line 1464 of yacc.c */ -#line 456 "libmemcached/options/parser.yy" +#line 414 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_HSIEH; ;} break; - case 64: + case 59: /* Line 1464 of yacc.c */ -#line 460 "libmemcached/options/parser.yy" +#line 418 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_MURMUR; ;} break; - case 65: + case 60: /* Line 1464 of yacc.c */ -#line 464 "libmemcached/options/parser.yy" +#line 422 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_JENKINS; ;} break; - case 66: + case 61: /* Line 1464 of yacc.c */ -#line 471 "libmemcached/options/parser.yy" +#line 429 "libmemcached/options/parser.yy" { (yyval.string)= (yyvsp[(1) - (1)].string); ;} break; - case 67: + case 62: /* Line 1464 of yacc.c */ -#line 475 "libmemcached/options/parser.yy" +#line 433 "libmemcached/options/parser.yy" { (yyval.string).c_str= (yyvsp[(1) - (1)].string).c_str +1; // +1 to move use passed the initial quote (yyval.string).length= (yyvsp[(1) - (1)].string).length -1; // -1 removes the end quote ;} break; - case 68: + case 63: /* Line 1464 of yacc.c */ -#line 483 "libmemcached/options/parser.yy" +#line 441 "libmemcached/options/parser.yy" { (yyval.distribution)= MEMCACHED_DISTRIBUTION_CONSISTENT; ;} break; - case 69: + case 64: /* Line 1464 of yacc.c */ -#line 487 "libmemcached/options/parser.yy" +#line 445 "libmemcached/options/parser.yy" { (yyval.distribution)= MEMCACHED_DISTRIBUTION_MODULA; ;} break; - case 70: + case 65: /* Line 1464 of yacc.c */ -#line 491 "libmemcached/options/parser.yy" +#line 449 "libmemcached/options/parser.yy" { (yyval.distribution)= MEMCACHED_DISTRIBUTION_RANDOM; ;} @@ -2161,7 +2088,7 @@ yyreduce: /* Line 1464 of yacc.c */ -#line 2165 "libmemcached/options/parser.cc" +#line 2092 "libmemcached/options/parser.cc" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -2373,7 +2300,7 @@ yyreturn: /* Line 1684 of yacc.c */ -#line 496 "libmemcached/options/parser.yy" +#line 454 "libmemcached/options/parser.yy" void Context::start() diff --git a/libmemcached/options/parser.h b/libmemcached/options/parser.h index 99f682fd..f25789af 100644 --- a/libmemcached/options/parser.h +++ b/libmemcached/options/parser.h @@ -54,58 +54,57 @@ AUTO_EJECT_HOSTS = 271, BINARY_PROTOCOL = 272, BUFFER_REQUESTS = 273, - CACHE_LOOKUPS = 274, - CONNECT_TIMEOUT = 275, - DISTRIBUTION = 276, - HASH = 277, - HASH_WITH_PREFIX_KEY = 278, - IO_BYTES_WATERMARK = 279, - IO_KEY_PREFETCH = 280, - IO_MSG_WATERMARK = 281, - KETAMA_HASH = 282, - KETAMA_WEIGHTED = 283, - NOREPLY = 284, - NUMBER_OF_REPLICAS = 285, - POLL_TIMEOUT = 286, - RANDOMIZE_REPLICA_READ = 287, - RCV_TIMEOUT = 288, - RETRY_TIMEOUT = 289, - SERVER_FAILURE_LIMIT = 290, - SND_TIMEOUT = 291, - SOCKET_RECV_SIZE = 292, - SOCKET_SEND_SIZE = 293, - SORT_HOSTS = 294, - SUPPORT_CAS = 295, - _TCP_NODELAY = 296, - _TCP_KEEPALIVE = 297, - _TCP_KEEPIDLE = 298, - USER_DATA = 299, - USE_UDP = 300, - VERIFY_KEY = 301, - PREFIX_KEY = 302, - MD5 = 303, - CRC = 304, - FNV1_64 = 305, - FNV1A_64 = 306, - FNV1_32 = 307, - FNV1A_32 = 308, - HSIEH = 309, - MURMUR = 310, - JENKINS = 311, - CONSISTENT = 312, - MODULA = 313, - RANDOM = 314, - TRUE = 315, - FALSE = 316, + CONNECT_TIMEOUT = 274, + DISTRIBUTION = 275, + HASH = 276, + HASH_WITH_PREFIX_KEY = 277, + IO_BYTES_WATERMARK = 278, + IO_KEY_PREFETCH = 279, + IO_MSG_WATERMARK = 280, + KETAMA_HASH = 281, + KETAMA_WEIGHTED = 282, + NOREPLY = 283, + NUMBER_OF_REPLICAS = 284, + POLL_TIMEOUT = 285, + RANDOMIZE_REPLICA_READ = 286, + RCV_TIMEOUT = 287, + RETRY_TIMEOUT = 288, + SERVER_FAILURE_LIMIT = 289, + SND_TIMEOUT = 290, + SOCKET_RECV_SIZE = 291, + SOCKET_SEND_SIZE = 292, + SORT_HOSTS = 293, + SUPPORT_CAS = 294, + _TCP_NODELAY = 295, + _TCP_KEEPALIVE = 296, + _TCP_KEEPIDLE = 297, + USER_DATA = 298, + USE_UDP = 299, + VERIFY_KEY = 300, + PREFIX_KEY = 301, + MD5 = 302, + CRC = 303, + FNV1_64 = 304, + FNV1A_64 = 305, + FNV1_32 = 306, + FNV1A_32 = 307, + HSIEH = 308, + MURMUR = 309, + JENKINS = 310, + CONSISTENT = 311, + MODULA = 312, + RANDOM = 313, + TRUE = 314, + FALSE = 315, + FLOAT = 316, NUMBER = 317, - FLOAT = 318, - HOSTNAME = 319, - HOSTNAME_WITH_PORT = 320, - IPADDRESS = 321, - IPADDRESS_WITH_PORT = 322, - STRING = 323, - QUOTED_STRING = 324, - FILE_PATH = 325 + PORT = 318, + WEIGHT_START = 319, + IPADDRESS = 320, + HOSTNAME = 321, + STRING = 322, + QUOTED_STRING = 323, + FILE_PATH = 324 }; #endif diff --git a/libmemcached/options/scanner.cc b/libmemcached/options/scanner.cc index ecc818c0..cf32ffca 100644 --- a/libmemcached/options/scanner.cc +++ b/libmemcached/options/scanner.cc @@ -2,6 +2,7 @@ #line 22 "libmemcached/options/scanner.l" #pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wunused-parameter" #include @@ -14,7 +15,7 @@ -#line 18 "libmemcached/options/scanner.cc" +#line 19 "libmemcached/options/scanner.cc" #define YY_INT_ALIGNED short int @@ -448,8 +449,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); yyg->yy_c_buf_p = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 96 -#define YY_END_OF_BUFFER 97 +#define YY_NUM_RULES 90 +#define YY_END_OF_BUFFER 91 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -457,97 +458,92 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[811] = +static yyconst flex_int16_t yy_accept[769] = { 0, - 0, 0, 97, 95, 3, 3, 1, 95, 95, 2, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 95, 0, 94, 76, 0, 2, 93, 0, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 0, 4, - 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 0, 0, 0, 2, 89, - 0, 93, 81, 93, 72, 93, 93, 93, 93, 93, - 93, 80, 93, 93, 93, 93, 93, 93, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - - 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 90, 90, 0, 0, 0, 2, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, - 74, 76, 76, 76, 76, 76, 76, 76, 0, 0, - 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 0, 0, 93, 70, - 73, 75, 93, 0, 86, 93, 93, 93, 93, 93, - 69, 93, 76, 76, 76, 76, 76, 76, 76, 76, - 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, - 76, 76, 0, 0, 76, 76, 0, 0, 76, 76, - - 76, 0, 0, 0, 76, 0, 76, 0, 0, 93, - 0, 0, 0, 93, 93, 78, 87, 79, 93, 0, - 0, 76, 76, 76, 76, 76, 76, 0, 22, 0, - 0, 0, 0, 0, 0, 0, 76, 76, 76, 0, - 0, 76, 76, 0, 0, 76, 76, 0, 0, 76, - 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 92, 0, 93, 0, 0, 84, 82, 68, - 88, 71, 0, 0, 76, 76, 0, 0, 76, 76, - 76, 0, 0, 0, 0, 0, 0, 0, 0, 76, - 76, 76, 0, 0, 76, 76, 0, 0, 0, 0, - - 76, 0, 0, 76, 0, 0, 76, 0, 0, 0, - 0, 0, 0, 0, 0, 76, 92, 91, 93, 85, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 76, - 76, 76, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 76, - 0, 0, 0, 0, 0, 5, 76, 0, 0, 0, - 0, 0, 0, 0, 76, 0, 0, 0, 0, 65, - 0, 0, 64, 0, 0, 92, 93, 0, 0, 0, - 0, 0, 0, 0, 0, 76, 0, 0, 76, 0, + 0, 0, 91, 89, 5, 5, 1, 89, 89, 89, + 2, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 0, 88, 73, 0, 0, + 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, - 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 4, 87, 87, 2, + 3, 87, 78, 87, 69, 87, 87, 87, 87, 87, + 87, 77, 87, 87, 87, 87, 87, 87, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + + 73, 73, 73, 73, 73, 73, 73, 73, 73, 4, + 0, 87, 2, 3, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 71, 73, 73, + 73, 73, 73, 73, 0, 0, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 4, 87, 87, 3, 87, 67, 70, 72, 87, + 0, 83, 87, 87, 87, 87, 87, 66, 87, 73, + 73, 73, 73, 73, 73, 73, 0, 0, 0, 0, + 0, 0, 73, 73, 73, 73, 73, 0, 0, 73, + 73, 0, 0, 73, 73, 73, 0, 0, 0, 73, + + 0, 73, 4, 0, 87, 3, 87, 0, 87, 87, + 87, 87, 75, 84, 76, 87, 0, 0, 73, 73, + 73, 73, 73, 0, 21, 0, 0, 0, 0, 0, + 0, 0, 73, 73, 0, 0, 73, 73, 0, 0, + 73, 73, 0, 0, 73, 0, 0, 73, 0, 0, + 0, 0, 0, 0, 0, 0, 73, 4, 86, 87, + 87, 87, 87, 81, 79, 65, 85, 68, 0, 0, + 73, 73, 73, 73, 73, 0, 0, 0, 0, 0, + 0, 0, 0, 73, 73, 0, 0, 73, 73, 0, + 0, 0, 0, 73, 0, 0, 73, 0, 0, 73, + + 0, 0, 0, 0, 0, 0, 0, 0, 73, 86, + 87, 82, 80, 0, 0, 0, 0, 0, 0, 73, + 73, 73, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 0, 0, 0, 0, 0, 0, 73, 0, 0, + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0, 73, 0, 0, 0, 0, 62, 0, 0, 61, + 0, 0, 86, 87, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 73, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 0, 0, 76, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 73, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 62, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 60, 59, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 52, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, - 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 55, 54, 0, 0, 57, - 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, + + 0, 0, 0, 0, 50, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 52, 51, 0, 0, 54, + 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38, 37, + 0, 0, 0, 0, 44, 43, 0, 0, 0, 0, + + 0, 58, 0, 57, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 56, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 41, 40, 0, 0, 0, 0, 47, 46, - 0, 0, 0, 0, 0, 61, 0, 60, 0, 0, - 0, 0, 0, 0, 16, 15, 0, 0, 0, 0, - 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 37, 36, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 59, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 40, 39, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 12, 15, 14, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, 10, 19, - 0, 43, 42, 0, 0, 0, 0, 0, 0, 0, - 0, 12, 11, 14, 13, 18, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 32, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, - 9, 20, 19, 0, 0, 0, 28, 0, 0, 27, + 18, 0, 0, 0, 27, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 30, 0, 29, 0, 0, 0, - 0, 0, 0, 49, 51, 48, 50, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, - 25, 35, 34, 0, 0, 0, 0, 24, 23, 0, - - 0, 0, 0, 0, 0, 45, 44, 39, 38, 0 + 0, 0, 29, 0, 28, 0, 0, 0, 0, 0, + 0, 46, 48, 45, 47, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 24, 32, + 31, 0, 0, 0, 0, 23, 22, 0, 0, 0, + 0, 0, 0, 42, 41, 36, 35, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -556,16 +552,16 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 5, 6, 1, 1, 1, 1, 1, - 1, 1, 1, 7, 8, 9, 1, 10, 11, 12, - 13, 14, 15, 16, 10, 10, 10, 17, 1, 1, - 18, 1, 1, 1, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 1, 1, 1, 1, 45, 1, 46, 47, 48, 49, - - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 11, 11, 11, 18, 1, 1, + 19, 1, 20, 1, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 1, 1, 1, 1, 47, 1, 48, 49, 50, 51, + + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -582,461 +578,439 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[72] = +static yyconst flex_int32_t yy_meta[74] = { 0, - 1, 1, 2, 1, 1, 1, 1, 1, 3, 3, - 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, + 1, 1, 2, 1, 3, 1, 1, 3, 3, 1, + 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3 + 3, 3, 3 } ; -static yyconst flex_int16_t yy_base[817] = +static yyconst flex_int16_t yy_base[773] = { 0, - 0, 949, 919, 2202, 2202, 2202, 2202, 906, 902, 63, - 71, 79, 73, 65, 81, 66, 72, 114, 112, 130, - 123, 119, 906, 900, 898, 184, 247, 255, 121, 263, - 129, 263, 264, 269, 265, 271, 273, 275, 320, 322, - 327, 331, 332, 333, 340, 371, 380, 381, 899, 2202, - 429, 77, 379, 382, 131, 141, 169, 260, 345, 258, - 441, 447, 272, 276, 329, 489, 505, 513, 522, 2202, - 530, 530, 421, 532, 536, 537, 541, 570, 585, 590, - 595, 376, 605, 596, 640, 644, 646, 652, 324, 343, - 386, 398, 393, 389, 395, 463, 510, 516, 524, 526, - - 534, 527, 521, 524, 528, 587, 589, 581, 582, 596, - 603, 707, 715, 724, 732, 740, 749, 749, 750, 751, - 755, 645, 763, 762, 800, 802, 804, 812, 813, 833, - 822, 627, 651, 648, 648, 749, 645, 658, 848, 860, - 751, 754, 773, 777, 820, 825, 464, 821, 821, 465, - 852, 848, 853, 466, 884, 863, 912, 921, 921, 923, - 927, 928, 929, 94, 933, 977, 965, 983, 978, 987, - 998, 1000, 572, 876, 892, 918, 916, 925, 913, 1004, - 908, 929, 916, 960, 982, 971, 990, 993, 1016, 761, - 1015, 1011, 1013, 1014, 1010, 1032, 1018, 1019, 1036, 786, - - 1029, 1035, 1036, 1031, 964, 1033, 1049, 1092, 1100, 1060, - 105, 889, 886, 1101, 1102, 1100, 1109, 1110, 1111, 1099, - 1106, 1087, 1095, 1132, 1107, 1120, 1125, 1112, 2202, 1113, - 1117, 1124, 1151, 1140, 1140, 1159, 1166, 1156, 1151, 1150, - 1151, 1148, 1160, 1165, 1166, 1187, 1160, 1170, 1171, 1161, - 1174, 1175, 1166, 1181, 1173, 1184, 1175, 1187, 1199, 1200, - 1208, 1194, 1229, 1256, 1256, 887, 884, 2202, 2202, 1241, - 1242, 1263, 1226, 1227, 1239, 1242, 1226, 1231, 1224, 1238, - 1265, 1259, 1264, 1270, 889, 886, 1271, 808, 807, 1252, - 1252, 1290, 1273, 1280, 1300, 1282, 1279, 1280, 1276, 1277, - - 1321, 1286, 1293, 1317, 1295, 1297, 1294, 1310, 1318, 1320, - 1324, 1313, 1329, 1330, 1316, 1323, 1377, 2202, 1346, 2202, - 2202, 1330, 1331, 1322, 1335, 1335, 1336, 1351, 1362, 1361, - 1356, 1361, 1364, 1365, 1367, 1373, 1367, 1373, 1378, 1372, - 1373, 1374, 0, 1383, 1384, 1387, 1388, 1391, 1392, 1379, - 1402, 1403, 1401, 1405, 1409, 2202, 824, 1412, 1415, 1426, - 1420, 1425, 1414, 1417, 1450, 1430, 1443, 1433, 1446, 2202, - 1432, 1433, 2202, 1443, 1444, 1492, 1493, 1464, 1465, 1451, - 1454, 1469, 1488, 1482, 1483, 1495, 1482, 1483, 1484, 1497, - 1498, 833, 1489, 1508, 779, 1492, 1511, 1509, 1510, 1510, - - 1511, 1513, 1514, 1516, 1517, 1518, 1511, 1513, 1534, 1538, - 1551, 2202, 1553, 1541, 1542, 1553, 1554, 1555, 1556, 1542, - 1543, 1561, 1562, 1566, 1554, 1567, 1557, 1569, 1570, 1567, - 1568, 1602, 1557, 1560, 1567, 1590, 1589, 1591, 1599, 1600, - 1622, 1604, 1605, 1606, 784, 745, 1593, 1613, 1599, 1598, - 1618, 1604, 1616, 1617, 766, 726, 1612, 1613, 1604, 1605, - 1632, 1610, 1613, 1631, 1634, 1651, 1653, 1643, 1644, 1664, - 1654, 1666, 1656, 1652, 1653, 1672, 1673, 1663, 1672, 1676, - 1666, 1675, 1679, 2202, 2202, 1656, 1657, 669, 653, 1663, - 1664, 1664, 1665, 1667, 1669, 1687, 1708, 1703, 1705, 1704, - - 1705, 1706, 1722, 1718, 1720, 1725, 1721, 1723, 1722, 1723, - 1713, 1714, 1712, 1713, 678, 677, 1717, 1718, 1717, 1718, - 1724, 1725, 1730, 1732, 1727, 1748, 1748, 1768, 1751, 1771, - 2202, 2202, 1757, 1758, 1769, 1767, 1755, 1772, 1770, 1758, - 2202, 2202, 1776, 1777, 1771, 1772, 1783, 1784, 1774, 1775, - 1783, 1784, 1789, 1791, 1784, 1783, 1804, 1804, 1821, 1809, - 1809, 1825, 1813, 1824, 1825, 1829, 1830, 1816, 1817, 2202, - 2202, 1833, 1834, 675, 674, 1819, 1820, 1821, 1822, 631, - 622, 626, 606, 566, 540, 2202, 2202, 1822, 1840, 2202, - 1824, 1842, 2202, 1833, 1835, 1849, 1852, 1857, 1859, 1861, - - 1862, 1871, 1872, 1870, 1871, 558, 1882, 1883, 1884, 1870, - 1878, 1887, 1873, 1881, 1875, 1876, 1881, 1882, 542, 533, - 1883, 1884, 2202, 2202, 1881, 1882, 1886, 1888, 2202, 2202, - 1890, 1911, 1913, 1915, 1930, 2202, 1932, 2202, 1919, 1920, - 1925, 1926, 1922, 1923, 2202, 2202, 1939, 1940, 1925, 1926, - 2202, 1942, 1943, 1932, 1948, 1951, 1935, 1951, 1954, 1951, - 1953, 1948, 1951, 2202, 2202, 1972, 1974, 532, 494, 1983, - 1984, 1982, 1983, 1984, 1985, 2202, 2202, 1975, 1976, 1985, - 1986, 1980, 1981, 412, 411, 1981, 1982, 1994, 1995, 1992, - 1998, 1989, 1995, 2001, 1992, 2008, 2010, 2008, 2029, 2031, - - 2033, 2202, 2202, 419, 379, 2017, 2019, 2020, 2021, 2029, - 2030, 2202, 2202, 2202, 2202, 2202, 2202, 405, 404, 2026, - 2027, 2051, 403, 2042, 2053, 359, 2044, 2202, 2202, 2053, - 2054, 2055, 2056, 2048, 2049, 2057, 2058, 2059, 2061, 2202, - 2202, 2202, 2202, 326, 316, 2050, 2202, 333, 2053, 2202, - 327, 2091, 2093, 2095, 2096, 2090, 2091, 323, 301, 299, - 266, 2090, 2091, 2092, 2202, 2093, 2202, 2086, 2087, 193, - 146, 2094, 2095, 2202, 2202, 2202, 2202, 2104, 2105, 170, - 153, 152, 151, 2093, 2094, 2104, 2105, 2090, 2091, 2202, - 2202, 2202, 2202, 2112, 2113, 2100, 2102, 2202, 2202, 2124, - - 2145, 150, 149, 2144, 2146, 2202, 2202, 2202, 2202, 2202, - 2195, 119, 2198, 117, 116, 108 + 0, 798, 802, 2094, 2094, 2094, 2094, 778, 760, 726, + 65, 72, 0, 55, 50, 57, 71, 55, 62, 72, + 74, 78, 75, 63, 733, 716, 701, 132, 195, 103, + 208, 251, 215, 235, 228, 230, 237, 245, 265, 281, + 286, 294, 296, 311, 313, 327, 343, 354, 361, 370, + 702, 2094, 418, 63, 305, 71, 78, 89, 78, 246, + 291, 362, 361, 91, 113, 189, 419, 398, 483, 526, + 490, 416, 467, 503, 508, 510, 515, 517, 543, 551, + 558, 570, 577, 579, 591, 622, 599, 624, 209, 224, + 254, 277, 274, 306, 210, 311, 321, 323, 342, 337, + + 346, 349, 353, 376, 571, 401, 407, 419, 412, 639, + 672, 715, 758, 646, 635, 687, 670, 693, 695, 748, + 739, 704, 750, 776, 702, 782, 791, 784, 416, 432, + 436, 567, 469, 519, 779, 793, 524, 531, 533, 544, + 642, 292, 629, 628, 372, 641, 685, 702, 401, 780, + 721, 843, 856, 827, 864, 877, 879, 884, 886, 891, + 893, 900, 906, 912, 914, 920, 936, 943, 955, 485, + 741, 769, 769, 788, 776, 800, 818, 887, 888, 904, + 925, 916, 929, 943, 626, 941, 936, 932, 934, 933, + 954, 940, 941, 959, 707, 951, 957, 969, 946, 714, + + 948, 968, 1020, 1033, 1076, 2094, 1054, 1052, 1059, 1068, + 1070, 1095, 1100, 1102, 1111, 1120, 987, 999, 980, 988, + 1001, 1006, 1014, 1028, 2094, 1043, 1057, 1067, 1087, 1078, + 1081, 1100, 1098, 1095, 1095, 1096, 1093, 1105, 1114, 1115, + 731, 1108, 1119, 1121, 1111, 1124, 1127, 1118, 1141, 1133, + 1144, 1137, 1150, 1152, 1156, 1157, 1139, 2094, 1207, 1180, + 1189, 1197, 1220, 1225, 1234, 1240, 1242, 1247, 1160, 1174, + 803, 889, 1172, 1186, 1210, 1208, 1209, 1221, 682, 657, + 1232, 601, 590, 1213, 1011, 1232, 1234, 1252, 1237, 1235, + 1236, 1230, 1231, 1267, 1241, 1243, 1269, 1243, 1244, 1240, + + 1257, 1259, 1266, 1268, 1264, 1281, 1283, 1272, 1303, 1346, + 1331, 1317, 1325, 1290, 1292, 1284, 1285, 1303, 1305, 1308, + 1305, 1308, 1313, 1316, 1328, 1333, 1328, 1335, 1339, 1334, + 0, 1344, 1346, 1349, 1351, 1354, 1355, 1341, 1363, 1364, + 1361, 1362, 1369, 2094, 1371, 1374, 1375, 1381, 1390, 1364, + 1366, 1402, 1371, 1396, 1387, 1400, 2094, 1391, 1393, 2094, + 1404, 1405, 1432, 1434, 1415, 1421, 1407, 1413, 1428, 1432, + 1434, 1421, 1424, 1426, 1439, 1440, 627, 1431, 1449, 578, + 1435, 1454, 1450, 1451, 1457, 1458, 1460, 1462, 1464, 1455, + 1457, 1465, 1466, 1484, 1485, 1472, 1473, 1486, 1488, 1490, + + 1493, 1480, 1481, 1499, 1500, 1507, 1492, 1508, 1495, 1509, + 1510, 1514, 1516, 1562, 1506, 1512, 1518, 1524, 1523, 1524, + 1535, 1533, 1536, 1540, 615, 575, 1529, 1549, 1535, 1533, + 1552, 1538, 611, 567, 1546, 1548, 1539, 1540, 1582, 1550, + 1552, 1569, 1570, 1568, 1569, 1559, 1565, 1584, 1579, 1591, + 1581, 1577, 1578, 1598, 1602, 1594, 1604, 1609, 1599, 1608, + 1614, 2094, 2094, 1591, 1592, 566, 564, 1598, 1599, 1604, + 1606, 1622, 1623, 1618, 1619, 1619, 1620, 1624, 1640, 1641, + 1643, 1648, 1644, 1646, 1635, 1639, 1639, 1641, 587, 584, + 1646, 1647, 1646, 1649, 1655, 1656, 1660, 1661, 1659, 1661, + + 1660, 1679, 1663, 1682, 2094, 2094, 1669, 1671, 1685, 1683, + 1676, 1693, 1691, 1679, 2094, 2094, 1697, 1699, 1696, 1699, + 1711, 1713, 1710, 1711, 1718, 1719, 1711, 1708, 1709, 1713, + 1730, 1718, 1717, 1734, 1722, 1737, 1739, 1728, 1729, 2094, + 2094, 1750, 1751, 583, 572, 1736, 1737, 1738, 1740, 558, + 550, 553, 550, 499, 486, 2094, 2094, 1743, 1763, 2094, + 1748, 1767, 2094, 1758, 1759, 1774, 1775, 1760, 1761, 1769, + 1775, 1774, 1775, 509, 1786, 1788, 1789, 1776, 1785, 1797, + 1783, 1796, 1794, 1795, 508, 502, 1796, 1797, 2094, 2094, + 1795, 1799, 1804, 1806, 2094, 2094, 1807, 1808, 1809, 1812, + + 1827, 2094, 1828, 2094, 1815, 1816, 1826, 1828, 1824, 1825, + 1842, 1843, 1829, 1831, 2094, 1850, 1851, 1845, 1861, 1864, + 1848, 1864, 1868, 1861, 1864, 2094, 2094, 1866, 1868, 491, + 471, 1876, 1877, 1876, 1877, 1878, 1879, 2094, 2094, 1869, + 1875, 1885, 1886, 1880, 1882, 446, 442, 1882, 1884, 1897, + 1901, 1898, 1909, 1900, 1906, 1912, 1903, 1914, 1918, 1921, + 1923, 2094, 2094, 441, 381, 1908, 1909, 1910, 1913, 1921, + 1922, 2094, 2094, 2094, 2094, 2094, 2094, 386, 378, 1918, + 1919, 1948, 365, 1940, 1951, 349, 1942, 1952, 1953, 1955, + 1957, 1952, 1953, 1966, 1967, 1968, 1969, 2094, 2094, 2094, + + 2094, 300, 284, 1957, 2094, 306, 1959, 2094, 290, 1980, + 1983, 1985, 1987, 1980, 1981, 287, 274, 253, 252, 1982, + 1983, 1984, 2094, 1985, 2094, 1978, 1984, 240, 200, 1992, + 1993, 2094, 2094, 2094, 2094, 2002, 2004, 215, 196, 132, + 120, 1992, 1994, 2005, 2009, 1994, 2000, 2094, 2094, 2094, + 2094, 2021, 2022, 2008, 2009, 2094, 2094, 2030, 2034, 119, + 116, 2034, 2036, 2094, 2094, 2094, 2094, 2094, 2087, 126, + 2090, 113 } ; -static yyconst flex_int16_t yy_def[817] = +static yyconst flex_int16_t yy_def[773] = { 0, - 810, 1, 810, 810, 810, 810, 810, 811, 810, 812, - 812, 812, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 813, 811, 811, 810, 814, 812, 12, 814, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 813, 810, - 26, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 815, 816, 815, 812, 810, - 816, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 816, 815, 816, 816, 816, 812, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 51, 51, 51, 51, 51, 51, 51, 810, 810, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 816, 816, 12, 12, - 12, 12, 12, 810, 12, 12, 12, 12, 12, 12, - 12, 12, 51, 51, 51, 51, 51, 51, 51, 51, - 810, 810, 810, 810, 810, 810, 51, 51, 51, 51, - 51, 51, 810, 810, 51, 51, 810, 810, 51, 51, - - 51, 810, 810, 810, 51, 810, 51, 816, 816, 12, - 810, 810, 810, 12, 12, 12, 12, 12, 12, 810, - 810, 51, 51, 51, 51, 51, 51, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 51, 51, 51, 810, - 810, 51, 51, 810, 810, 51, 51, 810, 810, 51, - 810, 810, 51, 810, 810, 810, 810, 810, 810, 810, - 810, 51, 816, 816, 12, 810, 810, 810, 810, 12, - 12, 12, 810, 810, 51, 51, 810, 810, 51, 51, - 51, 810, 810, 810, 810, 810, 810, 810, 810, 51, - 51, 51, 810, 810, 51, 51, 810, 810, 810, 810, - - 51, 810, 810, 51, 810, 810, 51, 810, 810, 810, - 810, 810, 810, 810, 810, 51, 816, 810, 12, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 51, - 51, 51, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 51, 810, 810, 810, 810, 810, 810, 51, - 810, 810, 810, 810, 810, 810, 51, 810, 810, 810, - 810, 810, 810, 810, 51, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 816, 12, 810, 810, 810, - 810, 810, 810, 810, 810, 51, 810, 810, 51, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - - 810, 810, 810, 810, 810, 51, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 12, 810, 810, 810, 810, 810, 810, 810, 810, - 51, 810, 810, 51, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 51, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 51, - - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 51, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - - 810, 810, 810, 810, 810, 51, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - - 810, 810, 810, 810, 810, 810, 810, 810, 810, 0, - 810, 810, 810, 810, 810, 810 + 768, 1, 768, 768, 768, 768, 768, 769, 768, 768, + 770, 768, 770, 770, 770, 770, 770, 770, 770, 770, + 770, 770, 770, 770, 771, 769, 769, 768, 768, 772, + 772, 772, 768, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, + 771, 768, 28, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 768, 772, 772, 772, + 768, 772, 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + + 53, 53, 53, 53, 53, 53, 53, 53, 53, 768, + 772, 772, 772, 768, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 53, 53, + 53, 53, 53, 53, 768, 768, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 768, 772, 772, 768, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 772, 53, + 53, 53, 53, 53, 53, 53, 768, 768, 768, 768, + 768, 768, 53, 53, 53, 53, 53, 768, 768, 53, + 53, 768, 768, 53, 53, 53, 768, 768, 768, 53, + + 768, 53, 768, 772, 772, 768, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 768, 768, 53, 53, + 53, 53, 53, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 53, 53, 768, 768, 53, 53, 768, 768, + 53, 53, 768, 768, 53, 768, 768, 53, 768, 768, + 768, 768, 768, 768, 768, 768, 53, 768, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, 768, 768, + 53, 53, 53, 53, 53, 768, 768, 768, 768, 768, + 768, 768, 768, 53, 53, 768, 768, 53, 53, 768, + 768, 768, 768, 53, 768, 768, 53, 768, 768, 53, + + 768, 768, 768, 768, 768, 768, 768, 768, 53, 772, + 772, 772, 772, 768, 768, 768, 768, 768, 768, 53, + 53, 53, 768, 768, 768, 768, 768, 768, 768, 768, + 53, 768, 768, 768, 768, 768, 768, 53, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 53, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 772, 772, 768, 768, 768, 768, 768, 768, + 53, 768, 768, 53, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 53, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 772, 768, 768, 768, 768, 768, 768, + 53, 768, 768, 53, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 53, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 53, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 53, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 53, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 0, 768, 768, + 768, 768 } ; -static yyconst flex_int16_t yy_nxt[2274] = +static yyconst flex_int16_t yy_nxt[2168] = { 0, 4, 5, 6, 7, 8, 4, 7, 9, 4, 10, - 10, 10, 10, 10, 10, 10, 4, 7, 11, 11, - 12, 13, 14, 15, 11, 16, 17, 18, 11, 11, - 19, 11, 11, 11, 11, 20, 21, 22, 11, 11, - 11, 11, 11, 11, 4, 11, 11, 12, 13, 14, - 15, 11, 16, 17, 18, 11, 11, 19, 11, 11, - 11, 11, 20, 21, 22, 11, 11, 11, 11, 11, - 11, 27, 28, 28, 28, 28, 28, 28, 28, 30, - 31, 31, 31, 31, 31, 31, 31, 30, 31, 31, - 31, 31, 31, 31, 31, 34, 35, 29, 29, 37, - - 36, 29, 39, 40, 29, 29, 212, 29, 29, 213, - 116, 32, 38, 29, 33, 89, 29, 266, 113, 68, - 267, 29, 34, 35, 29, 29, 37, 36, 29, 39, - 40, 29, 29, 42, 29, 29, 41, 70, 32, 38, - 29, 33, 89, 29, 43, 47, 29, 29, 45, 29, - 44, 29, 46, 29, 48, 29, 29, 94, 29, 95, - 42, 29, 29, 41, 29, 29, 807, 806, 793, 792, - 791, 43, 47, 29, 29, 45, 29, 44, 29, 46, - 29, 48, 29, 29, 94, 29, 95, 790, 29, 29, - 785, 29, 29, 51, 51, 51, 51, 51, 51, 51, - - 784, 96, 52, 53, 54, 55, 51, 51, 51, 56, - 57, 51, 58, 51, 51, 59, 51, 60, 51, 61, - 62, 63, 64, 65, 51, 51, 51, 51, 96, 52, - 53, 54, 55, 51, 51, 51, 56, 57, 51, 58, - 51, 51, 59, 51, 60, 51, 61, 62, 63, 64, - 65, 51, 51, 51, 51, 66, 67, 67, 67, 67, - 67, 67, 67, 27, 69, 69, 69, 69, 69, 69, - 69, 66, 71, 71, 71, 71, 71, 71, 71, 70, - 70, 70, 97, 777, 73, 70, 75, 70, 74, 70, - 100, 70, 109, 101, 72, 29, 29, 29, 29, 29, - - 29, 29, 77, 29, 29, 29, 76, 29, 29, 97, - 29, 73, 110, 75, 78, 74, 776, 100, 775, 109, - 101, 72, 29, 29, 29, 29, 29, 29, 29, 77, - 29, 29, 29, 76, 29, 29, 70, 29, 70, 110, - 774, 78, 80, 70, 767, 82, 79, 70, 70, 70, - 765, 111, 29, 83, 29, 29, 70, 29, 81, 29, - 763, 132, 29, 29, 29, 29, 29, 29, 84, 80, - 762, 85, 29, 79, 133, 29, 750, 98, 111, 29, - 83, 29, 29, 99, 29, 81, 29, 70, 132, 29, - 29, 29, 29, 29, 29, 84, 70, 70, 85, 29, - - 92, 133, 29, 29, 98, 90, 29, 86, 29, 134, - 99, 29, 29, 29, 93, 87, 29, 91, 135, 88, - 747, 743, 742, 735, 136, 137, 734, 92, 717, 716, - 29, 138, 90, 29, 86, 29, 134, 70, 29, 29, - 29, 93, 87, 29, 91, 135, 88, 51, 51, 51, - 51, 136, 137, 29, 51, 51, 29, 51, 138, 102, - 51, 103, 51, 104, 51, 51, 51, 51, 51, 105, - 139, 193, 197, 202, 51, 51, 51, 51, 106, 107, - 29, 51, 51, 29, 51, 108, 102, 51, 103, 51, - 104, 51, 51, 51, 51, 51, 105, 66, 112, 112, - - 112, 112, 112, 112, 112, 106, 107, 140, 194, 198, - 203, 703, 108, 114, 115, 115, 115, 115, 115, 115, - 115, 66, 112, 112, 112, 112, 112, 112, 112, 70, - 27, 117, 117, 117, 117, 117, 117, 117, 71, 71, - 71, 71, 71, 71, 71, 71, 70, 141, 70, 702, - 665, 142, 70, 70, 143, 144, 145, 70, 146, 664, - 147, 148, 29, 149, 29, 29, 118, 29, 29, 120, - 119, 29, 29, 29, 141, 651, 29, 121, 142, 220, - 122, 143, 144, 145, 634, 146, 70, 147, 148, 29, - 149, 29, 29, 118, 29, 29, 120, 119, 29, 29, - - 29, 70, 29, 29, 121, 29, 70, 123, 150, 151, - 633, 70, 70, 632, 153, 154, 221, 29, 155, 124, - 29, 70, 29, 125, 152, 29, 127, 29, 29, 29, - 29, 29, 29, 631, 123, 150, 151, 29, 156, 630, - 29, 153, 154, 126, 29, 155, 124, 29, 629, 29, - 125, 152, 29, 127, 29, 29, 70, 29, 29, 173, - 70, 128, 70, 163, 29, 156, 129, 29, 70, 174, - 126, 175, 29, 176, 131, 29, 29, 29, 29, 29, - 29, 29, 179, 180, 29, 130, 173, 29, 128, 164, - 163, 624, 623, 129, 571, 570, 174, 544, 175, 29, - - 176, 131, 29, 29, 29, 29, 29, 29, 29, 179, - 180, 29, 130, 543, 29, 71, 71, 71, 71, 71, - 71, 71, 71, 66, 112, 112, 112, 112, 112, 112, - 112, 70, 71, 157, 157, 157, 157, 157, 157, 157, - 114, 158, 158, 158, 158, 158, 158, 158, 71, 71, - 71, 71, 71, 71, 71, 71, 70, 30, 117, 117, - 117, 117, 117, 117, 117, 70, 70, 70, 240, 187, - 512, 70, 177, 511, 160, 159, 188, 162, 70, 70, - 178, 29, 29, 29, 29, 29, 161, 29, 165, 502, - 29, 501, 189, 251, 29, 29, 187, 29, 29, 177, - - 166, 160, 159, 188, 162, 241, 190, 178, 29, 29, - 29, 29, 29, 161, 29, 165, 70, 29, 70, 189, - 70, 29, 29, 450, 29, 29, 167, 166, 70, 70, - 252, 168, 29, 190, 29, 29, 29, 29, 70, 29, - 447, 412, 169, 191, 170, 29, 192, 29, 29, 70, - 171, 340, 339, 167, 29, 172, 195, 29, 168, 29, - 196, 29, 29, 29, 29, 29, 29, 181, 29, 169, - 191, 170, 29, 192, 29, 29, 182, 171, 183, 184, - 199, 29, 172, 195, 29, 200, 201, 196, 185, 207, - 186, 204, 29, 337, 181, 29, 336, 321, 320, 269, - - 268, 50, 25, 182, 25, 183, 184, 199, 50, 26, - 25, 222, 200, 201, 223, 185, 207, 186, 810, 205, - 208, 209, 209, 209, 209, 209, 209, 209, 206, 114, - 71, 71, 71, 71, 71, 71, 71, 70, 222, 70, - 224, 223, 225, 70, 70, 70, 205, 226, 227, 70, - 231, 232, 233, 29, 23, 29, 29, 210, 29, 29, - 29, 29, 29, 29, 29, 29, 810, 224, 29, 225, - 810, 259, 810, 211, 226, 227, 810, 231, 232, 233, - 29, 70, 29, 29, 210, 29, 29, 29, 29, 29, - 29, 29, 29, 70, 70, 29, 215, 29, 214, 70, - - 29, 216, 234, 70, 235, 810, 810, 236, 260, 29, - 29, 228, 29, 217, 70, 29, 70, 218, 29, 29, - 237, 229, 29, 215, 29, 214, 238, 29, 216, 234, - 29, 235, 29, 29, 236, 219, 29, 29, 239, 29, - 217, 242, 29, 243, 218, 29, 29, 237, 230, 29, - 244, 245, 246, 238, 247, 248, 249, 29, 250, 29, - 29, 253, 219, 254, 256, 239, 255, 257, 242, 258, - 243, 261, 262, 810, 810, 810, 70, 244, 245, 246, - 810, 247, 248, 249, 810, 250, 810, 810, 253, 810, - 254, 256, 29, 255, 257, 29, 258, 265, 261, 262, - - 71, 263, 263, 263, 263, 263, 263, 263, 208, 264, - 264, 264, 264, 264, 264, 264, 70, 70, 70, 29, - 810, 273, 29, 270, 265, 70, 70, 70, 274, 275, - 276, 279, 29, 29, 29, 29, 29, 29, 271, 277, - 280, 29, 29, 29, 29, 29, 29, 272, 273, 810, - 270, 281, 282, 283, 284, 274, 275, 276, 279, 29, - 29, 29, 29, 29, 29, 271, 285, 280, 29, 29, - 29, 29, 29, 29, 272, 286, 278, 287, 281, 282, - 283, 284, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 285, 299, 301, 302, 303, 304, 305, - - 306, 307, 286, 308, 287, 309, 310, 311, 312, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 313, 314, 301, 302, 303, 304, 305, 306, 307, 315, - 308, 300, 309, 310, 311, 312, 316, 71, 317, 317, - 317, 317, 317, 317, 317, 318, 324, 313, 314, 326, - 810, 810, 810, 322, 323, 328, 315, 70, 70, 341, - 329, 810, 330, 316, 208, 71, 71, 71, 71, 71, - 71, 71, 70, 29, 29, 331, 29, 29, 319, 70, - 322, 323, 328, 325, 332, 333, 327, 329, 29, 330, - 334, 29, 335, 338, 343, 29, 342, 344, 29, 346, - - 29, 29, 331, 29, 29, 319, 347, 348, 350, 351, - 352, 332, 333, 353, 354, 29, 359, 334, 29, 335, - 338, 343, 29, 360, 361, 29, 346, 363, 355, 364, - 374, 365, 366, 347, 345, 350, 351, 352, 356, 367, - 353, 354, 368, 359, 349, 369, 370, 371, 372, 373, - 360, 810, 378, 379, 363, 380, 364, 357, 365, 366, - 810, 362, 70, 387, 810, 358, 367, 375, 381, 368, - 382, 383, 369, 370, 371, 372, 373, 377, 29, 378, - 379, 29, 380, 384, 357, 71, 376, 376, 376, 376, - 376, 376, 376, 318, 385, 381, 386, 382, 383, 389, - - 388, 390, 391, 392, 377, 29, 393, 394, 29, 395, - 384, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 385, 406, 386, 407, 408, 389, 409, 390, 391, - 392, 410, 411, 393, 394, 413, 395, 414, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 415, 406, - 420, 407, 408, 421, 409, 416, 417, 422, 410, 411, - 418, 419, 413, 424, 414, 425, 426, 810, 427, 428, - 429, 430, 431, 810, 810, 415, 810, 420, 810, 810, - 421, 810, 416, 417, 433, 434, 435, 418, 419, 436, - 424, 437, 425, 426, 423, 427, 428, 429, 430, 431, - - 71, 71, 71, 71, 71, 71, 71, 71, 318, 70, - 438, 433, 434, 435, 439, 440, 436, 441, 437, 442, - 443, 444, 445, 446, 448, 29, 449, 451, 29, 452, - 432, 453, 454, 455, 456, 457, 458, 438, 459, 460, - 461, 439, 440, 462, 441, 463, 442, 443, 444, 445, - 446, 448, 29, 449, 451, 29, 452, 432, 453, 454, - 455, 456, 457, 458, 464, 459, 460, 461, 465, 466, - 462, 467, 463, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 480, 478, 481, 483, 484, 485, 486, - 487, 464, 479, 482, 488, 465, 466, 489, 467, 490, - - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 480, 478, 481, 483, 484, 485, 486, 487, 70, 479, - 482, 488, 491, 492, 489, 493, 490, 494, 495, 496, - 498, 499, 500, 503, 29, 504, 505, 29, 506, 517, - 507, 508, 509, 510, 513, 514, 515, 516, 519, 491, - 492, 520, 493, 521, 494, 495, 522, 498, 499, 500, - 503, 29, 504, 505, 29, 506, 497, 507, 508, 509, - 510, 513, 514, 515, 516, 519, 518, 523, 520, 524, - 521, 525, 526, 522, 527, 528, 529, 530, 531, 532, - 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, - - 545, 546, 547, 548, 523, 549, 524, 550, 525, 526, - 551, 527, 528, 529, 530, 531, 532, 533, 534, 535, - 536, 537, 538, 539, 540, 541, 542, 545, 546, 547, - 548, 552, 549, 553, 550, 554, 555, 551, 556, 557, - 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, - 568, 569, 572, 573, 574, 575, 576, 577, 552, 578, - 553, 579, 554, 555, 580, 556, 557, 558, 559, 560, - 561, 562, 563, 564, 565, 566, 567, 568, 569, 572, - 573, 574, 575, 576, 577, 581, 578, 582, 579, 583, - 584, 580, 585, 586, 587, 588, 589, 590, 591, 592, - - 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, - 603, 604, 581, 605, 582, 606, 583, 584, 607, 585, - 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, - 596, 597, 598, 599, 600, 601, 602, 603, 604, 608, - 605, 609, 606, 610, 611, 607, 612, 613, 614, 615, - 616, 617, 618, 619, 620, 621, 622, 625, 626, 627, - 628, 635, 636, 637, 638, 639, 608, 640, 609, 641, - 610, 611, 642, 612, 613, 614, 615, 616, 617, 618, - 619, 620, 621, 622, 625, 626, 627, 628, 635, 636, - 637, 638, 639, 643, 640, 644, 641, 645, 646, 642, - - 647, 648, 649, 650, 652, 653, 654, 655, 656, 657, - 658, 659, 660, 661, 662, 663, 666, 667, 668, 669, - 643, 670, 644, 671, 645, 646, 672, 647, 648, 649, - 650, 652, 653, 654, 655, 656, 657, 658, 659, 660, - 661, 662, 663, 666, 667, 668, 669, 673, 670, 674, - 671, 675, 676, 672, 677, 678, 679, 680, 681, 682, - 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, - 693, 694, 695, 696, 673, 697, 674, 698, 675, 676, - 699, 677, 678, 679, 680, 681, 682, 683, 684, 685, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - - 696, 700, 697, 701, 698, 704, 705, 699, 706, 707, - 708, 709, 710, 711, 712, 713, 714, 715, 718, 719, - 720, 721, 722, 723, 724, 725, 726, 727, 700, 728, - 701, 729, 704, 705, 730, 706, 707, 708, 709, 710, - 711, 712, 713, 714, 715, 718, 719, 720, 721, 722, - 723, 724, 725, 726, 727, 731, 728, 732, 729, 733, - 736, 730, 737, 738, 739, 740, 741, 744, 745, 746, - 748, 749, 751, 752, 753, 754, 755, 756, 757, 758, - 759, 760, 731, 761, 732, 764, 733, 736, 766, 737, - 738, 739, 740, 741, 744, 745, 746, 748, 749, 751, - - 752, 753, 754, 755, 756, 757, 758, 759, 760, 768, - 761, 769, 764, 770, 771, 766, 772, 773, 778, 779, - 780, 781, 782, 783, 786, 787, 788, 789, 794, 795, - 796, 797, 798, 799, 800, 801, 768, 802, 769, 803, - 770, 771, 804, 772, 773, 778, 779, 780, 781, 782, - 783, 786, 787, 788, 789, 794, 795, 796, 797, 798, - 799, 800, 801, 805, 802, 808, 803, 809, 810, 804, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 805, 810, 808, 810, 809, 24, 810, 24, 49, 49, - - 49, 3, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810 + 11, 11, 11, 11, 11, 11, 11, 12, 7, 4, + 13, 13, 14, 15, 16, 17, 13, 18, 19, 20, + 13, 13, 21, 13, 13, 13, 13, 22, 23, 24, + 13, 13, 13, 13, 13, 13, 4, 13, 13, 14, + 15, 16, 17, 13, 18, 19, 20, 13, 13, 21, + 13, 13, 13, 13, 22, 23, 24, 13, 13, 13, + 13, 13, 13, 31, 36, 32, 32, 32, 32, 32, + 32, 32, 33, 33, 33, 33, 33, 33, 33, 34, + 37, 39, 35, 41, 38, 42, 43, 44, 47, 49, + + 50, 36, 48, 89, 40, 92, 93, 30, 45, 94, + 30, 30, 95, 107, 46, 68, 34, 37, 39, 35, + 41, 38, 42, 43, 44, 47, 49, 50, 30, 48, + 89, 40, 92, 93, 765, 45, 94, 764, 751, 95, + 107, 46, 53, 53, 53, 53, 53, 53, 53, 30, + 750, 108, 54, 55, 56, 57, 53, 53, 53, 58, + 59, 53, 53, 53, 53, 60, 53, 61, 53, 62, + 63, 64, 65, 66, 53, 53, 53, 53, 108, 54, + 55, 56, 57, 53, 53, 53, 58, 59, 53, 53, + 53, 53, 60, 53, 61, 53, 62, 63, 64, 65, + + 66, 53, 53, 53, 53, 67, 67, 67, 67, 67, + 67, 67, 30, 109, 749, 30, 30, 135, 69, 69, + 69, 69, 69, 69, 69, 71, 71, 71, 71, 71, + 71, 71, 30, 748, 30, 30, 30, 30, 30, 30, + 109, 30, 30, 30, 30, 30, 743, 742, 129, 30, + 73, 74, 30, 30, 30, 30, 136, 130, 30, 31, + 75, 70, 70, 70, 70, 70, 70, 70, 72, 30, + 735, 734, 30, 30, 30, 129, 30, 73, 74, 131, + 96, 30, 76, 30, 130, 30, 97, 75, 30, 30, + 30, 30, 733, 30, 30, 72, 77, 30, 30, 188, + + 30, 30, 30, 30, 30, 732, 131, 96, 725, 76, + 132, 30, 133, 97, 79, 30, 80, 30, 30, 30, + 30, 30, 78, 77, 723, 98, 82, 30, 99, 81, + 721, 30, 30, 90, 30, 30, 83, 132, 189, 133, + 30, 79, 30, 80, 134, 91, 720, 30, 137, 78, + 30, 30, 98, 138, 139, 99, 81, 30, 30, 30, + 90, 30, 30, 83, 84, 30, 140, 708, 30, 30, + 141, 134, 91, 30, 30, 137, 85, 30, 30, 192, + 138, 139, 100, 705, 101, 103, 102, 142, 143, 30, + 144, 84, 86, 140, 104, 105, 701, 141, 87, 145, + + 30, 106, 30, 85, 700, 30, 30, 30, 197, 100, + 88, 101, 103, 102, 142, 143, 30, 144, 193, 86, + 30, 104, 105, 30, 30, 87, 145, 693, 106, 110, + 110, 110, 110, 110, 110, 110, 148, 88, 53, 53, + 53, 53, 149, 150, 30, 53, 53, 198, 692, 151, + 170, 53, 171, 53, 115, 53, 53, 53, 53, 53, + 677, 172, 30, 148, 676, 53, 53, 53, 53, 149, + 150, 30, 53, 53, 30, 30, 151, 170, 53, 171, + 53, 115, 53, 53, 53, 53, 53, 30, 172, 663, + 30, 111, 217, 112, 112, 112, 112, 112, 112, 112, + + 114, 114, 114, 114, 114, 114, 114, 30, 175, 662, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 627, 30, 30, 30, 30, 30, 626, 615, 119, 30, + 30, 218, 600, 30, 31, 175, 113, 113, 113, 113, + 113, 113, 113, 116, 117, 599, 176, 30, 183, 30, + 30, 30, 184, 118, 30, 30, 30, 598, 30, 30, + 597, 30, 30, 30, 185, 30, 30, 120, 596, 186, + 116, 117, 30, 176, 30, 183, 595, 30, 30, 184, + 118, 30, 121, 30, 30, 30, 30, 30, 122, 30, + 590, 185, 173, 146, 120, 30, 186, 30, 30, 30, + + 174, 589, 541, 30, 30, 540, 30, 30, 147, 121, + 518, 124, 517, 486, 125, 122, 30, 123, 485, 173, + 146, 478, 477, 30, 430, 30, 30, 174, 30, 30, + 30, 30, 30, 235, 427, 147, 330, 30, 124, 30, + 127, 125, 30, 30, 123, 30, 126, 329, 128, 152, + 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, + 155, 155, 155, 156, 327, 187, 190, 127, 30, 191, + 30, 194, 236, 126, 30, 128, 30, 30, 30, 30, + 30, 30, 153, 153, 153, 153, 153, 153, 153, 326, + 156, 30, 187, 190, 30, 30, 191, 30, 194, 30, + + 30, 30, 30, 30, 52, 27, 30, 158, 30, 30, + 30, 30, 30, 157, 246, 160, 30, 159, 30, 30, + 27, 254, 30, 111, 195, 154, 154, 154, 154, 154, + 154, 154, 164, 30, 158, 52, 167, 196, 292, 30, + 157, 161, 160, 30, 159, 29, 30, 30, 30, 202, + 30, 195, 30, 247, 30, 30, 30, 30, 30, 164, + 255, 30, 30, 167, 196, 30, 30, 28, 113, 113, + 113, 113, 113, 113, 113, 162, 202, 293, 219, 163, + 30, 165, 27, 30, 30, 30, 30, 199, 30, 30, + 30, 30, 30, 220, 30, 30, 30, 221, 30, 30, + + 177, 768, 162, 25, 30, 219, 163, 224, 165, 178, + 316, 179, 222, 223, 180, 169, 166, 200, 225, 768, + 220, 168, 30, 181, 221, 182, 201, 177, 30, 768, + 30, 30, 768, 768, 30, 111, 178, 30, 179, 222, + 223, 180, 169, 166, 200, 768, 226, 768, 168, 317, + 181, 768, 182, 203, 203, 203, 203, 203, 203, 203, + 30, 768, 227, 30, 204, 768, 205, 205, 205, 205, + 205, 205, 205, 30, 206, 206, 206, 206, 206, 206, + 206, 30, 768, 30, 30, 30, 30, 30, 30, 227, + 30, 30, 30, 30, 30, 30, 318, 30, 30, 30, + + 30, 30, 30, 768, 30, 768, 209, 30, 30, 210, + 30, 228, 768, 30, 30, 207, 30, 768, 30, 30, + 30, 30, 30, 30, 30, 30, 229, 30, 30, 211, + 30, 768, 30, 768, 213, 319, 768, 208, 228, 30, + 30, 768, 207, 30, 30, 212, 30, 30, 230, 231, + 30, 30, 30, 229, 232, 768, 211, 214, 30, 30, + 30, 213, 30, 30, 233, 768, 30, 234, 215, 237, + 238, 239, 212, 240, 768, 230, 231, 241, 242, 243, + 244, 232, 30, 245, 214, 248, 253, 249, 256, 30, + 250, 233, 216, 257, 234, 215, 237, 238, 239, 251, + + 240, 30, 252, 768, 241, 242, 243, 244, 768, 768, + 245, 269, 248, 253, 249, 256, 768, 250, 332, 216, + 257, 768, 768, 270, 271, 272, 251, 273, 274, 252, + 258, 258, 258, 258, 258, 258, 258, 30, 269, 768, + 30, 30, 275, 259, 259, 259, 259, 259, 259, 259, + 270, 271, 272, 768, 273, 274, 30, 333, 30, 30, + 30, 30, 30, 30, 768, 262, 30, 30, 263, 275, + 276, 264, 30, 768, 30, 30, 30, 30, 30, 30, + 30, 768, 265, 30, 204, 277, 260, 260, 260, 260, + 260, 260, 260, 261, 266, 768, 278, 276, 30, 30, + + 30, 768, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 279, 277, 280, 30, 30, 30, 281, 30, 30, + 261, 266, 30, 278, 30, 282, 283, 30, 30, 284, + 768, 768, 285, 267, 286, 287, 288, 289, 279, 768, + 280, 30, 290, 291, 281, 294, 30, 295, 30, 296, + 297, 298, 282, 283, 299, 300, 284, 30, 268, 285, + 267, 286, 287, 288, 289, 301, 30, 302, 303, 290, + 291, 304, 294, 305, 295, 306, 296, 297, 298, 307, + 308, 299, 300, 309, 30, 268, 768, 30, 204, 314, + 768, 768, 301, 30, 302, 303, 30, 30, 304, 768, + + 305, 30, 306, 315, 30, 30, 307, 308, 768, 312, + 309, 30, 320, 311, 30, 30, 314, 310, 310, 310, + 310, 310, 310, 310, 30, 321, 30, 30, 30, 30, + 315, 322, 30, 30, 313, 30, 323, 324, 30, 320, + 311, 30, 30, 30, 30, 325, 30, 30, 30, 30, + 30, 30, 321, 30, 30, 30, 328, 331, 322, 336, + 334, 768, 335, 323, 324, 338, 30, 339, 340, 341, + 342, 30, 325, 346, 343, 347, 348, 350, 351, 352, + 30, 353, 354, 328, 331, 344, 30, 334, 30, 335, + 355, 356, 338, 30, 339, 340, 341, 342, 337, 357, + + 346, 358, 347, 359, 350, 351, 352, 360, 353, 354, + 361, 768, 372, 345, 365, 349, 366, 355, 356, 367, + 368, 30, 768, 768, 30, 30, 357, 768, 358, 30, + 359, 768, 30, 30, 360, 30, 768, 768, 30, 30, + 369, 365, 370, 366, 768, 371, 367, 368, 374, 362, + 30, 373, 375, 30, 30, 376, 363, 363, 363, 363, + 363, 363, 363, 30, 364, 768, 377, 369, 378, 370, + 379, 30, 371, 380, 381, 374, 382, 30, 383, 375, + 384, 385, 376, 386, 387, 388, 389, 390, 391, 392, + 393, 364, 30, 377, 394, 378, 395, 379, 396, 397, + + 380, 381, 402, 382, 403, 383, 406, 384, 385, 404, + 386, 387, 388, 389, 390, 391, 392, 393, 398, 399, + 407, 394, 408, 395, 409, 396, 397, 400, 401, 402, + 410, 403, 411, 406, 412, 413, 30, 415, 30, 30, + 30, 30, 30, 416, 417, 398, 399, 407, 405, 408, + 418, 409, 419, 768, 400, 401, 420, 410, 421, 411, + 422, 412, 413, 423, 415, 424, 425, 426, 428, 429, + 416, 417, 431, 414, 432, 433, 434, 418, 30, 419, + 30, 435, 436, 420, 437, 421, 438, 422, 439, 440, + 423, 441, 424, 425, 426, 428, 429, 442, 443, 431, + + 414, 432, 433, 434, 444, 445, 446, 447, 435, 436, + 448, 437, 449, 438, 450, 439, 440, 451, 441, 452, + 453, 454, 455, 458, 442, 443, 461, 456, 459, 462, + 463, 444, 445, 446, 447, 457, 460, 448, 464, 449, + 465, 450, 472, 768, 451, 466, 452, 453, 454, 455, + 458, 467, 468, 461, 456, 459, 462, 463, 469, 470, + 471, 474, 457, 460, 475, 464, 30, 465, 476, 30, + 30, 479, 466, 480, 481, 482, 483, 484, 467, 468, + 487, 473, 488, 489, 490, 469, 470, 471, 474, 491, + 493, 475, 494, 495, 496, 476, 497, 498, 479, 499, + + 480, 481, 482, 483, 484, 500, 501, 487, 30, 488, + 489, 490, 502, 503, 504, 505, 506, 493, 507, 494, + 495, 496, 508, 497, 498, 509, 499, 510, 492, 511, + 512, 513, 500, 501, 514, 515, 516, 519, 520, 502, + 503, 504, 505, 506, 521, 507, 522, 523, 524, 508, + 525, 526, 509, 527, 510, 528, 511, 512, 513, 529, + 530, 514, 515, 516, 519, 520, 531, 532, 533, 534, + 535, 521, 536, 522, 523, 524, 537, 525, 526, 538, + 527, 539, 528, 542, 543, 544, 529, 530, 545, 546, + 547, 548, 549, 531, 532, 533, 534, 535, 550, 536, + + 551, 552, 553, 537, 554, 555, 538, 556, 539, 557, + 542, 543, 544, 558, 559, 545, 546, 547, 548, 549, + 560, 561, 562, 563, 564, 550, 565, 551, 552, 553, + 566, 554, 555, 567, 556, 568, 557, 569, 570, 571, + 558, 559, 572, 573, 574, 575, 576, 560, 561, 562, + 563, 564, 577, 565, 578, 579, 580, 566, 581, 582, + 567, 583, 568, 584, 569, 570, 571, 585, 586, 572, + 573, 574, 575, 576, 587, 588, 591, 592, 593, 577, + 594, 578, 579, 580, 601, 581, 582, 602, 583, 603, + 584, 604, 605, 606, 585, 586, 607, 608, 609, 610, + + 611, 587, 588, 591, 592, 593, 612, 594, 613, 614, + 616, 601, 617, 618, 602, 619, 603, 620, 604, 605, + 606, 621, 622, 607, 608, 609, 610, 611, 623, 624, + 625, 628, 629, 612, 630, 613, 614, 616, 631, 617, + 618, 632, 619, 633, 620, 634, 635, 636, 621, 622, + 637, 638, 639, 640, 641, 623, 624, 625, 628, 629, + 642, 630, 643, 644, 645, 631, 646, 647, 632, 648, + 633, 649, 634, 635, 636, 650, 651, 637, 638, 639, + 640, 641, 652, 653, 654, 655, 656, 642, 657, 643, + 644, 645, 658, 646, 647, 659, 648, 660, 649, 661, + + 664, 665, 650, 651, 666, 667, 668, 669, 670, 652, + 653, 654, 655, 656, 671, 657, 672, 673, 674, 658, + 675, 678, 659, 679, 660, 680, 661, 664, 665, 681, + 682, 666, 667, 668, 669, 670, 683, 684, 685, 686, + 687, 671, 688, 672, 673, 674, 689, 675, 678, 690, + 679, 691, 680, 694, 695, 696, 681, 682, 697, 698, + 699, 702, 703, 683, 684, 685, 686, 687, 704, 688, + 706, 707, 709, 689, 710, 711, 690, 712, 691, 713, + 694, 695, 696, 714, 715, 697, 698, 699, 702, 703, + 716, 717, 718, 719, 722, 704, 724, 706, 707, 709, + + 726, 710, 711, 727, 712, 728, 713, 729, 730, 731, + 714, 715, 736, 737, 738, 739, 740, 716, 717, 718, + 719, 722, 741, 724, 744, 745, 746, 726, 747, 752, + 727, 753, 728, 754, 729, 730, 731, 755, 756, 736, + 737, 738, 739, 740, 757, 758, 759, 760, 761, 741, + 762, 744, 745, 746, 763, 747, 752, 766, 753, 767, + 754, 768, 768, 768, 755, 756, 768, 768, 768, 768, + 768, 757, 758, 759, 760, 761, 768, 762, 768, 768, + 768, 763, 768, 768, 766, 768, 767, 26, 768, 26, + 51, 51, 51, 3, 768, 768, 768, 768, 768, 768, + + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768 } ; -static yyconst flex_int16_t yy_chk[2274] = +static yyconst flex_int16_t yy_chk[2168] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1045,264 +1019,250 @@ static yyconst flex_int16_t yy_chk[2274] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 10, 10, 10, 10, 10, 10, 10, 10, 11, - 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, - 12, 12, 12, 12, 12, 13, 14, 14, 16, 15, - - 14, 16, 16, 17, 17, 13, 164, 17, 13, 164, - 816, 12, 15, 15, 12, 52, 15, 211, 815, 814, - 211, 812, 13, 14, 14, 16, 15, 14, 16, 16, - 17, 17, 13, 19, 17, 13, 18, 29, 12, 15, - 15, 12, 52, 15, 19, 21, 18, 19, 20, 18, - 19, 22, 20, 29, 22, 21, 29, 55, 21, 56, - 19, 31, 20, 18, 31, 20, 803, 802, 783, 782, - 781, 19, 21, 18, 19, 20, 18, 19, 22, 20, - 29, 22, 21, 29, 55, 21, 56, 780, 31, 20, - 771, 31, 20, 26, 26, 26, 26, 26, 26, 26, - - 770, 57, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 57, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, - 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, - 28, 30, 30, 30, 30, 30, 30, 30, 30, 32, - 33, 35, 58, 761, 33, 34, 35, 36, 34, 37, - 60, 38, 63, 60, 32, 32, 33, 35, 32, 33, - - 35, 34, 37, 36, 34, 37, 36, 38, 37, 58, - 38, 33, 64, 35, 38, 34, 760, 60, 759, 63, - 60, 32, 32, 33, 35, 32, 33, 35, 34, 37, - 36, 34, 37, 36, 38, 37, 39, 38, 40, 64, - 758, 38, 40, 41, 751, 42, 39, 42, 43, 44, - 748, 65, 39, 43, 40, 39, 45, 40, 41, 41, - 745, 89, 41, 42, 43, 44, 42, 43, 44, 40, - 744, 45, 45, 39, 90, 45, 726, 59, 65, 39, - 43, 40, 39, 59, 40, 41, 41, 46, 89, 41, - 42, 43, 44, 42, 43, 44, 47, 48, 45, 45, - - 54, 90, 45, 46, 59, 53, 46, 46, 82, 91, - 59, 82, 47, 48, 54, 47, 48, 53, 92, 48, - 723, 719, 718, 705, 93, 94, 704, 54, 685, 684, - 46, 95, 53, 46, 46, 82, 91, 73, 82, 47, - 48, 54, 47, 48, 53, 92, 48, 51, 51, 51, - 51, 93, 94, 73, 51, 51, 73, 51, 95, 61, - 51, 61, 51, 61, 51, 51, 51, 51, 51, 62, - 96, 147, 150, 154, 51, 51, 51, 51, 62, 62, - 73, 51, 51, 73, 51, 62, 61, 51, 61, 51, - 61, 51, 51, 51, 51, 51, 62, 66, 66, 66, - - 66, 66, 66, 66, 66, 62, 62, 96, 147, 150, - 154, 669, 62, 67, 67, 67, 67, 67, 67, 67, - 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 69, 69, 69, 69, 69, 69, 69, 69, 71, 71, - 71, 71, 71, 71, 71, 71, 72, 97, 74, 668, - 620, 98, 75, 76, 99, 100, 101, 77, 102, 619, - 103, 104, 72, 105, 74, 72, 72, 74, 75, 76, - 74, 75, 76, 77, 97, 606, 77, 77, 98, 173, - 78, 99, 100, 101, 585, 102, 78, 103, 104, 72, - 105, 74, 72, 72, 74, 75, 76, 74, 75, 76, - - 77, 79, 78, 77, 77, 78, 80, 79, 106, 107, - 584, 81, 84, 583, 108, 109, 173, 79, 110, 80, - 79, 83, 80, 81, 107, 80, 84, 81, 84, 78, - 81, 84, 78, 582, 79, 106, 107, 83, 111, 581, - 83, 108, 109, 83, 79, 110, 80, 79, 580, 80, - 81, 107, 80, 84, 81, 84, 85, 81, 84, 132, - 86, 85, 87, 122, 83, 111, 86, 83, 88, 133, - 83, 134, 85, 135, 88, 85, 86, 122, 87, 86, - 122, 87, 137, 138, 88, 87, 132, 88, 85, 122, - 122, 575, 574, 86, 516, 515, 133, 489, 134, 85, - - 135, 88, 85, 86, 122, 87, 86, 122, 87, 137, - 138, 88, 87, 488, 88, 112, 112, 112, 112, 112, - 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 114, 114, 114, 114, 114, 114, 114, 114, - 115, 115, 115, 115, 115, 115, 115, 115, 116, 116, - 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, - 117, 117, 117, 117, 117, 118, 119, 120, 190, 141, - 456, 121, 136, 455, 119, 118, 142, 121, 124, 123, - 136, 118, 119, 120, 118, 119, 120, 121, 123, 446, - 121, 445, 143, 200, 124, 123, 141, 124, 123, 136, - - 124, 119, 118, 142, 121, 190, 144, 136, 118, 119, - 120, 118, 119, 120, 121, 123, 125, 121, 126, 143, - 127, 124, 123, 395, 124, 123, 125, 124, 128, 129, - 200, 126, 125, 144, 126, 125, 127, 126, 131, 127, - 392, 357, 127, 145, 128, 129, 146, 128, 129, 130, - 129, 289, 288, 125, 131, 130, 148, 131, 126, 125, - 149, 126, 125, 127, 126, 130, 127, 139, 130, 127, - 145, 128, 129, 146, 128, 129, 139, 129, 139, 140, - 151, 131, 130, 148, 131, 152, 153, 149, 140, 156, - 140, 155, 130, 286, 139, 130, 285, 267, 266, 213, - - 212, 49, 25, 139, 24, 139, 140, 151, 23, 9, - 8, 174, 152, 153, 175, 140, 156, 140, 3, 155, - 157, 157, 157, 157, 157, 157, 157, 157, 155, 158, - 158, 158, 158, 158, 158, 158, 158, 159, 174, 160, - 176, 175, 177, 161, 162, 163, 155, 178, 179, 165, - 181, 182, 183, 159, 2, 160, 159, 159, 160, 161, - 162, 163, 161, 162, 163, 165, 0, 176, 165, 177, - 0, 205, 0, 163, 178, 179, 0, 181, 182, 183, - 159, 167, 160, 159, 159, 160, 161, 162, 163, 161, - 162, 163, 165, 166, 169, 165, 167, 167, 166, 168, - - 167, 168, 184, 170, 185, 0, 0, 186, 205, 166, - 169, 180, 166, 169, 171, 168, 172, 170, 168, 170, - 187, 180, 170, 167, 167, 166, 188, 167, 168, 184, - 171, 185, 172, 171, 186, 172, 166, 169, 189, 166, - 169, 191, 168, 192, 170, 168, 170, 187, 180, 170, - 193, 194, 195, 188, 196, 197, 198, 171, 199, 172, - 171, 201, 172, 202, 203, 189, 202, 203, 191, 204, - 192, 206, 207, 0, 0, 0, 210, 193, 194, 195, - 0, 196, 197, 198, 0, 199, 0, 0, 201, 0, - 202, 203, 210, 202, 203, 210, 204, 210, 206, 207, - - 208, 208, 208, 208, 208, 208, 208, 208, 209, 209, - 209, 209, 209, 209, 209, 209, 216, 214, 215, 210, - 0, 220, 210, 214, 210, 217, 218, 219, 221, 222, - 223, 225, 216, 214, 215, 216, 214, 215, 215, 224, - 226, 217, 218, 219, 217, 218, 219, 219, 220, 0, - 214, 227, 228, 230, 231, 221, 222, 223, 225, 216, - 214, 215, 216, 214, 215, 215, 232, 226, 217, 218, - 219, 217, 218, 219, 219, 233, 224, 234, 227, 228, - 230, 231, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 232, 246, 247, 248, 249, 250, 251, - - 252, 253, 233, 254, 234, 255, 256, 257, 258, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 259, 260, 247, 248, 249, 250, 251, 252, 253, 261, - 254, 246, 255, 256, 257, 258, 262, 263, 263, 263, - 263, 263, 263, 263, 263, 263, 275, 259, 260, 276, - 0, 0, 0, 273, 274, 277, 261, 270, 271, 290, - 278, 0, 279, 262, 264, 264, 264, 264, 264, 264, - 264, 264, 265, 270, 271, 280, 270, 271, 265, 272, - 273, 274, 277, 275, 281, 282, 276, 278, 265, 279, - 283, 265, 284, 287, 291, 272, 290, 292, 272, 293, - - 270, 271, 280, 270, 271, 265, 294, 295, 296, 297, - 298, 281, 282, 299, 300, 265, 302, 283, 265, 284, - 287, 291, 272, 303, 304, 272, 293, 305, 301, 306, - 316, 307, 308, 294, 292, 296, 297, 298, 301, 309, - 299, 300, 310, 302, 295, 311, 312, 313, 314, 315, - 303, 0, 322, 323, 305, 324, 306, 301, 307, 308, - 0, 304, 319, 331, 0, 301, 309, 316, 325, 310, - 326, 327, 311, 312, 313, 314, 315, 319, 319, 322, - 323, 319, 324, 328, 301, 317, 317, 317, 317, 317, - 317, 317, 317, 317, 329, 325, 330, 326, 327, 332, - - 331, 333, 334, 335, 319, 319, 336, 337, 319, 338, - 328, 339, 340, 341, 342, 344, 345, 346, 347, 348, - 349, 329, 350, 330, 351, 352, 332, 353, 333, 334, - 335, 354, 355, 336, 337, 358, 338, 359, 339, 340, - 341, 342, 344, 345, 346, 347, 348, 349, 360, 350, - 363, 351, 352, 364, 353, 361, 361, 365, 354, 355, - 362, 362, 358, 366, 359, 367, 368, 0, 369, 371, - 372, 374, 375, 0, 0, 360, 0, 363, 0, 0, - 364, 0, 361, 361, 378, 379, 380, 362, 362, 381, - 366, 382, 367, 368, 365, 369, 371, 372, 374, 375, - - 376, 376, 376, 376, 376, 376, 376, 376, 376, 377, - 383, 378, 379, 380, 384, 385, 381, 386, 382, 387, - 388, 389, 390, 391, 393, 377, 394, 396, 377, 397, - 377, 398, 399, 400, 401, 402, 403, 383, 404, 405, - 406, 384, 385, 407, 386, 408, 387, 388, 389, 390, - 391, 393, 377, 394, 396, 377, 397, 377, 398, 399, - 400, 401, 402, 403, 409, 404, 405, 406, 410, 411, - 407, 413, 408, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 425, 424, 426, 427, 428, 429, 430, - 431, 409, 424, 426, 433, 410, 411, 434, 413, 435, - - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 425, 424, 426, 427, 428, 429, 430, 431, 432, 424, - 426, 433, 436, 437, 434, 438, 435, 439, 440, 441, - 442, 443, 444, 447, 432, 448, 449, 432, 450, 461, - 451, 452, 453, 454, 457, 458, 459, 460, 462, 436, - 437, 463, 438, 464, 439, 440, 465, 442, 443, 444, - 447, 432, 448, 449, 432, 450, 441, 451, 452, 453, - 454, 457, 458, 459, 460, 462, 461, 466, 463, 467, - 464, 468, 469, 465, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, 483, 486, 487, - - 490, 491, 492, 493, 466, 494, 467, 495, 468, 469, - 496, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 482, 483, 486, 487, 490, 491, 492, - 493, 497, 494, 498, 495, 499, 500, 496, 501, 502, - 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, - 513, 514, 517, 518, 519, 520, 521, 522, 497, 523, - 498, 524, 499, 500, 525, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 517, - 518, 519, 520, 521, 522, 526, 523, 527, 524, 528, - 529, 525, 530, 533, 534, 535, 536, 537, 538, 539, - - 540, 543, 544, 545, 546, 547, 548, 549, 550, 551, - 552, 553, 526, 554, 527, 555, 528, 529, 556, 530, - 533, 534, 535, 536, 537, 538, 539, 540, 543, 544, - 545, 546, 547, 548, 549, 550, 551, 552, 553, 557, - 554, 558, 555, 559, 560, 556, 561, 562, 563, 564, - 565, 566, 567, 568, 569, 572, 573, 576, 577, 578, - 579, 588, 589, 591, 592, 594, 557, 595, 558, 596, - 559, 560, 597, 561, 562, 563, 564, 565, 566, 567, - 568, 569, 572, 573, 576, 577, 578, 579, 588, 589, - 591, 592, 594, 598, 595, 599, 596, 600, 601, 597, - - 602, 603, 604, 605, 607, 608, 609, 610, 611, 612, - 613, 614, 615, 616, 617, 618, 621, 622, 625, 626, - 598, 627, 599, 628, 600, 601, 631, 602, 603, 604, - 605, 607, 608, 609, 610, 611, 612, 613, 614, 615, - 616, 617, 618, 621, 622, 625, 626, 632, 627, 633, - 628, 634, 635, 631, 637, 639, 640, 641, 642, 643, - 644, 647, 648, 649, 650, 652, 653, 654, 655, 656, - 657, 658, 659, 660, 632, 661, 633, 662, 634, 635, - 663, 637, 639, 640, 641, 642, 643, 644, 647, 648, - 649, 650, 652, 653, 654, 655, 656, 657, 658, 659, - - 660, 666, 661, 667, 662, 670, 671, 663, 672, 673, - 674, 675, 678, 679, 680, 681, 682, 683, 686, 687, - 688, 689, 690, 691, 692, 693, 694, 695, 666, 696, - 667, 697, 670, 671, 698, 672, 673, 674, 675, 678, - 679, 680, 681, 682, 683, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 699, 696, 700, 697, 701, - 706, 698, 707, 708, 709, 710, 711, 720, 721, 722, - 724, 725, 727, 730, 731, 732, 733, 734, 735, 736, - 737, 738, 699, 739, 700, 746, 701, 706, 749, 707, - 708, 709, 710, 711, 720, 721, 722, 724, 725, 727, - - 730, 731, 732, 733, 734, 735, 736, 737, 738, 752, - 739, 753, 746, 754, 755, 749, 756, 757, 762, 763, - 764, 766, 768, 769, 772, 773, 778, 779, 784, 785, - 786, 787, 788, 789, 794, 795, 752, 796, 753, 797, - 754, 755, 800, 756, 757, 762, 763, 764, 766, 768, - 769, 772, 773, 778, 779, 784, 785, 786, 787, 788, - 789, 794, 795, 801, 796, 804, 797, 805, 0, 800, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 801, 0, 804, 0, 805, 811, 0, 811, 813, 813, - - 813, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810 + 1, 1, 1, 11, 15, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 12, 14, + 16, 17, 14, 18, 16, 19, 20, 21, 22, 23, + + 24, 15, 22, 54, 17, 56, 57, 30, 21, 58, + 30, 30, 59, 64, 21, 772, 14, 16, 17, 14, + 18, 16, 19, 20, 21, 22, 23, 24, 770, 22, + 54, 17, 56, 57, 761, 21, 58, 760, 741, 59, + 64, 21, 28, 28, 28, 28, 28, 28, 28, 30, + 740, 65, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 65, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + + 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, + 29, 29, 31, 66, 739, 31, 31, 95, 31, 31, + 31, 31, 31, 31, 31, 33, 33, 33, 33, 33, + 33, 33, 35, 738, 36, 35, 35, 36, 36, 34, + 66, 37, 34, 34, 37, 37, 729, 728, 89, 38, + 35, 36, 38, 38, 31, 32, 95, 90, 32, 32, + 37, 32, 32, 32, 32, 32, 32, 32, 34, 39, + 719, 718, 39, 39, 35, 89, 36, 35, 36, 91, + 60, 34, 38, 37, 90, 40, 60, 37, 40, 40, + 41, 38, 717, 41, 41, 34, 39, 32, 42, 142, + + 43, 42, 42, 43, 43, 716, 91, 60, 709, 38, + 92, 39, 93, 60, 41, 44, 42, 45, 44, 44, + 45, 45, 40, 39, 706, 61, 44, 40, 61, 43, + 703, 46, 41, 55, 46, 46, 45, 92, 142, 93, + 42, 41, 43, 42, 94, 55, 702, 47, 96, 40, + 47, 47, 61, 97, 98, 61, 43, 44, 48, 45, + 55, 48, 48, 45, 46, 49, 99, 686, 49, 49, + 100, 94, 55, 46, 50, 96, 47, 50, 50, 145, + 97, 98, 62, 683, 62, 63, 62, 101, 102, 47, + 103, 46, 48, 99, 63, 63, 679, 100, 49, 104, + + 48, 63, 68, 47, 678, 68, 68, 49, 149, 62, + 50, 62, 63, 62, 101, 102, 50, 103, 145, 48, + 72, 63, 63, 72, 72, 49, 104, 665, 63, 67, + 67, 67, 67, 67, 67, 67, 106, 50, 53, 53, + 53, 53, 107, 108, 68, 53, 53, 149, 664, 109, + 129, 53, 130, 53, 72, 53, 53, 53, 53, 53, + 647, 131, 72, 106, 646, 53, 53, 53, 53, 107, + 108, 73, 53, 53, 73, 73, 109, 129, 53, 130, + 53, 72, 53, 53, 53, 53, 53, 69, 131, 631, + 69, 69, 170, 69, 69, 69, 69, 69, 69, 69, + + 71, 71, 71, 71, 71, 71, 71, 74, 133, 630, + 74, 74, 75, 73, 76, 75, 75, 76, 76, 77, + 586, 78, 77, 77, 78, 78, 585, 574, 78, 69, + 70, 170, 555, 70, 70, 133, 70, 70, 70, 70, + 70, 70, 70, 74, 76, 554, 134, 79, 137, 74, + 79, 79, 138, 77, 75, 80, 76, 553, 80, 80, + 552, 77, 81, 78, 139, 81, 81, 79, 551, 140, + 74, 76, 70, 134, 82, 137, 550, 82, 82, 138, + 77, 83, 80, 84, 83, 83, 84, 84, 81, 79, + 545, 139, 132, 105, 79, 85, 140, 80, 85, 85, + + 132, 544, 490, 87, 81, 489, 87, 87, 105, 80, + 467, 84, 466, 434, 85, 81, 82, 83, 433, 132, + 105, 426, 425, 83, 380, 84, 86, 132, 88, 86, + 86, 88, 88, 185, 377, 105, 283, 85, 84, 115, + 87, 85, 115, 115, 83, 87, 86, 282, 88, 110, + 110, 110, 110, 110, 110, 110, 114, 114, 114, 114, + 114, 114, 114, 115, 280, 141, 143, 87, 86, 144, + 88, 146, 185, 86, 117, 88, 111, 117, 117, 111, + 111, 115, 111, 111, 111, 111, 111, 111, 111, 279, + 115, 116, 141, 143, 116, 116, 144, 118, 146, 119, + + 118, 118, 119, 119, 51, 27, 125, 117, 122, 125, + 125, 122, 122, 116, 195, 119, 117, 118, 111, 112, + 26, 200, 112, 112, 147, 112, 112, 112, 112, 112, + 112, 112, 122, 116, 117, 25, 125, 148, 241, 118, + 116, 119, 119, 121, 118, 10, 121, 121, 125, 151, + 122, 147, 120, 195, 123, 120, 120, 123, 123, 122, + 200, 112, 113, 125, 148, 113, 113, 9, 113, 113, + 113, 113, 113, 113, 113, 120, 151, 241, 171, 121, + 124, 123, 8, 124, 124, 121, 126, 150, 128, 126, + 126, 128, 128, 172, 120, 127, 123, 173, 127, 127, + + 135, 3, 120, 2, 113, 171, 121, 176, 123, 135, + 271, 135, 174, 175, 136, 127, 124, 150, 176, 0, + 172, 126, 124, 136, 173, 136, 150, 135, 126, 0, + 128, 154, 0, 0, 154, 154, 135, 127, 135, 174, + 175, 136, 127, 124, 150, 0, 176, 0, 126, 271, + 136, 0, 136, 152, 152, 152, 152, 152, 152, 152, + 153, 0, 177, 153, 153, 0, 153, 153, 153, 153, + 153, 153, 153, 154, 155, 155, 155, 155, 155, 155, + 155, 156, 0, 157, 156, 156, 157, 157, 158, 177, + 159, 158, 158, 159, 159, 160, 272, 161, 160, 160, + + 161, 161, 153, 0, 162, 0, 161, 162, 162, 161, + 163, 178, 0, 163, 163, 156, 164, 0, 165, 164, + 164, 165, 165, 156, 166, 157, 179, 166, 166, 163, + 158, 0, 159, 0, 165, 272, 0, 160, 178, 161, + 167, 0, 156, 167, 167, 164, 162, 168, 180, 181, + 168, 168, 163, 179, 182, 0, 163, 166, 164, 169, + 165, 165, 169, 169, 183, 0, 166, 184, 167, 186, + 187, 188, 164, 189, 0, 180, 181, 190, 191, 192, + 193, 182, 167, 194, 166, 196, 199, 197, 201, 168, + 197, 183, 169, 202, 184, 167, 186, 187, 188, 198, + + 189, 169, 198, 0, 190, 191, 192, 193, 0, 0, + 194, 217, 196, 199, 197, 201, 0, 197, 285, 169, + 202, 0, 0, 218, 219, 220, 198, 221, 222, 198, + 203, 203, 203, 203, 203, 203, 203, 204, 217, 0, + 204, 204, 223, 204, 204, 204, 204, 204, 204, 204, + 218, 219, 220, 0, 221, 222, 208, 285, 207, 208, + 208, 207, 207, 209, 0, 208, 209, 209, 208, 223, + 224, 209, 210, 0, 211, 210, 210, 211, 211, 204, + 205, 0, 210, 205, 205, 226, 205, 205, 205, 205, + 205, 205, 205, 207, 211, 0, 227, 224, 208, 212, + + 207, 0, 212, 212, 213, 209, 214, 213, 213, 214, + 214, 228, 226, 229, 210, 215, 211, 230, 215, 215, + 207, 211, 205, 227, 216, 231, 232, 216, 216, 233, + 0, 0, 234, 212, 235, 236, 237, 238, 228, 0, + 229, 212, 239, 240, 230, 242, 213, 243, 214, 244, + 245, 246, 231, 232, 247, 248, 233, 215, 216, 234, + 212, 235, 236, 237, 238, 249, 216, 250, 251, 239, + 240, 252, 242, 253, 243, 254, 244, 245, 246, 255, + 256, 247, 248, 257, 260, 216, 0, 260, 260, 269, + 0, 0, 249, 261, 250, 251, 261, 261, 252, 0, + + 253, 262, 254, 270, 262, 262, 255, 256, 0, 262, + 257, 259, 273, 261, 259, 259, 269, 259, 259, 259, + 259, 259, 259, 259, 263, 274, 260, 263, 263, 264, + 270, 275, 264, 264, 263, 261, 276, 277, 265, 273, + 261, 265, 265, 262, 266, 278, 267, 266, 266, 267, + 267, 268, 274, 259, 268, 268, 281, 284, 275, 288, + 286, 0, 287, 276, 277, 289, 263, 290, 291, 292, + 293, 264, 278, 295, 294, 296, 297, 298, 299, 300, + 265, 301, 302, 281, 284, 294, 266, 286, 267, 287, + 303, 304, 289, 268, 290, 291, 292, 293, 288, 305, + + 295, 306, 296, 307, 298, 299, 300, 308, 301, 302, + 309, 0, 321, 294, 314, 297, 315, 303, 304, 316, + 317, 312, 0, 0, 312, 312, 305, 0, 306, 313, + 307, 0, 313, 313, 308, 311, 0, 0, 311, 311, + 318, 314, 319, 315, 0, 320, 316, 317, 322, 309, + 310, 321, 323, 310, 310, 324, 310, 310, 310, 310, + 310, 310, 310, 312, 311, 0, 325, 318, 326, 319, + 327, 313, 320, 328, 329, 322, 330, 311, 332, 323, + 333, 334, 324, 335, 336, 337, 338, 339, 340, 341, + 342, 311, 310, 325, 343, 326, 345, 327, 346, 347, + + 328, 329, 350, 330, 351, 332, 353, 333, 334, 352, + 335, 336, 337, 338, 339, 340, 341, 342, 348, 348, + 354, 343, 355, 345, 356, 346, 347, 349, 349, 350, + 358, 351, 359, 353, 361, 362, 363, 365, 364, 363, + 363, 364, 364, 366, 367, 348, 348, 354, 352, 355, + 368, 356, 369, 0, 349, 349, 370, 358, 371, 359, + 372, 361, 362, 373, 365, 374, 375, 376, 378, 379, + 366, 367, 381, 364, 382, 383, 384, 368, 363, 369, + 364, 385, 386, 370, 387, 371, 388, 372, 389, 390, + 373, 391, 374, 375, 376, 378, 379, 392, 393, 381, + + 364, 382, 383, 384, 394, 395, 396, 397, 385, 386, + 398, 387, 399, 388, 400, 389, 390, 401, 391, 402, + 403, 404, 405, 407, 392, 393, 409, 406, 408, 410, + 411, 394, 395, 396, 397, 406, 408, 398, 412, 399, + 413, 400, 421, 0, 401, 415, 402, 403, 404, 405, + 407, 416, 417, 409, 406, 408, 410, 411, 418, 419, + 420, 422, 406, 408, 423, 412, 414, 413, 424, 414, + 414, 427, 415, 428, 429, 430, 431, 432, 416, 417, + 435, 421, 436, 437, 438, 418, 419, 420, 422, 439, + 440, 423, 441, 442, 443, 424, 444, 445, 427, 446, + + 428, 429, 430, 431, 432, 447, 448, 435, 414, 436, + 437, 438, 449, 450, 451, 452, 453, 440, 454, 441, + 442, 443, 455, 444, 445, 456, 446, 457, 439, 458, + 459, 460, 447, 448, 461, 464, 465, 468, 469, 449, + 450, 451, 452, 453, 470, 454, 471, 472, 473, 455, + 474, 475, 456, 476, 457, 477, 458, 459, 460, 478, + 479, 461, 464, 465, 468, 469, 480, 481, 482, 483, + 484, 470, 485, 471, 472, 473, 486, 474, 475, 487, + 476, 488, 477, 491, 492, 493, 478, 479, 494, 495, + 496, 497, 498, 480, 481, 482, 483, 484, 499, 485, + + 500, 501, 502, 486, 503, 504, 487, 507, 488, 508, + 491, 492, 493, 509, 510, 494, 495, 496, 497, 498, + 511, 512, 513, 514, 517, 499, 518, 500, 501, 502, + 519, 503, 504, 520, 507, 521, 508, 522, 523, 524, + 509, 510, 525, 526, 527, 528, 529, 511, 512, 513, + 514, 517, 530, 518, 531, 532, 533, 519, 534, 535, + 520, 536, 521, 537, 522, 523, 524, 538, 539, 525, + 526, 527, 528, 529, 542, 543, 546, 547, 548, 530, + 549, 531, 532, 533, 558, 534, 535, 559, 536, 561, + 537, 562, 564, 565, 538, 539, 566, 567, 568, 569, + + 570, 542, 543, 546, 547, 548, 571, 549, 572, 573, + 575, 558, 576, 577, 559, 578, 561, 579, 562, 564, + 565, 580, 581, 566, 567, 568, 569, 570, 582, 583, + 584, 587, 588, 571, 591, 572, 573, 575, 592, 576, + 577, 593, 578, 594, 579, 597, 598, 599, 580, 581, + 600, 601, 603, 605, 606, 582, 583, 584, 587, 588, + 607, 591, 608, 609, 610, 592, 611, 612, 593, 613, + 594, 614, 597, 598, 599, 616, 617, 600, 601, 603, + 605, 606, 618, 619, 620, 621, 622, 607, 623, 608, + 609, 610, 624, 611, 612, 625, 613, 628, 614, 629, + + 632, 633, 616, 617, 634, 635, 636, 637, 640, 618, + 619, 620, 621, 622, 641, 623, 642, 643, 644, 624, + 645, 648, 625, 649, 628, 650, 629, 632, 633, 651, + 652, 634, 635, 636, 637, 640, 653, 654, 655, 656, + 657, 641, 658, 642, 643, 644, 659, 645, 648, 660, + 649, 661, 650, 666, 667, 668, 651, 652, 669, 670, + 671, 680, 681, 653, 654, 655, 656, 657, 682, 658, + 684, 685, 687, 659, 688, 689, 660, 690, 661, 691, + 666, 667, 668, 692, 693, 669, 670, 671, 680, 681, + 694, 695, 696, 697, 704, 682, 707, 684, 685, 687, + + 710, 688, 689, 711, 690, 712, 691, 713, 714, 715, + 692, 693, 720, 721, 722, 724, 726, 694, 695, 696, + 697, 704, 727, 707, 730, 731, 736, 710, 737, 742, + 711, 743, 712, 744, 713, 714, 715, 745, 746, 720, + 721, 722, 724, 726, 747, 752, 753, 754, 755, 727, + 758, 730, 731, 736, 759, 737, 742, 762, 743, 763, + 744, 0, 0, 0, 745, 746, 0, 0, 0, 0, + 0, 747, 752, 753, 754, 755, 0, 758, 0, 0, + 0, 759, 0, 0, 762, 0, 763, 769, 0, 769, + 771, 771, 771, 768, 768, 768, 768, 768, 768, 768, + + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768 } ; -static yyconst flex_int16_t yy_rule_linenum[96] = +static yyconst flex_int16_t yy_rule_linenum[90] = { 0, - 76, 79, 81, 83, 87, 88, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 150, 151, 153, 154, 155, - 156, 157, 158, 160, 161, 164, 169, 170, 171, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 183, 189, - 195, 201, 207, 213, 219 - + 77, 79, 81, 83, 85, 88, 92, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 150, 151, 153, 154, 155, 156, 157, 158, + 160, 161, 164, 169, 170, 171, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 183, 192, 210, 216 } ; /* The intent behind this definition is that it'll catch @@ -1333,7 +1293,7 @@ static yyconst flex_int16_t yy_rule_linenum[96] = * along with this program. If not, see . */ -#line 37 "libmemcached/options/scanner.l" +#line 38 "libmemcached/options/scanner.l" #include #include @@ -1347,8 +1307,8 @@ static yyconst flex_int16_t yy_rule_linenum[96] = } \ else \ { \ - result= context->length - context->pos; \ - result > max_size ? result = max_size : 0; \ + result= (int)(context->length - context->pos); \ + (size_t)result > (size_t)max_size ? result= max_size : 0; \ memcpy(buffer, context->buf + context->pos, result); \ context->pos += result; \ } \ @@ -1357,7 +1317,7 @@ static yyconst flex_int16_t yy_rule_linenum[96] = #define YY_INPUT(buffer, result, max_size) get_lex_chars(buffer, result, max_size, PARAM) -#line 1361 "libmemcached/options/scanner.cc" +#line 1321 "libmemcached/options/scanner.cc" #define INITIAL 0 @@ -1660,11 +1620,11 @@ YY_DECL struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* %% [7.0] user's declarations go here */ -#line 73 "libmemcached/options/scanner.l" +#line 74 "libmemcached/options/scanner.l" -#line 1668 "libmemcached/options/scanner.cc" +#line 1628 "libmemcached/options/scanner.cc" yylval = yylval_param; @@ -1730,13 +1690,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 811 ) + if ( yy_current_state >= 769 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 2202 ); + while ( yy_base[yy_current_state] != 2094 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ @@ -1759,13 +1719,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 96 ) + else if ( yy_act < 90 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 96 ) + else if ( yy_act == 90 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 97 ) + else if ( yy_act == 91 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1783,7 +1743,7 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 76 "libmemcached/options/scanner.l" +#line 77 "libmemcached/options/scanner.l" { return yytext[0];} YY_BREAK case 2: @@ -1792,377 +1752,362 @@ YY_RULE_SETUP { yylval->number = atoi(yytext); return (NUMBER); } YY_BREAK case 3: -/* rule 3 can match eol */ YY_RULE_SETUP #line 81 "libmemcached/options/scanner.l" -; /* skip whitespace */ +{ yylval->server.port = atoi(yytext +1); return PORT; } YY_BREAK case 4: -*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ -yyg->yy_c_buf_p = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 83 "libmemcached/options/scanner.l" -{ - return COMMENT; - } +{ yylval->server.weight = atoi(yytext +2); return WEIGHT_START; } YY_BREAK case 5: +/* rule 5 can match eol */ YY_RULE_SETUP -#line 87 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return SERVER; } +#line 85 "libmemcached/options/scanner.l" +; /* skip whitespace */ YY_BREAK case 6: +*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ +yyg->yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 88 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return SERVERS_OPTION; } +{ + return COMMENT; + } YY_BREAK case 7: YY_RULE_SETUP -#line 90 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return VERIFY_KEY; } +#line 92 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; yyextra->set_server(); return SERVER; } YY_BREAK case 8: YY_RULE_SETUP -#line 91 "libmemcached/options/scanner.l" +#line 94 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return VERIFY_KEY; } YY_BREAK case 9: YY_RULE_SETUP -#line 92 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return AUTO_EJECT_HOSTS; } +#line 95 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return VERIFY_KEY; } YY_BREAK case 10: YY_RULE_SETUP -#line 93 "libmemcached/options/scanner.l" +#line 96 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return AUTO_EJECT_HOSTS; } YY_BREAK case 11: YY_RULE_SETUP -#line 94 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return BINARY_PROTOCOL; } +#line 97 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return AUTO_EJECT_HOSTS; } YY_BREAK case 12: YY_RULE_SETUP -#line 95 "libmemcached/options/scanner.l" +#line 98 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return BINARY_PROTOCOL; } YY_BREAK case 13: YY_RULE_SETUP -#line 96 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return BUFFER_REQUESTS; } +#line 99 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return BINARY_PROTOCOL; } YY_BREAK case 14: YY_RULE_SETUP -#line 97 "libmemcached/options/scanner.l" +#line 100 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return BUFFER_REQUESTS; } YY_BREAK case 15: YY_RULE_SETUP -#line 98 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return CACHE_LOOKUPS; } +#line 101 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return BUFFER_REQUESTS; } YY_BREAK case 16: YY_RULE_SETUP -#line 99 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return CACHE_LOOKUPS; } +#line 102 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return CONFIGURE_FILE; } YY_BREAK case 17: YY_RULE_SETUP -#line 100 "libmemcached/options/scanner.l" +#line 103 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return CONFIGURE_FILE; } YY_BREAK case 18: YY_RULE_SETUP -#line 101 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return CONFIGURE_FILE; } +#line 104 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return CONNECT_TIMEOUT; } YY_BREAK case 19: YY_RULE_SETUP -#line 102 "libmemcached/options/scanner.l" +#line 105 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return CONNECT_TIMEOUT; } YY_BREAK case 20: YY_RULE_SETUP -#line 103 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return CONNECT_TIMEOUT; } +#line 106 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return DISTRIBUTION; } YY_BREAK case 21: YY_RULE_SETUP -#line 104 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return DISTRIBUTION; } +#line 107 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return HASH; } YY_BREAK case 22: YY_RULE_SETUP -#line 105 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return HASH; } +#line 108 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return HASH_WITH_PREFIX_KEY; } YY_BREAK case 23: YY_RULE_SETUP -#line 106 "libmemcached/options/scanner.l" +#line 109 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return HASH_WITH_PREFIX_KEY; } YY_BREAK case 24: YY_RULE_SETUP -#line 107 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return HASH_WITH_PREFIX_KEY; } +#line 110 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return IO_BYTES_WATERMARK; } YY_BREAK case 25: YY_RULE_SETUP -#line 108 "libmemcached/options/scanner.l" +#line 111 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return IO_BYTES_WATERMARK; } YY_BREAK case 26: YY_RULE_SETUP -#line 109 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return IO_BYTES_WATERMARK; } +#line 112 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return IO_KEY_PREFETCH; } YY_BREAK case 27: YY_RULE_SETUP -#line 110 "libmemcached/options/scanner.l" +#line 113 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return IO_KEY_PREFETCH; } YY_BREAK case 28: YY_RULE_SETUP -#line 111 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return IO_KEY_PREFETCH; } +#line 114 "libmemcached/options/scanner.l" +{ yyextra->begin= yytext; return IO_MSG_WATERMARK; } YY_BREAK case 29: YY_RULE_SETUP -#line 112 "libmemcached/options/scanner.l" +#line 115 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return IO_MSG_WATERMARK; } YY_BREAK case 30: YY_RULE_SETUP -#line 113 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return IO_MSG_WATERMARK; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 114 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return KETAMA_WEIGHTED; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 115 "libmemcached/options/scanner.l" -{ yyextra->begin= yytext; return KETAMA_WEIGHTED; } - YY_BREAK -case 33: -YY_RULE_SETUP #line 116 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return NOREPLY; } YY_BREAK -case 34: +case 31: YY_RULE_SETUP #line 117 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return NUMBER_OF_REPLICAS; } YY_BREAK -case 35: +case 32: YY_RULE_SETUP #line 118 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return NUMBER_OF_REPLICAS; } YY_BREAK -case 36: +case 33: YY_RULE_SETUP #line 119 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return POLL_TIMEOUT; } YY_BREAK -case 37: +case 34: YY_RULE_SETUP #line 120 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return POLL_TIMEOUT; } YY_BREAK -case 38: +case 35: YY_RULE_SETUP #line 121 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RANDOMIZE_REPLICA_READ; } YY_BREAK -case 39: +case 36: YY_RULE_SETUP #line 122 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RANDOMIZE_REPLICA_READ; } YY_BREAK -case 40: +case 37: YY_RULE_SETUP #line 123 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RCV_TIMEOUT; } YY_BREAK -case 41: +case 38: YY_RULE_SETUP #line 124 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RCV_TIMEOUT; } YY_BREAK -case 42: +case 39: YY_RULE_SETUP #line 125 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RETRY_TIMEOUT; } YY_BREAK -case 43: +case 40: YY_RULE_SETUP #line 126 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RETRY_TIMEOUT; } YY_BREAK -case 44: +case 41: YY_RULE_SETUP #line 127 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SERVER_FAILURE_LIMIT; } YY_BREAK -case 45: +case 42: YY_RULE_SETUP #line 128 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SERVER_FAILURE_LIMIT; } YY_BREAK -case 46: +case 43: YY_RULE_SETUP #line 129 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SND_TIMEOUT; } YY_BREAK -case 47: +case 44: YY_RULE_SETUP #line 130 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SND_TIMEOUT; } YY_BREAK -case 48: +case 45: YY_RULE_SETUP #line 131 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SOCKET_RECV_SIZE; } YY_BREAK -case 49: +case 46: YY_RULE_SETUP #line 132 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SOCKET_RECV_SIZE; } YY_BREAK -case 50: +case 47: YY_RULE_SETUP #line 133 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SOCKET_SEND_SIZE; } YY_BREAK -case 51: +case 48: YY_RULE_SETUP #line 134 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SOCKET_SEND_SIZE; } YY_BREAK -case 52: +case 49: YY_RULE_SETUP #line 135 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SORT_HOSTS; } YY_BREAK -case 53: +case 50: YY_RULE_SETUP #line 136 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SORT_HOSTS; } YY_BREAK -case 54: +case 51: YY_RULE_SETUP #line 137 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SUPPORT_CAS; } YY_BREAK -case 55: +case 52: YY_RULE_SETUP #line 138 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SUPPORT_CAS; } YY_BREAK -case 56: +case 53: YY_RULE_SETUP #line 139 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return _TCP_NODELAY; } YY_BREAK -case 57: +case 54: YY_RULE_SETUP #line 140 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return _TCP_NODELAY; } YY_BREAK -case 58: +case 55: YY_RULE_SETUP #line 141 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return _TCP_KEEPALIVE; } YY_BREAK -case 59: +case 56: YY_RULE_SETUP #line 142 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return _TCP_KEEPALIVE; } YY_BREAK -case 60: +case 57: YY_RULE_SETUP #line 143 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return _TCP_KEEPIDLE; } YY_BREAK -case 61: +case 58: YY_RULE_SETUP #line 144 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return _TCP_KEEPIDLE; } YY_BREAK -case 62: +case 59: YY_RULE_SETUP #line 145 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return USER_DATA; } YY_BREAK -case 63: +case 60: YY_RULE_SETUP #line 146 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return USER_DATA; } YY_BREAK -case 64: +case 61: YY_RULE_SETUP #line 147 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return USE_UDP; } YY_BREAK -case 65: +case 62: YY_RULE_SETUP #line 148 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return USE_UDP; } YY_BREAK -case 66: +case 63: YY_RULE_SETUP #line 150 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return PREFIX_KEY; } YY_BREAK -case 67: +case 64: YY_RULE_SETUP #line 151 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return PREFIX_KEY; } YY_BREAK -case 68: +case 65: YY_RULE_SETUP #line 153 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return INCLUDE; } YY_BREAK -case 69: +case 66: YY_RULE_SETUP #line 154 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return RESET; } YY_BREAK -case 70: +case 67: YY_RULE_SETUP #line 155 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return PARSER_DEBUG; } YY_BREAK -case 71: +case 68: YY_RULE_SETUP #line 156 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return SERVERS; } YY_BREAK -case 72: +case 69: YY_RULE_SETUP #line 157 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return END; } YY_BREAK -case 73: +case 70: YY_RULE_SETUP #line 158 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return ERROR; } YY_BREAK -case 74: +case 71: YY_RULE_SETUP #line 160 "libmemcached/options/scanner.l" { return TRUE; } YY_BREAK -case 75: +case 72: YY_RULE_SETUP #line 161 "libmemcached/options/scanner.l" { return FALSE; } YY_BREAK -case 76: +case 73: YY_RULE_SETUP #line 164 "libmemcached/options/scanner.l" { @@ -2170,134 +2115,122 @@ YY_RULE_SETUP return UNKNOWN_OPTION; } YY_BREAK -case 77: +case 74: YY_RULE_SETUP #line 169 "libmemcached/options/scanner.l" { return CONSISTENT; } YY_BREAK -case 78: +case 75: YY_RULE_SETUP #line 170 "libmemcached/options/scanner.l" { return MODULA; } YY_BREAK -case 79: +case 76: YY_RULE_SETUP #line 171 "libmemcached/options/scanner.l" { return RANDOM; } YY_BREAK -case 80: +case 77: YY_RULE_SETUP #line 173 "libmemcached/options/scanner.l" { return MD5; } YY_BREAK -case 81: +case 78: YY_RULE_SETUP #line 174 "libmemcached/options/scanner.l" { return CRC; } YY_BREAK -case 82: +case 79: YY_RULE_SETUP #line 175 "libmemcached/options/scanner.l" { return FNV1_64; } YY_BREAK -case 83: +case 80: YY_RULE_SETUP #line 176 "libmemcached/options/scanner.l" { return FNV1A_64; } YY_BREAK -case 84: +case 81: YY_RULE_SETUP #line 177 "libmemcached/options/scanner.l" { return FNV1_32; } YY_BREAK -case 85: +case 82: YY_RULE_SETUP #line 178 "libmemcached/options/scanner.l" { return FNV1A_32; } YY_BREAK -case 86: +case 83: YY_RULE_SETUP #line 179 "libmemcached/options/scanner.l" { return HSIEH; } YY_BREAK -case 87: +case 84: YY_RULE_SETUP #line 180 "libmemcached/options/scanner.l" { return MURMUR; } YY_BREAK -case 88: +case 85: YY_RULE_SETUP #line 181 "libmemcached/options/scanner.l" { return JENKINS; } YY_BREAK -case 89: +case 86: YY_RULE_SETUP #line 183 "libmemcached/options/scanner.l" { - yylval->string.c_str = yytext; - yylval->string.length = yyleng; - return HOSTNAME_WITH_PORT; - } - YY_BREAK -case 90: -YY_RULE_SETUP -#line 189 "libmemcached/options/scanner.l" -{ - yylval->string.c_str = yytext; - yylval->string.length = yyleng; - return HOSTNAME; - } - YY_BREAK -case 91: -YY_RULE_SETUP -#line 195 "libmemcached/options/scanner.l" -{ - yylval->string.c_str = yytext; - yylval->string.length = yyleng; - return IPADDRESS_WITH_PORT; - } - YY_BREAK -case 92: -YY_RULE_SETUP -#line 201 "libmemcached/options/scanner.l" -{ - yylval->string.c_str = yytext; - yylval->string.length = yyleng; + yylval->server.port= MEMCACHED_DEFAULT_PORT; + yylval->server.weight= 1; + yylval->server.c_str= yyextra->set_hostname(yytext, yyleng); + if (yylval->server.c_str) + yylval->server.length= yyleng; return IPADDRESS; } YY_BREAK -case 93: +case 87: YY_RULE_SETUP -#line 207 "libmemcached/options/scanner.l" +#line 192 "libmemcached/options/scanner.l" { + if (yyextra->is_server()) + { + yylval->server.port= MEMCACHED_DEFAULT_PORT; + yylval->server.weight= 1; + yylval->server.c_str= yyextra->set_hostname(yytext, yyleng); + if (yylval->server.c_str) + yylval->server.length= yyleng; + + return HOSTNAME; + } + yylval->string.c_str = yytext; yylval->string.length = yyleng; + return STRING; } YY_BREAK -case 94: +case 88: YY_RULE_SETUP -#line 213 "libmemcached/options/scanner.l" +#line 210 "libmemcached/options/scanner.l" { yylval->string.c_str = yytext; yylval->string.length = yyleng; return QUOTED_STRING; } YY_BREAK -case 95: +case 89: YY_RULE_SETUP -#line 219 "libmemcached/options/scanner.l" +#line 216 "libmemcached/options/scanner.l" { yyextra->begin= yytext; return UNKNOWN; } YY_BREAK -case 96: +case 90: YY_RULE_SETUP -#line 224 "libmemcached/options/scanner.l" +#line 221 "libmemcached/options/scanner.l" ECHO; YY_BREAK -#line 2301 "libmemcached/options/scanner.cc" +#line 2234 "libmemcached/options/scanner.cc" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -2613,7 +2546,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 811 ) + if ( yy_current_state >= 769 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -2647,11 +2580,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 811 ) + if ( yy_current_state >= 769 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 810); + yy_is_jam = (yy_current_state == 768); return yy_is_jam ? 0 : yy_current_state; } @@ -3563,7 +3496,7 @@ void config_free (void * ptr , yyscan_t yyscanner) /* %ok-for-header */ -#line 224 "libmemcached/options/scanner.l" +#line 221 "libmemcached/options/scanner.l" diff --git a/libmemcached/options/scanner.h b/libmemcached/options/scanner.h index 062d9adf..5401206b 100644 --- a/libmemcached/options/scanner.h +++ b/libmemcached/options/scanner.h @@ -6,6 +6,7 @@ #line 22 "libmemcached/options/scanner.l" #pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wunused-parameter" #include @@ -18,7 +19,7 @@ -#line 22 "libmemcached/options/scanner.h" +#line 23 "libmemcached/options/scanner.h" #define YY_INT_ALIGNED short int @@ -470,9 +471,9 @@ extern int config_lex \ #undef YY_DECL #endif -#line 224 "libmemcached/options/scanner.l" +#line 221 "libmemcached/options/scanner.l" -#line 477 "libmemcached/options/scanner.h" +#line 478 "libmemcached/options/scanner.h" #undef config_IN_HEADER #endif /* config_HEADER_H */ diff --git a/libmemcached/options/server.h b/libmemcached/options/server.h index af6e0f3e..2f666f49 100644 --- a/libmemcached/options/server.h +++ b/libmemcached/options/server.h @@ -43,14 +43,16 @@ struct server_t { - const char *c_str; - size_t length; in_port_t port; + uint32_t weight; + size_t length; + const char *c_str; }; inline std::ostream& operator<<(std::ostream& output, const server_t& arg) { output.write(arg.c_str, arg.length); output << ':' << arg.port; + output << '+' << arg.weight; return output; } diff --git a/libmemcached/options/symbol.h b/libmemcached/options/symbol.h index b14eb331..919d3f17 100644 --- a/libmemcached/options/symbol.h +++ b/libmemcached/options/symbol.h @@ -46,12 +46,12 @@ union YYSTYPE long long number; string_t string; string_t option; - server_t server; double double_number; memcached_server_distribution_t distribution; memcached_hash_t hash; memcached_behavior_t behavior; bool boolean; + server_t server; }; typedef union YYSTYPE YYSTYPE; diff --git a/libmemcached/parse.c b/libmemcached/parse.c index 917c5e30..85860ef3 100644 --- a/libmemcached/parse.c +++ b/libmemcached/parse.c @@ -10,8 +10,6 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) { char *string; - in_port_t port; - uint32_t weight; const char *begin_ptr; const char *end_ptr; memcached_server_st *servers= NULL; @@ -27,8 +25,7 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) { char buffer[HUGE_STRING_LEN]; char *ptr, *ptr2; - port= 0; - weight= 0; + uint32_t weight= 0; if (string) { @@ -46,6 +43,7 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) ptr= index(buffer, ':'); + in_port_t port= 0; if (ptr) { ptr[0]= 0; @@ -57,6 +55,7 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) ptr2= index(ptr, ' '); if (! ptr2) ptr2= index(ptr, ':'); + if (ptr2) { ptr2++; diff --git a/libmemcached/server.c b/libmemcached/server.c index 97b0b27c..b446d131 100644 --- a/libmemcached/server.c +++ b/libmemcached/server.c @@ -12,14 +12,14 @@ /* This is a partial implementation for fetching/creating memcached_server_st objects. */ -#include "common.h" +#include static inline void _server_init(memcached_server_st *self, const memcached_st *root, const char *hostname, in_port_t port, uint32_t weight, memcached_connection_t type) { - self->options.sockaddr_inited= false; self->options.is_shutting_down= false; + self->options.is_dead= false; self->number_of_hosts= 0; self->cursor_active= 0; self->port= port; @@ -27,9 +27,7 @@ static inline void _server_init(memcached_server_st *self, const memcached_st *r self->fd= -1; self->io_bytes_sent= 0; self->server_failure_counter= 0; - self->weight= weight; - self->state.is_corked= false; - self->state.is_dead= false; + self->weight= weight ? weight : 1; // 1 is the default weight value WATCHPOINT_SET(self->io_wait_count.read= 0); WATCHPOINT_SET(self->io_wait_count.write= 0); self->major_version= UINT8_MAX; @@ -42,6 +40,7 @@ static inline void _server_init(memcached_server_st *self, const memcached_st *r self->read_data_length= 0; self->write_buffer_offset= 0; self->address_info= NULL; + self->address_info_next= NULL; if (root) { @@ -52,12 +51,21 @@ static inline void _server_init(memcached_server_st *self, const memcached_st *r self->next_retry= 0; } + if (self->weight > 1 && root) + { + ((memcached_st *)root)->ketama.weighted= true; + } + self->root= root; self->limit_maxbytes= 0; if (hostname == NULL) + { self->hostname[0]= 0; + } else + { strncpy(self->hostname, hostname, NI_MAXHOST - 1); + } } static memcached_server_st *_server_create(memcached_server_st *self, const memcached_st *memc) @@ -246,8 +254,6 @@ void memcached_server_list_free(memcached_server_list_st self) if (self == NULL) return; - const memcached_st *root= self->root; - for (uint32_t x= 0; x < memcached_server_list_count(self); x++) { if (self[x].address_info) @@ -257,6 +263,7 @@ void memcached_server_list_free(memcached_server_list_st self) } } + const memcached_st *root= self->root; if (root) { libmemcached_free(root, self); diff --git a/libmemcached/server.h b/libmemcached/server.h index aadd690f..98f5ed68 100644 --- a/libmemcached/server.h +++ b/libmemcached/server.h @@ -17,8 +17,8 @@ struct memcached_server_st { struct { bool is_allocated:1; bool is_initialized:1; - bool sockaddr_inited:1; bool is_shutting_down:1; + bool is_dead:1; } options; uint32_t number_of_hosts; uint32_t cursor_active; @@ -28,10 +28,6 @@ struct memcached_server_st { uint32_t io_bytes_sent; /* # bytes sent since last read */ uint32_t server_failure_counter; uint32_t weight; - struct { // Place any "state" sort variables in here. - bool is_corked:1; - bool is_dead:1; - } state; struct { uint32_t read; uint32_t write; @@ -46,6 +42,7 @@ struct memcached_server_st { size_t read_data_length; size_t write_buffer_offset; struct addrinfo *address_info; + struct addrinfo *address_info_next; time_t next_retry; const memcached_st *root; uint64_t limit_maxbytes; diff --git a/libmemcached/strerror.c b/libmemcached/strerror.c index 773ccd03..b3ac2b75 100644 --- a/libmemcached/strerror.c +++ b/libmemcached/strerror.c @@ -95,6 +95,8 @@ const char *memcached_strerror(memcached_st *ptr, memcached_return_t rc) return "ERROR OCCURED WHILE PARSING"; case MEMCACHED_PARSE_USER_ERROR: return "USER INITIATED ERROR OCCURED WHILE PARSING"; + case MEMCACHED_DEPRECATED: + return "DEPRECATED"; case MEMCACHED_MAXIMUM_RETURN: return "Gibberish returned!"; default: diff --git a/libtest/include.am b/libtest/include.am index f14d9435..fb859b66 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -7,6 +7,13 @@ # # included from Top Level Makefile.am # All paths should be given relative to the root +# + +LIBUTEST_TMP = ${abs_top_builddir}/tests/var/tmp/ + +CLEANFILES+= \ + tests/var/log/* \ + tests/var/tmp/* noinst_HEADERS+= \ libtest/failed.h \ @@ -23,3 +30,11 @@ libtest_libtest_la_SOURCES=\ libtest_libtest_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} libtest_libtest_la_CPPFLAGS= ${AM_CPPFLAGS} +tests/var: tests/var/log tests/var/tmp + $(mkdir_p) tests/var + +tests/var/log: + $(mkdir_p) tests/var/log + +tests/var/tmp: + $(mkdir_p) tests/var/tmp diff --git a/libtest/server.c b/libtest/server.c index c96ffb51..6cf05fa1 100644 --- a/libtest/server.c +++ b/libtest/server.c @@ -15,9 +15,7 @@ #define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10 -#define PID_FILE_BASE "/tmp/%ulibmemcached_memc.pid" - -#include "config.h" +#include #include #include @@ -28,6 +26,7 @@ #include #include #include +#include #include #include @@ -45,6 +44,27 @@ static void global_sleep(void) #endif } +static bool wait_for_file(const char *filename) +{ + uint32_t timeout= 6; + uint32_t waited; + uint32_t this_wait; + uint32_t retry; + + for (waited= 0, retry= 1; ; retry++, waited+= this_wait) + { + if ((! access(filename, R_OK)) || (waited >= timeout)) + { + return true; + } + + this_wait= retry * retry / 3 + 1; + sleep(this_wait); + } + + return false; +} + static void kill_file(const char *file_buffer) { FILE *fp; @@ -95,10 +115,17 @@ void server_startup(server_startup_st *construct) char *end_ptr; end_ptr= server_string_buffer; + uint32_t port_base= 0; for (uint32_t x= 0; x < construct->count; x++) { int status; - in_port_t port; + + snprintf(construct->pid_file[x], FILENAME_MAX, "/tmp/memcached.pidXXXXXX"); + if (mkstemp(construct->pid_file[x]) == -1) + { + perror("mkstemp"); + return; + } { char *var; @@ -108,40 +135,47 @@ void server_startup(server_startup_st *construct) if ((var= getenv(variable_buffer))) { - port= (in_port_t)atoi(var); + construct->port[x]= (in_port_t)atoi(var); } else { - port= (in_port_t)(x + TEST_PORT_BASE); + do { + construct->port[x]= (in_port_t)(x + TEST_PORT_BASE + port_base); + + if (libmemcached_util_ping("localhost", construct->port[x], NULL)) + { + port_base++; + construct->port[x]= 0; + } + } while (construct->port[x] == 0); } } - char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), PID_FILE_BASE, x); - kill_file(buffer); - + char buffer[FILENAME_MAX]; if (x == 0) { - snprintf(buffer, sizeof(buffer), "%s -d -u root -P "PID_FILE_BASE" -t 1 -p %u -U %u -m 128", - MEMCACHED_BINARY, x, port, port); + snprintf(buffer, sizeof(buffer), "%s -d -P %s -t 1 -p %u -U %u -m 128", + MEMCACHED_BINARY, construct->pid_file[x], construct->port[x], construct->port[x]); } else { - snprintf(buffer, sizeof(buffer), "%s -d -u root -P "PID_FILE_BASE" -t 1 -p %u -U %u", - MEMCACHED_BINARY, x, port, port); + snprintf(buffer, sizeof(buffer), "%s -d -P %s -t 1 -p %u -U %u", + MEMCACHED_BINARY, construct->pid_file[x], construct->port[x], construct->port[x]); } - if (libmemcached_util_ping("localhost", port, NULL)) + + if (libmemcached_util_ping("localhost", construct->port[x], NULL)) { - fprintf(stderr, "Server on port %u already exists\n", port); + fprintf(stderr, "Server on port %u already exists\n", construct->port[x]); } else { status= system(buffer); fprintf(stderr, "STARTING SERVER: %s status:%d\n", buffer, status); } + int count; size_t remaining_length= sizeof(server_string_buffer) - (size_t)(end_ptr -server_string_buffer); - count= snprintf(end_ptr, remaining_length, "localhost:%u,", port); + count= snprintf(end_ptr, remaining_length, "localhost:%u,", construct->port[x]); if ((size_t)count >= remaining_length || count < 0) { @@ -153,17 +187,20 @@ void server_startup(server_startup_st *construct) *end_ptr= 0; - int *pids= calloc(construct->count, sizeof(int)); for (uint32_t x= 0; x < construct->count; x++) { - char buffer[PATH_MAX]; /* Nothing special for number */ - - snprintf(buffer, sizeof(buffer), PID_FILE_BASE, x); + if (! wait_for_file(construct->pid_file[x])) + { + abort(); + } + } + for (uint32_t x= 0; x < construct->count; x++) + { uint32_t counter= 3000; // Absurd, just to catch run away process - while (pids[x] <= 0 && --counter) + while (construct->pids[x] <= 0 && --counter) { - FILE *file= fopen(buffer, "r"); + FILE *file= fopen(construct->pid_file[x], "r"); if (file) { char pid_buffer[1024]; @@ -171,24 +208,41 @@ void server_startup(server_startup_st *construct) if (found) { - pids[x]= atoi(pid_buffer); + construct->pids[x]= atoi(pid_buffer); fclose(file); - if (pids[x] > 0) + if (construct->pids[x] > 0) break; } fclose(file); } - global_sleep(); + switch (errno) + { + default: + fprintf(stderr, "%s -> fopen(%s)\n", construct->pid_file[x], strerror(errno)); + abort(); + case ENOENT: + case EINTR: + case EACCES: + break; + case ENOTCONN: + continue; + } + + // Safety 3rd, check to see if the file has gone away + if (! wait_for_file(construct->pid_file[x])) + { + abort(); + } } bool was_started= false; - if (pids[x] > 0) + if (construct->pids[x] > 0) { counter= 30; while (--counter) { - if (kill(pids[x], 0) == 0) + if (kill(construct->pids[x], 0) == 0) { was_started= true; break; @@ -199,16 +253,15 @@ void server_startup(server_startup_st *construct) if (was_started == false) { - fprintf(stderr, "Failed to open buffer %s(%d)\n", buffer, pids[x]); + fprintf(stderr, "Failed to open buffer %s(%d)\n", construct->pid_file[x], construct->pids[x]); for (uint32_t y= 0; y < construct->count; y++) { - if (pids[y] > 0) - kill(pids[y], SIGTERM); + if (construct->pids[y] > 0) + kill(construct->pids[y], SIGTERM); } abort(); } } - free(pids); construct->server_list= strdup(server_string_buffer); } @@ -236,9 +289,7 @@ void server_shutdown(server_startup_st *construct) { for (uint32_t x= 0; x < construct->count; x++) { - char file_buffer[PATH_MAX]; /* Nothing special for number */ - snprintf(file_buffer, sizeof(file_buffer), PID_FILE_BASE, x); - kill_file(file_buffer); + kill_file(construct->pid_file[x]); } free(construct->server_list); diff --git a/libtest/server.h b/libtest/server.h index e849f29a..454f69ca 100644 --- a/libtest/server.h +++ b/libtest/server.h @@ -9,6 +9,8 @@ #pragma once +#include + /* Server startup and shutdown functions. */ @@ -19,6 +21,7 @@ extern "C" { #include typedef struct server_startup_st server_startup_st; +#define SERVERS_TO_CREATE 5 struct server_startup_st { @@ -26,6 +29,9 @@ struct server_startup_st uint8_t udp; memcached_server_st *servers; char *server_list; + char pid_file[SERVERS_TO_CREATE][FILENAME_MAX]; + in_port_t port[SERVERS_TO_CREATE]; + int pids[SERVERS_TO_CREATE]; }; void server_startup(server_startup_st *construct); diff --git a/libtest/test.c b/libtest/test.c index da989b17..9a79e4c5 100644 --- a/libtest/test.c +++ b/libtest/test.c @@ -10,7 +10,7 @@ Sample test application. */ -#include "config.h" +#include #include diff --git a/libtest/test.h b/libtest/test.h index b7a2f5ee..58d24373 100644 --- a/libtest/test.h +++ b/libtest/test.h @@ -242,7 +242,7 @@ do \ { \ if (strcmp((A), (B))) \ { \ - fprintf(stderr, "\n%s:%d: %s -> %s\n", __FILE__, __LINE__, (A), (B)); \ + fprintf(stderr, "\n%s:%d: `%s` -> `%s`\n", __FILE__, __LINE__, (A), (B)); \ create_core(); \ return TEST_FAILURE; \ } \ diff --git a/m4/pandora_drizzle_build.m4 b/m4/pandora_drizzle_build.m4 deleted file mode 100644 index 54f946f1..00000000 --- a/m4/pandora_drizzle_build.m4 +++ /dev/null @@ -1,77 +0,0 @@ -dnl Copyright (C) 2009 Sun Microsystems, Inc. -dnl This file is free software; Sun Microsystems, Inc. -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl Check for all of the headers and libs that Drizzle needs. We check all -dnl of these for plugins too, to ensure that all of the appropriate defines -dnl are set. - -AC_DEFUN([PANDORA_DRIZZLE_BUILD],[ - - AC_STRUCT_TM - - AC_FUNC_ALLOCA - AC_FUNC_UTIME_NULL - AC_FUNC_VPRINTF - - PANDORA_WORKING_FDATASYNC - - AC_CHECK_FUNCS(\ - gethrtime \ - setupterm \ - backtrace \ - backtrace_symbols \ - backtrace_symbols_fd) - - AC_HEADER_STAT - AC_HEADER_DIRENT - AC_HEADER_STDC - AC_HEADER_SYS_WAIT - AC_HEADER_STDBOOL - - AC_CHECK_HEADERS(sys/types.h sys/fpu.h fpu_control.h ieeefp.h) - AC_CHECK_HEADERS(select.h sys/select.h) - AC_CHECK_HEADERS(utime.h sys/utime.h ) - AC_CHECK_HEADERS(synch.h sys/mman.h) - AC_CHECK_HEADERS(sched.h) - AC_CHECK_HEADERS(sys/prctl.h) - AC_CHECK_HEADERS(execinfo.h) - AC_CHECK_HEADERS(locale.h) - AC_CHECK_HEADERS(termcap.h termio.h termios.h asm/termbits.h) - AC_CHECK_HEADERS(paths.h) - - - #-------------------------------------------------------------------- - # Check for system libraries. Adds the library to $LIBS - # and defines HAVE_LIBM etc - #-------------------------------------------------------------------- - - # For the sched_yield() function on Solaris - AC_CHECK_FUNC(sched_yield, [], - [AC_CHECK_LIB(posix4, [sched_yield], - [AC_DEFINE(HAVE_SCHED_YIELD, 1, [Have sched_yield function]) LIBS="$LIBS -lposix4"])]) - - AS_IF([test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no"],[ - AC_CHECK_FUNC(gtty, [], [AC_CHECK_LIB(compat, gtty)]) - ]) - - AC_CHECK_HEADERS([curses.h term.h],[],[],[[ - #ifdef HAVE_CURSES_H - # include - #endif - ]]) - AC_CHECK_TYPES([uint, ulong]) - - PANDORA_REQUIRE_BISON - - PANDORA_CXX_DEMANGLE - PANDORA_REQUIRE_BOOST([1.38]) - PANDORA_REQUIRE_BOOST_PROGRAM_OPTIONS - PANDORA_REQUIRE_BOOST_THREAD - PANDORA_REQUIRE_BOOST_REGEX - PANDORA_REQUIRE_BOOST_DATE_TIME - PANDORA_REQUIRE_BOOST_FILESYSTEM - PANDORA_REQUIRE_BOOST_IOSTREAMS - -]) diff --git a/m4/pandora_have_libreadline.m4 b/m4/pandora_have_libreadline.m4 deleted file mode 100644 index b49e97dd..00000000 --- a/m4/pandora_have_libreadline.m4 +++ /dev/null @@ -1,242 +0,0 @@ -# -# SYNOPSIS -# -# PANDORA_HAVE_LIBREADLINE -# -# DESCRIPTION -# -# Searches for a readline compatible library. If found, defines -# `HAVE_LIBREADLINE'. If the found library has the `add_history' -# function, sets also `HAVE_READLINE_HISTORY'. Also checks for the -# locations of the necessary include files and sets `HAVE_READLINE_H' -# or `HAVE_READLINE_READLINE_H' and `HAVE_READLINE_HISTORY_H' or -# 'HAVE_HISTORY_H' if the corresponding include files exists. -# -# The libraries that may be readline compatible are `libedit', -# `libeditline' and `libreadline'. Sometimes we need to link a -# termcap library for readline to work, this macro tests these cases -# too by trying to link with `libtermcap', `libcurses' or -# `libncurses' before giving up. -# -# Here is an example of how to use the information provided by this -# macro to perform the necessary includes or declarations in a C -# file: -# -# #ifdef HAVE_LIBREADLINE -# # if defined(HAVE_READLINE_READLINE_H) -# # include -# # elif defined(HAVE_READLINE_H) -# # include -# # else /* !defined(HAVE_READLINE_H) */ -# extern char *readline (); -# # endif /* !defined(HAVE_READLINE_H) */ -# char *cmdline = NULL; -# #else /* !defined(HAVE_READLINE_READLINE_H) */ -# /* no readline */ -# #endif /* HAVE_LIBREADLINE */ -# -# #ifdef HAVE_READLINE_HISTORY -# # if defined(HAVE_READLINE_HISTORY_H) -# # include -# # elif defined(HAVE_HISTORY_H) -# # include -# # else /* !defined(HAVE_HISTORY_H) */ -# extern void add_history (); -# extern int write_history (); -# extern int read_history (); -# # endif /* defined(HAVE_READLINE_HISTORY_H) */ -# /* no history */ -# #endif /* HAVE_READLINE_HISTORY */ -# -# LAST MODIFICATION -# -# 2009-11-17 -# -# Based on VL_LIB_READLINE from Ville Laurikari -# -# COPYLEFT -# -# Copyright (C) 2009 Monty Taylor -# Copyright (C) 2002 Ville Laurikari -# -# Copying and distribution of this file, with or without -# modification, are permitted in any medium without royalty provided -# the copyright notice and this notice are preserved. - -AC_DEFUN([PANDORA_CHECK_TIOCGWINSZ],[ - AC_CACHE_CHECK([for TIOCGWINSZ in sys/ioctl.h], - [pandora_cv_tiocgwinsz_in_ioctl],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ -#include -#include - ]],[[ -int x= TIOCGWINSZ; - ]]) - ],[ - pandora_cv_tiocgwinsz_in_ioctl=yes - ],[ - pandora_cv_tiocgwinsz_in_ioctl=no - ]) - ]) - AS_IF([test "$pandora_cv_tiocgwinsz_in_ioctl" = "yes"],[ - AC_DEFINE([GWINSZ_IN_SYS_IOCTL], [1], - [READLINE: your system defines TIOCGWINSZ in sys/ioctl.h.]) - ]) -]) - -AC_DEFUN([PANDORA_CHECK_RL_COMPENTRY], [ - AC_CACHE_CHECK([defined rl_compentry_func_t], [pandora_cv_rl_compentry],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ -#include "stdio.h" -#include "readline/readline.h" - ]],[[ -rl_compentry_func_t *func2= (rl_compentry_func_t*)0; - ]]) - ],[ - pandora_cv_rl_compentry=yes - ],[ - pandora_cv_rl_compentry=no - ]) - ]) - AS_IF([test "$pandora_cv_rl_compentry" = "yes"],[ - AC_DEFINE([HAVE_RL_COMPENTRY], [1], - [Does system provide rl_compentry_func_t]) - ]) - - save_CXXFLAGS="${CXXFLAGS}" - CXXFLAGS="${AM_CXXFLAGS} ${CXXFLAGS}" - AC_LANG_PUSH(C++) - AC_CACHE_CHECK([rl_compentry_func_t works], [pandora_cv_rl_compentry_works],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ -#include "stdio.h" -#include "readline/readline.h" - ]],[[ -rl_completion_entry_function= (rl_compentry_func_t*)NULL; - ]]) - ],[ - pandora_cv_rl_compentry_works=yes - ],[ - pandora_cv_rl_compentry_works=no - ]) - ]) - AS_IF([test "$pandora_cv_rl_compentry_works" = "yes"],[ - AC_DEFINE([HAVE_WORKING_RL_COMPENTRY], [1], - [Does system provide an rl_compentry_func_t that is usable]) - ]) - CXXFLAGS="${save_CXXFLAGS}" - AC_LANG_POP() -]) - - -AC_DEFUN([PANDORA_CHECK_RL_COMPLETION_FUNC], [ - AC_CACHE_CHECK([defined rl_completion_func_t], [pandora_cv_rl_completion],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ -#include "stdio.h" -#include "readline/readline.h" - ]],[[ -rl_completion_func_t *func1= (rl_completion_func_t*)0; - ]]) - ],[ - pandora_cv_rl_completion=yes - ],[ - pandora_cv_rl_completion=no - ]) - ]) - AS_IF([test "$pandora_cv_rl_completion" = "yes"],[ - AC_DEFINE([HAVE_RL_COMPLETION], [1], - [Does system provide rl_completion_func_t]) - ]) -]) - -AC_DEFUN([_PANDORA_SEARCH_LIBREADLINE], [ - - save_LIBS="${LIBS}" - LIBS="" - - AC_CACHE_CHECK([for a readline compatible library], - ac_cv_libreadline, [ - ORIG_LIBS="$LIBS" - for readline_lib in readline edit editline; do - for termcap_lib in "" termcap curses ncurses; do - if test -z "$termcap_lib"; then - TRY_LIB="-l$readline_lib" - else - TRY_LIB="-l$readline_lib -l$termcap_lib" - fi - LIBS="$ORIG_LIBS $TRY_LIB" - AC_TRY_LINK_FUNC(readline, ac_cv_libreadline="$TRY_LIB") - if test -n "$ac_cv_libreadline"; then - break - fi - done - if test -n "$ac_cv_libreadline"; then - break - fi - done - if test -z "$ac_cv_libreadline"; then - ac_cv_libreadline="no" - LIBS="$ORIG_LIBS" - fi - ]) - - if test "$ac_cv_libreadline" != "no"; then - AC_DEFINE(HAVE_LIBREADLINE, 1, - [Define if you have a readline compatible library]) - AC_CHECK_HEADERS(readline.h readline/readline.h) - AC_CACHE_CHECK([whether readline supports history], - ac_cv_libreadline_history, [ - ac_cv_libreadline_history="no" - AC_TRY_LINK_FUNC(add_history, ac_cv_libreadline_history="yes") - ]) - if test "$ac_cv_libreadline_history" = "yes"; then - AC_DEFINE(HAVE_READLINE_HISTORY, 1, - [Define if your readline library has \`add_history']) - AC_CHECK_HEADERS(history.h readline/history.h) - fi - fi - PANDORA_CHECK_RL_COMPENTRY - PANDORA_CHECK_RL_COMPLETION_FUNC - PANDORA_CHECK_TIOCGWINSZ - - - READLINE_LIBS="${LIBS}" - LIBS="${save_LIBS}" - AC_SUBST(READLINE_LIBS) - - AM_CONDITIONAL(HAVE_LIBREADLINE, [test "x${ac_cv_libreadline}" = "xyes"]) -]) - -AC_DEFUN([_PANDORA_HAVE_LIBREADLINE],[ - - AC_ARG_ENABLE([libreadline], - [AS_HELP_STRING([--disable-libreadline], - [Build with libreadline support @<:@default=on@:>@])], - [ac_enable_libreadline="$enableval"], - [ac_enable_libreadline="yes"]) - - _PANDORA_SEARCH_LIBREADLINE -]) - - -AC_DEFUN([PANDORA_HAVE_LIBREADLINE],[ - AC_REQUIRE([_PANDORA_HAVE_LIBREADLINE]) -]) - -AC_DEFUN([_PANDORA_REQUIRE_LIBREADLINE],[ - ac_enable_libreadline="yes" - _PANDORA_SEARCH_LIBREADLINE - - AS_IF([test "x$ac_cv_libreadline" = "xno"], - AC_MSG_ERROR([libreadline is required for ${PACKAGE}. On Debian this can be found in libreadline5-dev. On RedHat this can be found in readline-devel.])) - -]) - -AC_DEFUN([PANDORA_REQUIRE_LIBREADLINE],[ - AC_REQUIRE([_PANDORA_REQUIRE_LIBREADLINE]) -]) - - diff --git a/tests/hash_plus.cc b/tests/hash_plus.cc index c148d3ef..140d28fc 100644 --- a/tests/hash_plus.cc +++ b/tests/hash_plus.cc @@ -3,9 +3,9 @@ */ #include -#include -#include -#include +#include +#include +#include #include @@ -69,7 +69,7 @@ static test_return_t digest_test(void *obj) return TEST_SUCCESS; } -static test_return_t set_function_test(void *obj) +static test_return_t set_function_test(void *) { Hashkit hashk; hashkit_hash_algorithm_t algo_list[]= { @@ -84,21 +84,15 @@ static test_return_t set_function_test(void *obj) HASHKIT_HASH_JENKINS, HASHKIT_HASH_MAX }; - hashkit_hash_algorithm_t *algo; - (void)obj; - for (algo= algo_list; *algo != HASHKIT_HASH_MAX; algo++) + for (hashkit_hash_algorithm_t *algo= algo_list; *algo != HASHKIT_HASH_MAX; algo++) { - hashkit_return_t rc; - uint32_t x; - const char **ptr; - uint32_t *list; - - rc= hashk.set_function(*algo); + hashkit_return_t rc= hashk.set_function(*algo); test_true(rc == HASHKIT_SUCCESS); + uint32_t *list; switch (*algo) { case HASHKIT_HASH_DEFAULT: @@ -123,9 +117,18 @@ static test_return_t set_function_test(void *obj) list= fnv1a_32_values; break; case HASHKIT_HASH_HSIEH: +#ifndef HAVE_HSIEH_HASH + continue; +#endif list= hsieh_values; break; case HASHKIT_HASH_MURMUR: +#ifdef WORDS_BIGENDIAN + continue; +#endif +#ifndef HAVE_MURMUR_HASH + continue; +#endif list= murmur_values; break; case HASHKIT_HASH_JENKINS: @@ -139,12 +142,16 @@ static test_return_t set_function_test(void *obj) } // Now we make sure we did set the hash correctly. + uint32_t x; + const char **ptr; for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) { uint32_t hash_val; hash_val= hashk.digest(*ptr, strlen(*ptr)); - test_true(list[x] == hash_val); + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%lu %lus %s", (unsigned long)list[x], (unsigned long)hash_val, libhashkit_string_hash(*algo)); + test_true_got(list[x] == hash_val, buffer); } } @@ -158,7 +165,7 @@ static test_return_t set_distribution_function_test(void *obj) (void)obj; rc= hashk.set_distribution_function(HASHKIT_HASH_CUSTOM); - test_true(rc == HASHKIT_FAILURE); + test_true_got(rc == HASHKIT_FAILURE or rc == HASHKIT_INVALID_ARGUMENT, hashkit_strerror(NULL, rc)); rc= hashk.set_distribution_function(HASHKIT_HASH_JENKINS); test_true(rc == HASHKIT_SUCCESS); diff --git a/tests/include.am b/tests/include.am index 490ed023..990c772d 100644 --- a/tests/include.am +++ b/tests/include.am @@ -43,8 +43,7 @@ noinst_HEADERS+= \ noinst_PROGRAMS+= \ tests/atomsmasher \ - tests/hashplus \ - tests/memplus \ + tests/hash_plus \ tests/startservers \ tests/testapp \ tests/testhashkit \ @@ -100,19 +99,15 @@ tests_testhashkit_SOURCES = tests/hashkit_functions.c tests_testhashkit_DEPENDENCIES = libtest/libtest.la libhashkit/libhashkit.la tests_testhashkit_LDADD = $(tests_testhashkit_DEPENDENCIES) $(LIBSASL) -tests_hashplus_SOURCES = tests/hash_plus.cc -tests_hashplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX) -tests_hashplus_DEPENDENCIES = $(tests_testhashkit_DEPENDENCIES) -tests_hashplus_LDADD = $(tests_testhashkit_DEPENDENCIES) $(LIBSASL) - -tests_memplus_SOURCES = tests/mem_plus.cc -tests_memplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX) -tests_memplus_DEPENDENCIES = $(TESTS_LDADDS) -tests_memplus_LDADD = $(tests_memplus_DEPENDENCIES) $(LIBSASL) +tests_hash_plus_SOURCES = tests/hash_plus.cc +tests_hash_plus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX) +tests_hash_plus_DEPENDENCIES = $(tests_testhashkit_DEPENDENCIES) +tests_hash_plus_LDADD = $(tests_testhashkit_DEPENDENCIES) $(LIBSASL) +check_PROGRAMS+= tests/hash_plus test: check -check-local: $(TEST_DOCS) test-mem test-hash memcapable +check-local: tests/var $(TEST_DOCS) test-mem test-hash memcapable @echo "Tests completed" test-x: check-local test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat @@ -238,8 +233,6 @@ MEM_COMMAND= tests/testapp $(COLLECTION) $(SUITE) TESTPLUS_COMMAND= tests/testplus $(COLLECTION) $(SUITE) -MEMPLUS_COMMAND= tests/memplus $(COLLECTION) $(SUITE) - HASHPLUS_COMMAND= tests/hashplus $(COLLECTION) $(SUITE) ATOM_COMMAND= tests/atomsmasher $(COLLECTION) $(SUITE) @@ -248,7 +241,7 @@ UDP_COMMAND= tests/testudp $(COLLECTION) $(SUITE) HASH_COMMAND= tests/testhashkit $(COLLECTION) $(SUITE) -test-mem: tests/testapp support/example.cnf +test-mem: tests/testapp $(MEM_COMMAND) test-udp: tests/testudp @@ -266,9 +259,6 @@ test-hash: tests/testhashkit test-hashplus: tests/hashplus $(HASHPLUS_COMMAND) -test-memplus: tests/memplus - $(MEMPLUS_COMMAND) - pahole-mem: tests/testapp $(PAHOLE_COMMAND) $(MEM_COMMAND) @@ -290,9 +280,6 @@ gdb-hash: tests/testhashkit gdb-hashplus: tests/hashplus $(DEBUG_COMMAND) $(HASHPLUS_COMMAND) -gdb-memplus: tests/memplus - $(DEBUG_COMMAND) $(MEMPLUS_COMMAND) - gdb-memslap: clients/memslap $(DEBUG_COMMAND) $(MEMSLAP_COMMAND) @@ -314,9 +301,6 @@ valgrind-hash: tests/testhashkit valgrind-hashplus: tests/hashplus $(VALGRIND_COMMAND) $(HASHPLUS_COMMAND) -valgrind-memplus: tests/memplus - $(VALGRIND_COMMAND) $(MEMPLUS_COMMAND) - valgrind-memslap: clients/memslap $(VALGRIND_COMMAND) $(MEMSLAP_COMMAND) diff --git a/tests/mem_functions.c b/tests/mem_functions.c index e3f6426a..15daa39f 100644 --- a/tests/mem_functions.c +++ b/tests/mem_functions.c @@ -231,7 +231,12 @@ static memcached_return_t server_display_unsort_function(const memcached_st *ptr uint32_t x= *((uint32_t *)(context)); (void)ptr; - assert(test_ports[x] == server->port); + if (! (test_ports[x] == server->port)) + { + fprintf(stderr, "%lu -> %lu\n", (unsigned long)test_ports[x], (unsigned long)server->port); + return MEMCACHED_FAILURE; + } + *((uint32_t *)(context))= ++x; return MEMCACHED_SUCCESS; @@ -405,7 +410,7 @@ static test_return_t error_test(memcached_st *memc) 54481931U, 4186304426U, 1741088401U, 2979625118U, 4159057246U, 3425930182U, 2593724503U, 1868899624U, 1769812374U, 2302537950U, 1110330676U, 3365377466U, - 1336171666U, 3365377466U }; + 1336171666U, 3021258493U, 3365377466U }; // You have updated the memcache_error messages but not updated docs/tests. for (rc= MEMCACHED_SUCCESS; rc < MEMCACHED_MAXIMUM_RETURN; rc++) @@ -421,7 +426,7 @@ static test_return_t error_test(memcached_st *memc) } test_true(values[rc] == hash_val); } - test_true(MEMCACHED_MAXIMUM_RETURN == 45); + test_true(MEMCACHED_MAXIMUM_RETURN == 46); return TEST_SUCCESS; } @@ -2000,21 +2005,15 @@ static test_return_t MEMCACHED_BEHAVIOR_CORK_test(memcached_st *memc) { memcached_return_t rc; bool set= true; - bool value; rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CORK, set); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOT_SUPPORTED); + test_true(rc == MEMCACHED_DEPRECATED); - value= (bool)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_CORK); - - if (rc == MEMCACHED_SUCCESS) - { - test_true((bool)value == set); - } - else - { - test_false((bool)value == set); - } + // Platform dependent +#if 0 + bool value= (bool)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_CORK); + test_false(value); +#endif return TEST_SUCCESS; } @@ -5477,7 +5476,7 @@ static test_return_t test_cull_servers(memcached_st *memc) uint32_t count = memcached_server_count(memc); // Do not do this in your code, it is not supported. - memc->servers[1].state.is_dead= true; + memc->servers[1].options.is_dead= true; memc->state.is_time_for_rebuild= true; uint32_t new_count= memcached_server_count(memc); @@ -5752,7 +5751,7 @@ static test_return_t regression_bug_583031(memcached_st *unused) (void)memcached_get(memc, "dsf", 3, &length, &flags, &rc); - test_true_got(rc == MEMCACHED_TIMEOUT || rc == MEMCACHED_ERRNO, memcached_strerror(memc, rc)); + test_true_got(rc == MEMCACHED_TIMEOUT || rc == MEMCACHED_ERRNO || rc == MEMCACHED_FAILURE, memcached_strerror(memc, rc)); memcached_free(memc); @@ -6225,7 +6224,8 @@ test_st parser_tests[] ={ {"randomly generated options", 0, (test_callback_fn)random_statement_build_test }, {"prefix_key", 0, (test_callback_fn)parser_key_prefix_test }, {"server", 0, (test_callback_fn)server_test }, - {"servers", 0, (test_callback_fn)servers_test }, + {"bad server strings", 0, (test_callback_fn)servers_bad_test }, + {"server with weights", 0, (test_callback_fn)server_with_weight_test }, {0, 0, (test_callback_fn)0} }; @@ -6302,8 +6302,6 @@ collection_st collection[] ={ {0, 0, 0, 0} }; -#define SERVERS_TO_CREATE 5 - #include "libmemcached_world.h" void get_world(world_st *world) diff --git a/tests/mem_plus.cc b/tests/mem_plus.cc deleted file mode 100644 index d9a76afb..00000000 --- a/tests/mem_plus.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - C++ to libmemcit -*/ -#include - -#include -#include -#include - -#include - -static test_return_t exists_test(void *obj) -{ - Memcached memc; - (void)obj; - (void)memc; - - return TEST_SUCCESS; -} - -static test_return_t new_test(void *obj) -{ - Memcached *memc= new Memcached; - (void)obj; - - (void)memc; - - delete memc; - - return TEST_SUCCESS; -} - -static test_return_t copy_test(void *obj) -{ - Memcached *memc= new Memcached; - Memcached *copy(memc); - (void)obj; - - (void)copy; - - delete memc; - - return TEST_SUCCESS; -} - -static test_return_t assign_test(void *obj) -{ - Memcached memc; - Memcached copy; - (void)obj; - - copy= memc; - - (void)copy; - - return TEST_SUCCESS; -} - -test_st basic[] ={ - { "exists", 0, reinterpret_cast(exists_test) }, - { "new", 0, reinterpret_cast(new_test) }, - { "copy", 0, reinterpret_cast(copy_test) }, - { "assign", 0, reinterpret_cast(assign_test) }, - { 0, 0, 0} -}; - -collection_st collection[] ={ - {"basic", 0, 0, basic}, - {0, 0, 0, 0} -}; - -void get_world(world_st *world) -{ - world->collections= collection; -} diff --git a/tests/parser.cc b/tests/parser.cc index 61d846c9..c7b7dc09 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -125,13 +125,6 @@ static test_return_t __check_AUTO_EJECT_HOSTS(memcached_st *memc, const scanner_ return TEST_SUCCESS; } -static test_return_t __check_CACHE_LOOKUPS(memcached_st *memc, const scanner_string_st &value) -{ - (void)value; - test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_CACHE_LOOKUPS)); - return TEST_SUCCESS; -} - static test_return_t __check_NOREPLY(memcached_st *memc, const scanner_string_st &value) { (void)value; @@ -163,18 +156,18 @@ scanner_variable_t test_server_strings[]= { { NIL, scanner_string_null, scanner_string_null, NULL } }; -scanner_variable_t test_servers_strings[]= { - { ARRAY, make_scanner_string("--servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225"), scanner_string_null, NULL }, - { ARRAY, make_scanner_string("--servers=a.example.com:81,localhost:82,b.example.com"), scanner_string_null, NULL }, - { ARRAY, make_scanner_string("--servers=localhost,localhost:80"), scanner_string_null, NULL }, - { NIL, scanner_string_null, scanner_string_null, NULL} +scanner_variable_t test_server_strings_with_weights[]= { + { ARRAY, make_scanner_string("--server=10.0.2.1:30/?40"), make_scanner_string("10.0.2.1"), __check_host }, + { ARRAY, make_scanner_string("--server=example.com:1024/?30"), make_scanner_string("example.com"), __check_host }, + { ARRAY, make_scanner_string("--server=10.0.2.1/?20"), make_scanner_string("10.0.2.1"), __check_host }, + { ARRAY, make_scanner_string("--server=example.com/?10"), make_scanner_string("example.com"), __check_host }, + { NIL, scanner_string_null, scanner_string_null, NULL } }; - scanner_variable_t bad_test_strings[]= { { ARRAY, make_scanner_string("-servers=localhost:11221,localhost:11222,localhost:11223,localhost:11224,localhost:11225"), scanner_string_null, NULL }, { ARRAY, make_scanner_string("-- servers=a.example.com:81,localhost:82,b.example.com"), scanner_string_null, NULL }, - { ARRAY, make_scanner_string("--servers=localhost+80"), scanner_string_null, NULL}, + { ARRAY, make_scanner_string("--servers=localhost:+80"), scanner_string_null, NULL}, { ARRAY, make_scanner_string("--servers=localhost.com."), scanner_string_null, NULL}, { ARRAY, make_scanner_string("--server=localhost.com."), scanner_string_null, NULL}, { ARRAY, make_scanner_string("--server=localhost.com.:80"), scanner_string_null, NULL}, @@ -201,9 +194,7 @@ scanner_variable_t test_boolean_options[]= { { ARRAY, make_scanner_string("--AUTO_EJECT_HOSTS"), scanner_string_null, __check_AUTO_EJECT_HOSTS }, { ARRAY, make_scanner_string("--BINARY_PROTOCOL"), scanner_string_null, NULL }, { ARRAY, make_scanner_string("--BUFFER_REQUESTS"), scanner_string_null, NULL }, - { ARRAY, make_scanner_string("--CACHE_LOOKUPS"), scanner_string_null, __check_CACHE_LOOKUPS }, { ARRAY, make_scanner_string("--HASH_WITH_PREFIX_KEY"), scanner_string_null, NULL }, - { ARRAY, make_scanner_string("--KETAMA_WEIGHTED"), scanner_string_null, NULL }, { ARRAY, make_scanner_string("--NOREPLY"), scanner_string_null, __check_NOREPLY }, { ARRAY, make_scanner_string("--RANDOMIZE_REPLICA_READ"), scanner_string_null, NULL }, { ARRAY, make_scanner_string("--SORT_HOSTS"), scanner_string_null, NULL }, @@ -258,13 +249,17 @@ static test_return_t _test_option(scanner_variable_t *scanner, bool test_true= t if (test_true) { if (rc != MEMCACHED_SUCCESS) + { memcached_error_print(memc); + } test_true(rc == MEMCACHED_SUCCESS); if (ptr->check_func) { - (*ptr->check_func)(memc, ptr->result); + test_return_t test_rc= (*ptr->check_func)(memc, ptr->result); + if (test_rc != TEST_SUCCESS) + return test_rc; } } else @@ -278,28 +273,19 @@ static test_return_t _test_option(scanner_variable_t *scanner, bool test_true= t return TEST_SUCCESS; } -test_return_t server_test(memcached_st *junk) +test_return_t server_test(memcached_st *) { - (void)junk; return _test_option(test_server_strings); } -test_return_t servers_test(memcached_st *junk) +test_return_t server_with_weight_test(memcached_st *) { - (void)junk; + return _test_option(test_server_strings_with_weights); +} +test_return_t servers_bad_test(memcached_st *) +{ test_return_t rc; - if ((rc= _test_option(test_server_strings)) != TEST_SUCCESS) - { - return rc; - } - -#if 0 - memcached_server_fn callbacks[1]; - callbacks[0]= server_print_callback; - memcached_server_cursor(memc, callbacks, NULL, 1); -#endif - if ((rc= _test_option(bad_test_strings, false)) != TEST_SUCCESS) { return rc; @@ -308,48 +294,40 @@ test_return_t servers_test(memcached_st *junk) return TEST_SUCCESS; } -test_return_t parser_number_options_test(memcached_st *junk) +test_return_t parser_number_options_test(memcached_st*) { - (void)junk; return _test_option(test_number_options); } -test_return_t parser_boolean_options_test(memcached_st *junk) +test_return_t parser_boolean_options_test(memcached_st*) { - (void)junk; return _test_option(test_boolean_options); } -test_return_t behavior_parser_test(memcached_st *junk) +test_return_t behavior_parser_test(memcached_st*) { - (void)junk; return TEST_SUCCESS; } -test_return_t parser_hash_test(memcached_st *junk) +test_return_t parser_hash_test(memcached_st*) { - (void)junk; return _test_option(hash_strings); } -test_return_t parser_distribution_test(memcached_st *junk) +test_return_t parser_distribution_test(memcached_st*) { - (void)junk; return _test_option(distribution_strings); } -test_return_t parser_key_prefix_test(memcached_st *junk) +test_return_t parser_key_prefix_test(memcached_st*) { - (void)junk; return _test_option(distribution_strings); } #define SUPPORT_EXAMPLE_CNF "support/example.cnf" -test_return_t memcached_parse_configure_file_test(memcached_st *junk) +test_return_t memcached_parse_configure_file_test(memcached_st*) { - (void)junk; - if (access(SUPPORT_EXAMPLE_CNF, R_OK)) return TEST_SKIPPED; @@ -365,9 +343,8 @@ test_return_t memcached_parse_configure_file_test(memcached_st *junk) return TEST_SUCCESS; } -test_return_t memcached_create_with_options_with_filename(memcached_st *junk) +test_return_t memcached_create_with_options_with_filename(memcached_st*) { - (void)junk; if (access(SUPPORT_EXAMPLE_CNF, R_OK)) return TEST_SKIPPED; @@ -379,10 +356,8 @@ test_return_t memcached_create_with_options_with_filename(memcached_st *junk) return TEST_SUCCESS; } -test_return_t libmemcached_check_configuration_with_filename_test(memcached_st *junk) +test_return_t libmemcached_check_configuration_with_filename_test(memcached_st*) { - (void)junk; - if (access(SUPPORT_EXAMPLE_CNF, R_OK)) return TEST_SKIPPED; @@ -401,10 +376,8 @@ test_return_t libmemcached_check_configuration_with_filename_test(memcached_st * return TEST_SUCCESS; } -test_return_t libmemcached_check_configuration_test(memcached_st *junk) +test_return_t libmemcached_check_configuration_test(memcached_st*) { - (void)junk; - memcached_return_t rc; char buffer[BUFSIZ]; @@ -418,10 +391,8 @@ test_return_t libmemcached_check_configuration_test(memcached_st *junk) return TEST_SUCCESS; } -test_return_t memcached_create_with_options_test(memcached_st *junk) +test_return_t memcached_create_with_options_test(memcached_st*) { - (void)junk; - memcached_st *memc_ptr; memc_ptr= memcached_create_with_options(STRING_WITH_LEN("--server=localhost")); test_true_got(memc_ptr, memcached_last_error_message(memc_ptr)); @@ -433,12 +404,11 @@ test_return_t memcached_create_with_options_test(memcached_st *junk) return TEST_SUCCESS; } -test_return_t test_include_keyword(memcached_st *junk) +test_return_t test_include_keyword(memcached_st*) { if (access(SUPPORT_EXAMPLE_CNF, R_OK)) return TEST_SKIPPED; - (void)junk; char buffer[BUFSIZ]; memcached_return_t rc; rc= libmemcached_check_configuration(STRING_WITH_LEN("INCLUDE \"support/example.cnf\""), buffer, sizeof(buffer)); @@ -447,9 +417,8 @@ test_return_t test_include_keyword(memcached_st *junk) return TEST_SUCCESS; } -test_return_t test_end_keyword(memcached_st *junk) +test_return_t test_end_keyword(memcached_st*) { - (void)junk; char buffer[BUFSIZ]; memcached_return_t rc; rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost END bad keywords"), buffer, sizeof(buffer)); @@ -458,9 +427,8 @@ test_return_t test_end_keyword(memcached_st *junk) return TEST_SUCCESS; } -test_return_t test_reset_keyword(memcached_st *junk) +test_return_t test_reset_keyword(memcached_st*) { - (void)junk; char buffer[BUFSIZ]; memcached_return_t rc; rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost reset --server=bad.com"), buffer, sizeof(buffer)); @@ -469,9 +437,8 @@ test_return_t test_reset_keyword(memcached_st *junk) return TEST_SUCCESS; } -test_return_t test_error_keyword(memcached_st *junk) +test_return_t test_error_keyword(memcached_st*) { - (void)junk; char buffer[BUFSIZ]; memcached_return_t rc; rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost ERROR --server=bad.com"), buffer, sizeof(buffer)); @@ -480,20 +447,14 @@ test_return_t test_error_keyword(memcached_st *junk) return TEST_SUCCESS; } -#define RANDOM_STRINGS 50 -test_return_t random_statement_build_test(memcached_st *junk) +#define RANDOM_STRINGS 100 +test_return_t random_statement_build_test(memcached_st*) { - (void)junk; std::vector option_list; for (scanner_variable_t *ptr= test_server_strings; ptr->type != NIL; ptr++) option_list.push_back(&ptr->option); -#if 0 - for (scanner_variable_t *ptr= test_servers_strings; ptr->type != NIL; ptr++) - option_list.push_back(&ptr->option); -#endif - for (scanner_variable_t *ptr= test_number_options; ptr->type != NIL; ptr++) option_list.push_back(&ptr->option); diff --git a/tests/parser.h b/tests/parser.h index b21cdf70..c12a7bdf 100644 --- a/tests/parser.h +++ b/tests/parser.h @@ -47,55 +47,58 @@ LIBTEST_INTERNAL_API test_return_t server_test(memcached_st *memc); LIBTEST_INTERNAL_API -test_return_t servers_test(memcached_st *memc); +test_return_t servers_bad_test(memcached_st *memc); LIBTEST_INTERNAL_API -test_return_t behavior_parser_test(memcached_st *junk); +test_return_t behavior_parser_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t parser_number_options_test(memcached_st *junk); +test_return_t parser_number_options_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t parser_distribution_test(memcached_st *junk); +test_return_t parser_distribution_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t parser_hash_test(memcached_st *junk); +test_return_t parser_hash_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t parser_boolean_options_test(memcached_st *junk); +test_return_t parser_boolean_options_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t parser_key_prefix_test(memcached_st *junk); +test_return_t parser_key_prefix_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t memcached_parse_configure_file_test(memcached_st *junk); +test_return_t memcached_parse_configure_file_test(memcached_st*); LIBTEST_INTERNAL_API - test_return_t libmemcached_check_configuration_test(memcached_st *junk); + test_return_t libmemcached_check_configuration_test(memcached_st*); LIBTEST_INTERNAL_API - test_return_t memcached_create_with_options_test(memcached_st *junk); + test_return_t memcached_create_with_options_test(memcached_st*); LIBTEST_INTERNAL_API - test_return_t memcached_create_with_options_with_filename(memcached_st *junk); + test_return_t memcached_create_with_options_with_filename(memcached_st*); LIBTEST_INTERNAL_API - test_return_t libmemcached_check_configuration_with_filename_test(memcached_st *junk); + test_return_t libmemcached_check_configuration_with_filename_test(memcached_st*); LIBTEST_INTERNAL_API - test_return_t random_statement_build_test(memcached_st *junk); + test_return_t random_statement_build_test(memcached_st*); LIBTEST_INTERNAL_API -test_return_t test_include_keyword(memcached_st *junk); +test_return_t test_include_keyword(memcached_st*); LIBTEST_INTERNAL_API -test_return_t test_end_keyword(memcached_st *junk); +test_return_t test_end_keyword(memcached_st*); LIBTEST_INTERNAL_API -test_return_t test_reset_keyword(memcached_st *junk); +test_return_t test_reset_keyword(memcached_st*); LIBTEST_INTERNAL_API -test_return_t test_error_keyword(memcached_st *junk); +test_return_t test_error_keyword(memcached_st*); + +LIBTEST_INTERNAL_API +test_return_t server_with_weight_test(memcached_st *); #ifdef __cplusplus } diff --git a/unittests/include.am b/unittests/include.am deleted file mode 100644 index b7ca5d26..00000000 --- a/unittests/include.am +++ /dev/null @@ -1,20 +0,0 @@ -# vim:ft=automake -# included from Top Level Makefile.am -# All paths should be given relative to the root - -if HAVE_LIBGTEST -check_PROGRAMS += unittests/unittests -endif - -unittests_unittests_SOURCES= \ - unittests/main.cc \ - unittests/strings.cc - -unittests_unittests_CXXFLAGS= ${AM_CXXFLAGS} ${NO_WERROR} ${NO_EFF_CXX} -unittests_unittests_LDADD= \ - libtest/libserver.la \ - libmemcached/libmemcachedinternal.la \ - ${TESTS_LDADDS} ${LTLIBGTEST} -# Shorthand -unit: check-TESTS - diff --git a/unittests/main.cc b/unittests/main.cc deleted file mode 100644 index 7e575c30..00000000 --- a/unittests/main.cc +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * - * Copyright (C) 2010 Monty Taylor - * - * All rights reserved. - * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. - */ - -#include "config.h" - -#include - - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/unittests/strings.cc b/unittests/strings.cc deleted file mode 100644 index 8728926b..00000000 --- a/unittests/strings.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* libMemcached - * Copyright (C) 2010 Brian Aker - * All rights reserved. - * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. - */ - -#include "config.h" - -#include - -#include - -TEST(memcached_string_st, memcached_create_static) -{ - memcached_string_st string; - memcached_string_st *string_ptr; - - memcached_st *memc= memcached_create(NULL); - string_ptr= memcached_string_create(memc, &string, 0); - ASSERT_TRUE(string.options.is_initialized); - ASSERT_TRUE(string_ptr); - - /* The following two better be the same! */ - ASSERT_FALSE(memcached_is_allocated(string_ptr)); - ASSERT_FALSE(memcached_is_allocated(&string)); - EXPECT_EQ(&string, string_ptr); - - ASSERT_TRUE(string.options.is_initialized); - ASSERT_TRUE(memcached_is_initialized(&string)); - memcached_string_free(&string); - ASSERT_FALSE(memcached_is_initialized(&string)); - - memcached_free(memc); -} - -TEST(memcached_string_st, memcached_create_null) -{ - memcached_string_st *string; - memcached_st *memc= memcached_create(NULL); - - string= memcached_string_create(memc, NULL, 0); - ASSERT_TRUE(string); - ASSERT_TRUE(memcached_is_allocated(string)); - ASSERT_TRUE(memcached_is_initialized(string)); - memcached_string_free(string); - - memcached_free(memc); -} - -TEST(memcached_string_st, string_alloc_with_size) -{ - memcached_string_st *string; - memcached_st *memc= memcached_create(NULL); - - string= memcached_string_create(memc, NULL, 1024); - ASSERT_TRUE(string); - ASSERT_TRUE(memcached_is_allocated(string)); - ASSERT_TRUE(memcached_is_initialized(string)); - memcached_string_free(string); - - memcached_free(memc); -} - -TEST(memcached_string_st, string_alloc_with_size_toobig) -{ - memcached_st *memc= memcached_create(NULL); - memcached_string_st *string; - - string= memcached_string_create(memc, NULL, SIZE_MAX); - ASSERT_FALSE(string); - - memcached_free(memc); -} - -TEST(memcached_string_st, string_alloc_append) -{ - char buffer[SMALL_STRING_LEN]; - memcached_string_st *string; - - memcached_st *memc= memcached_create(NULL); - - /* Ring the bell! */ - memset(buffer, 6, SMALL_STRING_LEN); - - string= memcached_string_create(memc, NULL, 100); - ASSERT_TRUE(string); - ASSERT_TRUE(memcached_is_allocated(string)); - ASSERT_TRUE(memcached_is_initialized(string)); - - for (uint32_t x= 0; x < 1024; x++) - { - memcached_return_t rc; - rc= memcached_string_append(string, buffer, SMALL_STRING_LEN); - EXPECT_EQ(rc, MEMCACHED_SUCCESS); - } - ASSERT_TRUE(memcached_is_allocated(string)); - memcached_string_free(string); - - memcached_free(memc); -} - -TEST(memcached_string_st, string_alloc_append_toobig) -{ - memcached_return_t rc; - char buffer[SMALL_STRING_LEN]; - memcached_string_st *string; - - memcached_st *memc= memcached_create(NULL); - - /* Ring the bell! */ - memset(buffer, 6, SMALL_STRING_LEN); - - string= memcached_string_create(memc, NULL, 100); - ASSERT_TRUE(string); - ASSERT_TRUE(memcached_is_allocated(string)); - ASSERT_TRUE(memcached_is_initialized(string)); - - for (uint32_t x= 0; x < 1024; x++) - { - rc= memcached_string_append(string, buffer, SMALL_STRING_LEN); - EXPECT_EQ(rc, MEMCACHED_SUCCESS); - } - rc= memcached_string_append(string, buffer, SIZE_MAX); - EXPECT_EQ(rc, MEMCACHED_MEMORY_ALLOCATION_FAILURE); - ASSERT_TRUE(memcached_is_allocated(string)); - memcached_string_free(string); - - memcached_free(memc); -}