From: Brian Aker Date: Fri, 24 Jun 2011 20:09:30 +0000 (-0700) Subject: Merge in trunk. Updates to manual/update to latest libtest. X-Git-Tag: 0.51~3 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=50dc8599f105fe915607e6f2d57851fd9acad839;hp=625e84ebfc422790372bc2984f504bdcb4da779c;p=m6w6%2Flibmemcached Merge in trunk. Updates to manual/update to latest libtest. --- diff --git a/ChangeLog b/ChangeLog index 3e7cc639..969eda06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ -0.50 - +0.50 Mon Jun 20 10:36:57 PDT 2011 * Updates to C++ interface * Custom free allocators need to now check for value before calling free. - + * memcached_fetch_result() now uses the internal result when available (about 25 to 50% faster). + * Fix for stats structure. + * Updates to documentation. * memcached_fetch_result() now uses the internal result when available (about 25 to 50% faster). 0.49 Thu Apr 14 08:43:37 PDT 2011 @@ -11,8 +12,6 @@ * New error system. * New flow control for messages means faster get/set calls. * Added new documentation 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. * 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. * Added MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS to simplify the setting of AUTO REJECT for servers. diff --git a/configure.ac b/configure.ac index 681778b5..3631b9cd 100644 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ # the COPYING file in this directory for full text. AC_PREREQ(2.59) -AC_INIT([libmemcached],[0.49],[http://libmemcached.org/]) +AC_INIT([libmemcached],[0.50],[http://libmemcached.org/]) AC_CONFIG_SRCDIR([libmemcached/memcached.cc]) AC_CONFIG_AUX_DIR(config) @@ -19,7 +19,7 @@ AC_CHECK_PROGS([LEX], ['flex'], [:]) #shared library versioning MEMCACHED_UTIL_LIBRARY_VERSION=2:0:0 MEMCACHED_PROTOCAL_LIBRARY_VERSION=0:0:0 -MEMCACHED_LIBRARY_VERSION=7:0:0 +MEMCACHED_LIBRARY_VERSION=8:0:0 # | | | # +------+ | +---+ # | | | diff --git a/docs/bin/memaslap.rst b/docs/bin/memaslap.rst new file mode 100644 index 00000000..b69bb3f8 --- /dev/null +++ b/docs/bin/memaslap.rst @@ -0,0 +1,1248 @@ +================================================== +memaslap - Load testing and benchmarking a server +================================================== + + +-------- +SYNOPSIS +-------- + +memaslap [options] + +.. program:: memaslap + +.. option:: --help + +----------- +DESCRIPTION +----------- + + +memaslap is a load generation and benchmark tool for :program:`memcached()` +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 testss 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 :option:`--servers` option or via the +environment variable :envvar:`MEMCACHED_SERVERS`. + + +-------- +FEATURES +-------- + + +Memslap is developed to for the following purposes: + + +Manages network connections with libevent asynchronously. + + + +Set both TCP and UDP up to use non-blocking IO. + + + +Improves parallelism: higher performance in multi-threads environments. + + + +Improves time efficiency: faster processing speed. + + + +Generates key and value more efficiently; key size distribution and value size distribution are configurable. + + + +Supports get, multi-get, and set commands; command distribution is configurable. + + + +Supports controllable miss rate and overwrite rate. + + + +Supports data and expire-time verification. + + + +Supports dumping statistic information periodically. + + + +Supports thousands of TCP connections. + + + +Supports binary protocol. + + + +Supports facebook test (set with TCP and multi-get with UDP) and replication test. + + + + +------- +DETAILS +------- + + +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. + + +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 testss 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. + + +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. + + +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. + + +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 testss multiple servers. The only +limitation is that the number of servers cannot be greater than the number +of threads. The other way to tests 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 testss 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 +testss 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. + + + +----- +USAGE +----- + + +Below are some usage samples: + + +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 + + + +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 + +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 testss set and get commands. And it +testss 100% set and 100% get. For 100% get, it will preset some objects to +the server. + + +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 testss 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. + + +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 testss 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 + + +Verification +____________ + + +Memslap testss both data verification and expire-time +verification. The user can use "--verify=" or "-v" to specify the proportion +of data verification. In theory, it testss 100% data verification. The +user can use "--exp_verify=" or "-e" to specify the proportion of +expire-time verification. In theory, it testss 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. + + +multi-servers and multi-config +_______________________________ + + +Memslap testss 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. + + +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.) + + +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. + + +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 testss data +verification and expire-time verification for multi-get. + +Memslap testss 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. + + +UDP and TCP +___________ + + +Memslap testss 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 testsed by the binary protocol because the binary protocol of +memcached does not tests that. + +UDP doesn’t tests reconnection. + + +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. + + +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. + + +Supports thousands of TCP connections +_____________________________________ + + +Start memaslap with "--conn_sock=" or "-n" to enable this +feature. Make sure that your system can tests opening thousands of files +and creating thousands of sockets. However, this feature does not tests +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. + + +Supports binary protocol +________________________ + + +Start memaslap with "--binary" or "-B" options to enable this +feature. It testss 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 tests UDP. In addition, memcached 1.3.3 does not tests +multi-get. If you specify "--division=50" option, it just sends 50 get +commands together as “mulit-get” to the server. + + + +------------------ +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: + + +.. code-block:: perl + + --------------------------------------------------------------------------- + #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 testss 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 + + + +---------------- +Format of output +---------------- + + +At the beginning, memaslap displays some configuration information as follows: + + +servers : 127.0.0.1:11211 + + + +threads count: 1 + + + +concurrency: 16 + + + +run time: 20s + + + +windows size: 10k + + + +set proportion: set_prop=0.10 + + + +get proportion: get_prop=0.90 + + + +Where +_____ + + + +servers : "servers" + + The servers used by memaslap. + + + +threads count + + The number of threads memaslap runs with. + + + +concurrency + + The number of concurrencies memaslap runs with. + + + +run time + + How long to run memaslap. + + + +windows size + + The task window size of each concurrency. + + + +set proportion + + The proportion of set command. + + + +get proportion + + The proportion of get command. + + + +The output of dynamic statistics is something like this: + + +.. code-block:: perl + + --------------------------------------------------------------------------------------------------------------------------------- + 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 + --------------------------------------------------------------------------------------------------------------------------------- + + + +Where +_____ + + + +Get Statistics + + Statistics information of get command + + + +Set Statistics + + Statistics information of set command + + + +Total Statistics + + Statistics information of both get and set command + + + +Period + + Result within a period + + + +Global + + Accumulated results + + + +Ops + + Total operations + + + +TPS + + Throughput, operations/second + + + +Net + + The rate of network + + + +Get_miss + + How many objects can’t be gotten + + + +Min + + The minimum response time + + + +Max + + The maximum response time + + + +Avg: + + The average response time + + + +Std_dev + + Standard deviation of response time + + + +Geo_dist + + Geometric distribution based on natural exponential function + + + +At the end, memaslap will output something like this: + + +.. code-block:: perl + + --------------------------------------------------------------------------------------------------------------------------------- + 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 + --------------------------------------------------------------------------------------------------------------------------------- + + + +Where +_____ + + + +Get Statistics + + Get statistics of response time + + + +Set Statistics + + Set statistics of response time + + + +Total Statistics + + Both get and set statistics of response time + + + +Min + + The accumulated and minimum response time + + + +Max + + The accumulated and maximum response time + + + +Avg + + The accumulated and average response time + + + +Std + + Standard deviation of response time + + + +Log2 Dist + + Geometric distribution based on logarithm 2 + + + +cmd_get + + Total get commands done + + + +cmd_set + + Total set commands done + + + +get_misses + + How many objects can’t be gotten from server + + + +verify_misses + + How many objects need to verify but can’t get them + + + +verify_failed + + How many objects with insistent value + + + +expired_get + + How many objects are expired but we get them + + + +unexpired_unget + + How many objects are unexpired but we can’t get them + + + +written_bytes + + Total written bytes + + + +read_bytes + + Total read bytes + + + +object_bytes + + Total object bytes + + + +packet_disorder + + How many UDP packages are disorder + + + +packet_drop + + How many UDP packages are lost + + + +udp_timeout + + How many times UDP time out happen + + + +Run time + + Total run time + + + +Ops + + Total operations + + + +TPS + + Throughput, operations/second + + + +Net_rate + + The average rate of network + + + + + +------- +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 tests, when connection is closed it will be reconnected. + +-U, --udp + UDP tests, 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. + + +-------- +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 + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------- +AUTHORS +------- + + +Mingqiang Zhuang (Schooner Technolgy) +Brian Aker, + + +-------- +SEE ALSO +-------- + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/bin/memcapable.rst b/docs/bin/memcapable.rst new file mode 100644 index 00000000..0e4f33e3 --- /dev/null +++ b/docs/bin/memcapable.rst @@ -0,0 +1,78 @@ +======================================================================= +memcapable - Checking a Memcached server capibilities and compatibility +======================================================================= + +-------- +SYNOPSIS +-------- + +memcapable [options] + +.. program:: memcapable + +----------- +DESCRIPTION +----------- + +:program:`memcapable` connects to the specified memcached server and tries to +determine its capabilities by running the various commands and verifying +the response. + + +----------- +LIMITATIONS +----------- + + +The current version of memcapable will only verify the binary protocol. + + +------- +OPTIONS +------- + + +.. option:: -h hostname + +Specify the hostname to connect to. The default is \ *localhost*\ + +.. option:: -p port + +Specify the port number to connect to. The default is \ *11211*\ + +.. option:: -c + +Generate a coredump when it detects an error from the server. + +.. option:: -v + +Print out the comparison when it detects an error from the server. + +.. option:: -t n + +Set the timeout from an IO operation to/from the server to \ *n*\ seconds. + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Trond Norbye, + + +-------- +SEE ALSO +-------- + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` + diff --git a/docs/bin/memcat.rst b/docs/bin/memcat.rst new file mode 100644 index 00000000..b8612a92 --- /dev/null +++ b/docs/bin/memcat.rst @@ -0,0 +1,73 @@ +================================= +memcat - "cat" data from a server +================================= + + + +-------- +SYNOPSIS +-------- + +memcat [options] key + +Copy a set of keys to stdout + + +.. program:: memcat + + +----------- +DESCRIPTION +----------- + + +:program:`memcat` outputs to stdout the value a single or multiple set of keys +stored in a memcached(1) server. If any key is not found an error is returned. + +It is similar to the standard UNIX cat(1) utility. + + +------- +OPTIONS +------- + + +You can specify servers via the option: + +.. cmdoption:: --servers + +or via the environment variable: + +.. envvar:: `MEMCACHED_SERVERS` + +For a full list of operations run the tool with the option: + +.. cmdoption:: --help + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Brian Aker, + +Mark Atwood + + +-------- +SEE ALSO +-------- + + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` + diff --git a/docs/bin/memcp.rst b/docs/bin/memcp.rst new file mode 100644 index 00000000..a85eed8b --- /dev/null +++ b/docs/bin/memcp.rst @@ -0,0 +1,75 @@ +============================= +memcp - Copy data to a server +============================= + + +Copies files to a collection of memcached servers + + +-------- +SYNOPSIS +-------- + +memcp [options] [file] [server] + +.. program:: memcp + + +----------- +DESCRIPTION +----------- + + +:program:`memcp` copies one or more files into memcached(1) servers. +It is similar to the standard UNIX cp(1) command. + +The key names will be the names of the files, +without any directory path. + + +------- +OPTIONS +------- + + +You can specify servers via the option: + +.. option:: --servers + +or via the environment variable: + +.. envvar:: `MEMCACHED_SERVERS` + +If you do not specify either these, the final value in the command line list is the name of a server(s). + +For a full list of operations run the tool with the option: + +.. option:: --help + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Brian Aker, + +Mark Atwood, + + +-------- +SEE ALSO +-------- + + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` + diff --git a/docs/bin/memdump.rst b/docs/bin/memdump.rst new file mode 100644 index 00000000..6a8e12da --- /dev/null +++ b/docs/bin/memdump.rst @@ -0,0 +1,58 @@ +============================= +memdump - Dumping your server +============================= + + +Dump a list of keys from a server. + + +-------- +SYNOPSIS +-------- + +memdump [options] + +.. program:: memdump + +----------- +DESCRIPTION +----------- + + +:program:`memdump` dumps a list of "keys" from all servers that +it is told to fetch from. Because memcached does not guarentee to +provide all keys it is not possible to get a complete "dump". + + +------- +OPTIONS +------- + + +For a full list of operations run the tool with option: + +.. option:: --help + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Brian Aker, + + +-------- +SEE ALSO +-------- + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/bin/memerror.rst b/docs/bin/memerror.rst new file mode 100644 index 00000000..53fc09c4 --- /dev/null +++ b/docs/bin/memerror.rst @@ -0,0 +1,58 @@ +============================================== +memerror - translate an error code to a string +============================================== + + +Translates a memcached error code into a string + + +-------- +SYNOPSIS +-------- + +memerror [options] [error code] + +.. program:: memerror + +----------- +DESCRIPTION +----------- + + +:program:`memerror` translates an error code from libmemcached(3) into a human +readable string. + + +------- +OPTIONS +------- + + +For a full list of operations run the tool with option: + +.. option:: --help + + +---- +HOME +---- + + +To find out more infoerroration please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Brian Aker, + + +-------- +SEE ALSO +-------- + + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/bin/memflush.rst b/docs/bin/memflush.rst new file mode 100644 index 00000000..a2b9894d --- /dev/null +++ b/docs/bin/memflush.rst @@ -0,0 +1,67 @@ +======================================= +memflush - flush all data from a server +======================================= + + +Reset a server or list of servers + + +-------- +SYNOPSIS +-------- + +memflush [options] + +.. program:: memflush + +----------- +DESCRIPTION +----------- + + +:program:`memflush` resets the contents of memcached(1) servers. +This means that all data in the specified servers will be deleted. + + +------- +OPTIONS +------- + + +You can specify servers via the option: + +.. option:: --servers + +or via the environment variable: + +.. envvar:: `MEMCACHED_SERVERS` + +For a full list of operations run the tool with option: + +.. option:: --help + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Brian Aker, + +Mark Atwood + + +-------- +SEE ALSO +-------- + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/bin/memrm.rst b/docs/bin/memrm.rst new file mode 100644 index 00000000..d395b364 --- /dev/null +++ b/docs/bin/memrm.rst @@ -0,0 +1,71 @@ +================================= +memrm - Remove data from a server +================================= + + +memrm - Remove a key(s) from a collection of memcached servers + + +-------- +SYNOPSIS +-------- + +memrm [options] [key] + +.. program:: memrm + + +----------- +DESCRIPTION +----------- + + +:program:`memrm` removes items, specified by key, from memcached(1) servers. + + +------- +OPTIONS +------- + + +You can specify servers via the option: + +.. option:: --servers + +or via the environment variable: + +.. envvar:: `MEMCACHED_SERVERS` + +For a full list of operations run the tool with the + +.. option:: --help + + + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +------ +AUTHOR +------ + + +Brian Aker, + +Mark Atwood, + + +-------- +SEE ALSO +-------- + + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` + diff --git a/docs/bin/memslap.rst b/docs/bin/memslap.rst new file mode 100644 index 00000000..fbaa5fe3 --- /dev/null +++ b/docs/bin/memslap.rst @@ -0,0 +1,63 @@ +================================================= +memslap - Load testing and benchmarking a server +================================================= + + +-------- +SYNOPSIS +-------- + +memslap [options] + +.. program:: memslap + +----------- +DESCRIPTION +----------- + + +:program:`memslap` 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. + + +------- +OPTIONS +------- + + +You can specify servers via the option: + +.. option:: --servers + +or via the environment variable: + +.. envvar:: `MEMCACHED_SERVERS` + +For a full list of operations run the tool with: + +.. option:: --help + + +---- +HOME +---- + + +To find out more information please check: +'http://libmemcached.org/ '_ + + +------ +AUTHOR +------ + + +Brian Aker, + + +-------- +SEE ALSO +-------- + + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/bin/memstat.rst b/docs/bin/memstat.rst new file mode 100644 index 00000000..3bbec8f8 --- /dev/null +++ b/docs/bin/memstat.rst @@ -0,0 +1,61 @@ +========================================= +memstat - Gather statistics from a server +========================================= + + +memstat - Display the operating status of a single or group of memcached servers + + +-------- +SYNOPSIS +-------- + +memstat [options] + +.. program:: memstat + +----------- +DESCRIPTION +----------- + + +:program:`memstat` dumps the state of memcached(1) servers. +It displays all data to stdout. + + +------- +OPTIONS +------- + + +You can specify servers via the option: + +.. option:: --servers + +or via the environment variable: + +.. envvar:: 'MEMCACHED_SERVERS, --args' + +which can be used to specify the "argument" sent to the stats command (ie slab, size, items, etc..). + +For a full list of operations run the tool with: + +.. option:: --help + + +---- +HOME +---- + + +To find out more information please check: +`http://libmemcached.org/ `_ + + +-------- +SEE ALSO +-------- + + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` + diff --git a/docs/hashkit_create.rst b/docs/hashkit_create.rst index f7aabac5..8935b2d0 100644 --- a/docs/hashkit_create.rst +++ b/docs/hashkit_create.rst @@ -10,6 +10,8 @@ SYNOPSIS #include +.. c:type:: hashkit_st + .. c:function:: hashkit_st *hashkit_create(hashkit_st *hash); .. c:function:: hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *ptr); @@ -20,25 +22,24 @@ SYNOPSIS Compile and link with -lhashkit - ----------- DESCRIPTION ----------- -The hashkit_create() function initializes a hashkit object for use. If +The :c:func:`hashkit_create()` function initializes a hashkit object for use. If you pass a NULL argument for hash, then the memory for the object is allocated. If you specify a pre-allocated piece of memory, that is initialized for use. -The hashkit_clone() function initializes a hashkit object much like -hashkit_create(), but instead of using default settings it will use +The :c:func:`hashkit_clone()` function initializes a hashkit object much like +:c:func:`hashkit_create()`, but instead of using default settings it will use the settings of the ptr hashkit object. -The hashkit_free() frees any resources being consumed by the hashkit -objects that were initialized with hashkit_create() or hashkit_clone(). +The :c:func:`hashkit_free()` frees any resources being consumed by the hashkit +objects that were initialized with :c:func:`hashkit_create()` or :c:func:`hashkit_clone()`. -The hashkit_is_allocated() reports where the memory was allocated +The :c:func:`hashkit_is_allocated()` reports where the memory was allocated for a hashkit object. @@ -47,11 +48,11 @@ RETURN VALUE ------------ -hashkit_create() and hashkit_clone() will return NULL on failure or +:c:func:`hashkit_create()` and :c:func:`hashkit_clone()` will return NULL on failure or non-NULL on success. -hashkit_is_allocated() returns true if the memory for the hashkit -object was allocated inside of hashkit_create() or hashkit_clone(), +:c:func:`hashkit_is_allocated()` returns true if the memory for the hashkit +object was allocated inside of :c:func:`hashkit_create()` or :c:func:`hashkit_clone()`, otherwise it is false and was user-supplied memory. diff --git a/docs/index.rst b/docs/index.rst index cef0830d..57e2671d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -53,6 +53,7 @@ Advanced Topics memcached_generate_hash_value memcached_memory_allocators memcached_quit + libmemcached/memcached_return_t memcached_sasl memcached_server_st memcached_servers @@ -61,6 +62,16 @@ Advanced Topics memcached_verbosity memcached_version + +#################### +Deprecated Functions +#################### + +.. toctree:: + :titlesonly: + + libmemcached/memcached_fetch + ################# Platform Specific ################# @@ -97,16 +108,16 @@ Client Applications .. toctree:: :maxdepth: 1 - memcapable - memcat - memcp - memdump - memerror - memflush - memrm - memslap - memaslap - memstat + bin/memcapable + bin/memcat + bin/memcp + bin/memdump + bin/memerror + bin/memflush + bin/memrm + bin/memslap + bin/memaslap + bin/memstat ---------- Libhashkit diff --git a/docs/libhashkit.rst b/docs/libhashkit.rst index 5f31f69b..d13b8757 100644 --- a/docs/libhashkit.rst +++ b/docs/libhashkit.rst @@ -15,8 +15,7 @@ Introducing libhashkit DESCRIPTION ----------- - -\ **libhashkit**\ is a small and thread-safe client library that provides a collection of useful hashing algorithm. libhashkit is distributed with libmemcached. +:program:'libhashkit' is a small and thread-safe client library that provides a collection of useful hashing algorithm. libhashkit is distributed with libmemcached. ---- diff --git a/docs/libmemcached.rst b/docs/libmemcached.rst index 23ec93b4..78af3e32 100644 --- a/docs/libmemcached.rst +++ b/docs/libmemcached.rst @@ -10,6 +10,8 @@ SYNOPSIS Compile and link with -lmemcached +======= + libMemcached is an open source C/C++ client library and tools for the memcached server (http://danga.com/memcached). It has been designed to be light on memory usage, thread safe, and provide full access to server side methods. libMemcached was designed to provide the greatest number of options to use Memcached. Some of the features provided: @@ -41,13 +43,13 @@ a modular and consistent method of object distribution. There are multiple implemented routing and hashing methods. See the memcached_behavior_set() manpage for more information. -All operations are performed against a \ ``memcached_st``\ structure. +All operations are performed against a :c:type:`memcached_st` structure. These structures can either be dynamically allocated or statically allocated and then initialized by memcached_create(). Functions have been -written in order to encapsulate the \ ``memcached_st``\ . It is not +written in order to encapsulate the :c:type:`memcached_st` . It is not recommended that you operate directly against the structure. -Nearly all functions return a \ ``memcached_return_t``\ value. +Nearly all functions return a :c:type:`memcached_return_t`\ value. This value can be translated to a printable string with memcached_strerror(3). Objects are stored on servers by hashing keys. The hash value maps the key to a particular server. All clients understand how this hashing works, so it is possibly to reliably both push data to a server and retrieve data from a server. @@ -56,7 +58,7 @@ Group keys can be optionally used to group sets of objects with servers. Namespaces are supported, and can be used to partition caches so that multiple applications can use the same memcached servers. -\ ``memcached_st``\ structures are thread-safe, but each thread must +:c:type:`memcached_st` structures are thread-safe, but each thread must contain its own structure (that is, if you want to share these among threads you must provide your own locking). No global variables are used in this library. @@ -129,9 +131,9 @@ THREADS AND PROCESSES When using threads or forked processes it is important to keep one instance -of \ ``memcached_st``\ per process or thread. Without creating your own locking -structures you can not share a single \ ``memcached_st``\ . However, you can call -memcached_quit(3) on a \ ``memcached_st``\ and then use the resulting cloned +of :c:type:`memcached_st` per process or thread. Without creating your own locking +structures you can not share a single :c:type:`memcached_st`. However, you can call +memcached_quit(3) on a :c:type:`memcached_st` and then use the resulting cloned structure. diff --git a/docs/libmemcached/memcached_fetch.rst b/docs/libmemcached/memcached_fetch.rst new file mode 100644 index 00000000..9d995101 --- /dev/null +++ b/docs/libmemcached/memcached_fetch.rst @@ -0,0 +1,66 @@ +================= +memcached_fetch() +================= + +.. index:: object: memcached_st + +-------- +SYNOPSIS +-------- + + +#include + +.. c:function:: char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error) + + .. deprecated:: 0.50 + Use :c:func:`memcached_fetch_result()` instead. + +Compile and link with -lmemcached + + +----------- +DESCRIPTION +----------- + +:c:func:`memcached_fetch()` is used to fetch an individual value from the server. :c:func:`memcached_mget()` must always be called before using this method. +You must pass in a key and its length to fetch the object. You must supply +three pointer variables which will give you the state of the returned +object. A :c:type:`uint32_t` pointer to contain whatever flags you stored with the value, a :c:type:`size_t` pointer which will be filled with size of of the +object, and a :c:type:`memcached_return_t` pointer to hold any error. The +object will be returned upon success and NULL will be returned on failure. :c:type:`MEMCACHD_END` is returned by the \*error value when all objects that have been found are returned. The final value upon :c:type:`MEMCACHED_END` is null. + +Values returned by :c:func:`memcached_fetch()` must be freed by the caller. + +All of the above functions are not tested when the +:c:type:`MEMCACHED_BEHAVIOR_USE_UDP` has been set. Executing any of these +functions with this behavior on will result in :c:type:`MEMCACHED_NOT_SUPPORTED` being returned, or for those functions which do not return a :c:type:`memcached_return_t`, the error function parameter will be set to :c:type:`MEMCACHED_NOT_SUPPORTED`. + + +------ +RETURN +------ + +:c:func:`memcached_fetch()` sets error to +to :c:type:`MEMCACHED_END` upon successful conclusion. +:c:type:`MEMCACHED_NOTFOUND` will be return if no keys at all were found. + +:c:type:`MEMCACHED_KEY_TOO_BIG` is set to error whenever :c::func:`memcached_fetch()` was used +and the key was set larger then :c:type:`MEMCACHED_MAX_KEY`, which was the largest +key allowed for the original memcached ascii server. + + +---- +HOME +---- + +To find out more information please check: +`http://libmemcached.org/ `_ + + +-------- +SEE ALSO +-------- + +:manpage:`memcached(1)` :manpage:`libmemcached(3)` :manpage:`memcached_strerror(3)` :manpage:`memcached_fetch_result(3)` + diff --git a/docs/libmemcached/memcached_return_t.rst b/docs/libmemcached/memcached_return_t.rst new file mode 100644 index 00000000..40f6f96f --- /dev/null +++ b/docs/libmemcached/memcached_return_t.rst @@ -0,0 +1,138 @@ +================================ +Error Codes (memcached_return_t) +================================ + +-------- +SYNOPSIS +-------- + +#include + +.. c:type:: memcached_return_t + +.. c:function:: const char *libmemcached_strerror(libmemcached_return_t rc) + +.. c:function:: bool libmemcached_success(libmemcached_return_t rc) + +.. c:function:: bool libmemcached_failure(libmemcached_return_t rc) + +.. c:function:: bool libmemcache_continue(libmemcached_return_t rc) + + + +:c:func:`memcached_success()` return true if :c:type:`MEMCACHED_SUCCESS` tested true. + +:c:func:`memcached_failure()` return true if any value other then :c:type:`MEMCACHED_SUCCESS` was provided. + + +Libmemcached return types: +++++++++++++++++++++++++++ + + +.. c:type:: MEMCACHED_SUCCESS + +Success + +.. c:type:: MEMCACHED_FAILURE + +.. c:type:: MEMCACHED_HOST_LOOKUP_FAILURE + +.. c:type:: MEMCACHED_CONNECTION_FAILURE + +.. c:type:: MEMCACHED_CONNECTION_BIND_FAILURE +.. deprecated:: <0.30 + +.. c:type:: MEMCACHED_WRITE_FAILURE + +.. c:type:: MEMCACHED_READ_FAILURE + +.. c:type:: MEMCACHED_UNKNOWN_READ_FAILURE + +.. c:type:: MEMCACHED_PROTOCOL_ERROR + +.. c:type:: MEMCACHED_CLIENT_ERROR + +.. c:type:: MEMCACHED_SERVER_ERROR + +.. c:type:: MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE +.. deprecated:: <0.30 + +.. c:type:: MEMCACHED_DATA_EXISTS + +.. c:type:: MEMCACHED_DATA_DOES_NOT_EXIST + +.. c:type:: MEMCACHED_NOTSTORED + +.. c:type:: MEMCACHED_STORED + +.. c:type:: MEMCACHED_NOTFOUND + +.. c:type:: MEMCACHED_MEMORY_ALLOCATION_FAILURE + +.. c:type:: MEMCACHED_PARTIAL_READ + +.. c:type:: MEMCACHED_SOME_ERRORS + +.. c:type:: MEMCACHED_NO_SERVERS + +.. c:type:: MEMCACHED_END + +.. c:type:: MEMCACHED_DELETED + +.. c:type:: MEMCACHED_VALUE + +.. c:type:: MEMCACHED_STAT + +.. c:type:: MEMCACHED_ITEM + +.. c:type:: MEMCACHED_ERRNO + +.. c:type:: MEMCACHED_FAIL_UNIX_SOCKET +.. deprecated:: <0.30 + +.. c:type:: MEMCACHED_NOT_SUPPORTED + +.. c:type:: MEMCACHED_NO_KEY_PROVIDED +.. deprecated:: <0.30 + Use :c:type:`MEMCACHED_BAD_KEY_PROVIDED` instead. + +.. c:type:: MEMCACHED_FETCH_NOTFINISHED + +.. c:type:: MEMCACHED_TIMEOUT + + Connection to server timed out. + +.. c:type:: MEMCACHED_BUFFERED + +.. c:type:: MEMCACHED_BAD_KEY_PROVIDED + +.. c:type:: MEMCACHED_INVALID_HOST_PROTOCOL + +.. c:type:: MEMCACHED_SERVER_MARKED_DEAD + +.. c:type:: MEMCACHED_UNKNOWN_STAT_KEY + +.. c:type:: MEMCACHED_E2BIG + +.. c:type:: MEMCACHED_INVALID_ARGUMENTS + +.. c:type:: MEMCACHED_KEY_TOO_BIG + +.. c:type:: MEMCACHED_AUTH_PROBLEM + +.. c:type:: MEMCACHED_AUTH_FAILURE + +.. c:type:: MEMCACHED_AUTH_CONTINUE + +.. c:type:: MEMCACHED_PARSE_ERROR + +.. c:type:: MEMCACHED_PARSE_USER_ERROR + +.. c:type:: MEMCACHED_DEPRECATED + +-------- +SEE ALSO +-------- + +:manpage:`memcached(8)` :manpage:`libmemcached(3)` :manpage:`memcached_client_error()` or :manpage:`memcached_worker_error()` + diff --git a/docs/libmemcached_configuration.rst b/docs/libmemcached_configuration.rst index 74902aab..4cfec4a8 100644 --- a/docs/libmemcached_configuration.rst +++ b/docs/libmemcached_configuration.rst @@ -2,7 +2,7 @@ Configuring Libmemcached ======================== -.. index:: object: memcached_st +.. highlightlang:: c -------- SYNOPSIS @@ -17,13 +17,12 @@ SYNOPSIS Compile and link with -lmemcached - ----------- DESCRIPTION ----------- Libmemcached implements a custom language for configuring and modifying -servers. By passing in an option string you can generate a memcached_st object +servers. By passing in an option string you can generate a ``memcached_st`` object that you can use in your application directly. .. describe:: --SERVER=:/? diff --git a/docs/memaslap.rst b/docs/memaslap.rst deleted file mode 100644 index 02e2ab26..00000000 --- a/docs/memaslap.rst +++ /dev/null @@ -1,1250 +0,0 @@ -================================================== -memaslap - Load testing and benchmarking a server -================================================== - - --------- -SYNOPSIS --------- - -:program:: `memaslap` - -.. program:: memaslap - -.. option:: --help - ------------ -DESCRIPTION ------------ - - -\ **memaslap**\ 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 testss 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 \ **--servers**\ option or via the -environment variable \ ``MEMCACHED_SERVERS``\ . - - --------- -FEATURES --------- - - -Memslap is developed to for the following purposes: - - -Manages network connections with libevent asynchronously. - - - -Set both TCP and UDP up to use non-blocking IO. - - - -Improves parallelism: higher performance in multi-threads environments. - - - -Improves time efficiency: faster processing speed. - - - -Generates key and value more efficiently; key size distribution and value size distribution are configurable. - - - -Supports get, multi-get, and set commands; command distribution is configurable. - - - -Supports controllable miss rate and overwrite rate. - - - -Supports data and expire-time verification. - - - -Supports dumping statistic information periodically. - - - -Supports thousands of TCP connections. - - - -Supports binary protocol. - - - -Supports facebook test (set with TCP and multi-get with UDP) and replication test. - - - - -------- -DETAILS -------- - - -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. - - -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 testss 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. - - -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. - - -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. - - -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 testss multiple servers. The only -limitation is that the number of servers cannot be greater than the number -of threads. The other way to tests 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 testss 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 -testss 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. - - - ------ -USAGE ------ - - -Below are some usage samples: - - -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 - - - -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 - -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 testss set and get commands. And it -testss 100% set and 100% get. For 100% get, it will preset some objects to -the server. - - -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 testss 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. - - -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 testss 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 - - -Verification -____________ - - -Memslap testss both data verification and expire-time -verification. The user can use "--verify=" or "-v" to specify the proportion -of data verification. In theory, it testss 100% data verification. The -user can use "--exp_verify=" or "-e" to specify the proportion of -expire-time verification. In theory, it testss 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. - - -multi-servers and multi-config -_______________________________ - - -Memslap testss 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. - - -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.) - - -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. - - -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 testss data -verification and expire-time verification for multi-get. - -Memslap testss 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. - - -UDP and TCP -___________ - - -Memslap testss 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 testsed by the binary protocol because the binary protocol of -memcached does not tests that. - -UDP doesn’t tests reconnection. - - -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. - - -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. - - -Supports thousands of TCP connections -_____________________________________ - - -Start memaslap with "--conn_sock=" or "-n" to enable this -feature. Make sure that your system can tests opening thousands of files -and creating thousands of sockets. However, this feature does not tests -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. - - -Supports binary protocol -________________________ - - -Start memaslap with "--binary" or "-B" options to enable this -feature. It testss 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 tests UDP. In addition, memcached 1.3.3 does not tests -multi-get. If you specify "--division=50" option, it just sends 50 get -commands together as “mulit-get” to the server. - - - ------------------- -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: - - -.. code-block:: perl - - --------------------------------------------------------------------------- - #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 testss 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 - - - ----------------- -Format of output ----------------- - - -At the beginning, memaslap displays some configuration information as follows: - - -servers : 127.0.0.1:11211 - - - -threads count: 1 - - - -concurrency: 16 - - - -run time: 20s - - - -windows size: 10k - - - -set proportion: set_prop=0.10 - - - -get proportion: get_prop=0.90 - - - -Where -_____ - - - -servers : "servers" - - The servers used by memaslap. - - - -threads count - - The number of threads memaslap runs with. - - - -concurrency - - The number of concurrencies memaslap runs with. - - - -run time - - How long to run memaslap. - - - -windows size - - The task window size of each concurrency. - - - -set proportion - - The proportion of set command. - - - -get proportion - - The proportion of get command. - - - -The output of dynamic statistics is something like this: - - -.. code-block:: perl - - --------------------------------------------------------------------------------------------------------------------------------- - 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 - --------------------------------------------------------------------------------------------------------------------------------- - - - -Where -_____ - - - -Get Statistics - - Statistics information of get command - - - -Set Statistics - - Statistics information of set command - - - -Total Statistics - - Statistics information of both get and set command - - - -Period - - Result within a period - - - -Global - - Accumulated results - - - -Ops - - Total operations - - - -TPS - - Throughput, operations/second - - - -Net - - The rate of network - - - -Get_miss - - How many objects can’t be gotten - - - -Min - - The minimum response time - - - -Max - - The maximum response time - - - -Avg: - - The average response time - - - -Std_dev - - Standard deviation of response time - - - -Geo_dist - - Geometric distribution based on natural exponential function - - - -At the end, memaslap will output something like this: - - -.. code-block:: perl - - --------------------------------------------------------------------------------------------------------------------------------- - 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 - --------------------------------------------------------------------------------------------------------------------------------- - - - -Where -_____ - - - -Get Statistics - - Get statistics of response time - - - -Set Statistics - - Set statistics of response time - - - -Total Statistics - - Both get and set statistics of response time - - - -Min - - The accumulated and minimum response time - - - -Max - - The accumulated and maximum response time - - - -Avg - - The accumulated and average response time - - - -Std - - Standard deviation of response time - - - -Log2 Dist - - Geometric distribution based on logarithm 2 - - - -cmd_get - - Total get commands done - - - -cmd_set - - Total set commands done - - - -get_misses - - How many objects can’t be gotten from server - - - -verify_misses - - How many objects need to verify but can’t get them - - - -verify_failed - - How many objects with insistent value - - - -expired_get - - How many objects are expired but we get them - - - -unexpired_unget - - How many objects are unexpired but we can’t get them - - - -written_bytes - - Total written bytes - - - -read_bytes - - Total read bytes - - - -object_bytes - - Total object bytes - - - -packet_disorder - - How many UDP packages are disorder - - - -packet_drop - - How many UDP packages are lost - - - -udp_timeout - - How many times UDP time out happen - - - -Run time - - Total run time - - - -Ops - - Total operations - - - -TPS - - Throughput, operations/second - - - -Net_rate - - The average rate of network - - - - - -------- -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 tests, when connection is closed it will be reconnected. - --U, --udp - UDP tests, 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. - - --------- -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 - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - -------- -AUTHORS -------- - - -Mingqiang Zhuang (Schooner Technolgy) -Brian Aker, - - --------- -SEE ALSO --------- - -:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/memcached_behavior.rst b/docs/memcached_behavior.rst index 0a8314d9..59ec4839 100644 --- a/docs/memcached_behavior.rst +++ b/docs/memcached_behavior.rst @@ -26,55 +26,50 @@ Compile and link with -lmemcached DESCRIPTION ----------- -:manpage:`libmemcached(3)` behavior can be modified by use memcached_behavior_set(). -Default behavior is the library strives to be quick and accurate. Some -behavior, while being faster, can also result in not entirely accurate -behavior (for instance, memcached_set() will always respond with -\ ``MEMCACHED_SUCCESS``\ ). +:manpage:`libmemcached(3)` behavior can be modified by using :c:func:`memcached_behavior_set()`. Default behavior is the library strives to be quick and +accurate. Some behavior, while being faster, can also result in not entirely +accurate behavior (for instance, :c:func:`memcached_set()` will always respond +with :c:type:`MEMCACHED_SUCCESS`). -memcached_behavior_get() takes a behavior flag and returns whether or not -that behavior is currently enabled in the client. +:c:func:`memcached_behavior_get()` takes a behavior flag and returns whether or not that behavior is currently enabled in the client. -memcached_behavior_set() changes the value of a particular option of the -client. It takes both a flag (listed below) and a value. For simple on or -off options you just need to pass in a value of 1. Calls to -memcached_behavior_set() will flush and reset all connections. +:c:func:`memcached_behavior_set()` changes the value of a particular option +of the client. It takes both a flag (listed below) and a value. For simple +on or off options you just need to pass in a value of 1. Calls to +:c:func:`memcached_behavior_set()` will flush and reset all connections. -.. c:var:: MEMCACHED_BEHAVIOR_USE_UDP +.. c:type:: MEMCACHED_BEHAVIOR_USE_UDP Causes :manpage:`libmemcached(3)` to use the UDP transport when communicating with a memcached server. Not all I/O operations are testsed when this behavior is enababled. The following operations will return -\ ``MEMCACHED_NOT_SUPPORTED``\ when executed with the MEMCACHED_BEHAVIOR_USE_UDP -enabled: memcached_version(), memcached_stat(), memcached_get(), -memcached_get_by_key(), memcached_mget(), memcached_mget_by_key(), -memcached_fetch(), memcached_fetch_result(), memcached_value_fetch(). +:c:type:`MEMCACHED_NOT_SUPPORTED` when executed with the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` enabled: :c:func:`memcached_version()`, :c:func:`memcached_stat()`, :c:func:`memcached_get()`, :c:func:`memcached_get_by_key()`, :c:func:`memcached_mget()`, :c:func:`memcached_mget_by_key()`, :c:func:`memcached_fetch()`, :c:func:`memcached_fetch_result()`, :c:func:`memcached_value_fetch()`. All other operations are testsed but are executed in a 'fire-and-forget' mode, in which once the client has executed the operation, no attempt will be made to ensure the operation has been received and acted on by the server. -:manpage:`libmemcached(3)` does not allow TCP and UDP servers to be shared within -the same libmemached(3) client 'instance'. An attempt to add a TCP server -when this behavior is enabled will result in a \ ``MEMCACHED_INVALID_HOST_PROTOCOL``\ , -as will attempting to add a UDP server when this behavior has not been enabled. +:manpage:`libmemcached(3)` does not allow TCP and UDP servers to be shared +within the same libmemached(3) client 'instance'. An attempt to add a TCP +server when this behavior is enabled will result in a :c:type:`MEMCACHED_INVALID_HOST_PROTOCOL`, as will attempting to add a UDP server when this behavior has +not been enabled. -.. c:var:: MEMCACHED_BEHAVIOR_NO_BLOCK +.. c:type:: MEMCACHED_BEHAVIOR_NO_BLOCK -Causes :manpage:`libmemcached(3)` to use asychronous IO. This is the fastest transport -available for storage functions. +Causes :manpage:`libmemcached(3)` to use asychronous IO. This is the fastest +transport available for storage functions. -.. c:var:: MEMCACHED_BEHAVIOR_SND_TIMEOUT +.. c:type:: MEMCACHED_BEHAVIOR_SND_TIMEOUT This sets the microsecond behavior of the socket against the SO_SNDTIMEO flag. In cases where you cannot use non-blocking IO this will allow you to still have timeouts on the sending of data. -.. c:var:: MEMCACHED_BEHAVIOR_RCV_TIMEOUT +.. c:type:: MEMCACHED_BEHAVIOR_RCV_TIMEOUT This sets the microsecond behavior of the socket against the SO_RCVTIMEO flag. @@ -82,179 +77,185 @@ In cases where you cannot use non-blocking IO this will allow you to still have -.. c:var:: MEMCACHED_BEHAVIOR_TCP_NODELAY +.. c:type:: MEMCACHED_BEHAVIOR_TCP_NODELAY Turns on the no-delay feature for connecting sockets (may be faster in some environments). -.. c:var:: MEMCACHED_BEHAVIOR_HASH +.. c:type:: MEMCACHED_BEHAVIOR_HASH -Makes the default hashing algorithm for keys use MD5. The value can be set to either MEMCACHED_HASH_DEFAULT, MEMCACHED_HASH_MD5, MEMCACHED_HASH_CRC, MEMCACHED_HASH_FNV1_64, MEMCACHED_HASH_FNV1A_64, MEMCACHED_HASH_FNV1_32, MEMCACHED_HASH_FNV1A_32, MEMCACHED_HASH_JENKINS, MEMCACHED_HASH_HSIEH, and MEMCACHED_HASH_MURMUR. +Makes the default hashing algorithm for keys use MD5. The value can be set to either :c:type:`MEMCACHED_HASH_DEFAULT`, :c:type:`MEMCACHED_HASH_MD5`, :c:type:`MEMCACHED_HASH_CRC`, :c:type:`MEMCACHED_HASH_FNV1_64`, :c:type:`MEMCACHED_HASH_FNV1A_64`, :c:type:`MEMCACHED_HASH_FNV1_32`, :c:type:`MEMCACHED_HASH_FNV1A_32`, :c:type:`MEMCACHED_HASH_JENKINS`, :c:type:`MEMCACHED_HASH_HSIEH`, and :c:type:`MEMCACHED_HASH_MURMUR`. -Each hash has it's advantages and it's weaknesses. If you don't know or don't care, just go with the default. +Each hash has it's advantages and it's weaknesses. If you don't know or don't +care, just go with the default. -Support for MEMCACHED_HASH_HSIEH is a compile time option that is disabled by default. To enable tests for this hashing algorithm, configure and build libmemcached with the --enable-hash_hsieh. +Support for :c:type:`MEMCACHED_HASH_HSIEH` is a compile time option that is disabled by default. To enable tests for this hashing algorithm, configure and build libmemcached with the --enable-hash_hsieh. -.. c:var:: MEMCACHED_BEHAVIOR_DISTRIBUTION +.. c:type:: MEMCACHED_BEHAVIOR_DISTRIBUTION Using this you can enable different means of distributing values to servers. The default method is MEMCACHED_DISTRIBUTION_MODULA. You can enable consistent hashing by setting MEMCACHED_DISTRIBUTION_CONSISTENT. Consistent hashing delivers better distribution and allows servers to be added to the cluster with minimal cache losses. Currently MEMCACHED_DISTRIBUTION_CONSISTENT is an alias for the value MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA. -.. c:var:: MEMCACHED_BEHAVIOR_CACHE_LOOKUPS +.. c:type:: MEMCACHED_BEHAVIOR_CACHE_LOOKUPS +.. deprecated:: 0.46(?) + DNS lookups are now always cached until an error occurs with the server. -DEPRECATED. Memcached can cache named lookups so that DNS lookups are made only once. + Memcached can cache named lookups so that DNS lookups are made only once. -.. c:var:: MEMCACHED_BEHAVIOR_SUPPORT_CAS +.. c:type:: MEMCACHED_BEHAVIOR_SUPPORT_CAS Support CAS operations (this is not enabled by default at this point in the server since it imposes a slight performance penalty). -.. c:var:: MEMCACHED_BEHAVIOR_KETAMA +.. c:type:: MEMCACHED_BEHAVIOR_KETAMA Sets the default distribution to MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA and the hash to MEMCACHED_HASH_MD5. -.. c:var:: MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED +.. c:type:: MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED + + Sets the default distribution to MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA with the weighted tests. and the hash to MEMCACHED_HASH_MD5. -Sets the default distribution to MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA with the weighted tests. and the hash to MEMCACHED_HASH_MD5. - -.. c:var:: MEMCACHED_BEHAVIOR_KETAMA_HASH +.. c:type:: MEMCACHED_BEHAVIOR_KETAMA_HASH Sets the hashing algorithm for host mapping on continuum. The value can be set to either MEMCACHED_HASH_DEFAULT, MEMCACHED_HASH_MD5, MEMCACHED_HASH_CRC, MEMCACHED_HASH_FNV1_64, MEMCACHED_HASH_FNV1A_64, MEMCACHED_HASH_FNV1_32, and MEMCACHED_HASH_FNV1A_32. -.. c:var:: MEMCACHED_BEHAVIOR_KETAMA_COMPAT +.. c:type:: MEMCACHED_BEHAVIOR_KETAMA_COMPAT Sets the compatibility mode. The value can be set to either MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED (this is the default) or MEMCACHED_KETAMA_COMPAT_SPY to be compatible with the SPY Memcached client for Java. -.. c:var:: MEMCACHED_BEHAVIOR_POLL_TIMEOUT +.. c:type:: MEMCACHED_BEHAVIOR_POLL_TIMEOUT Modify the timeout value that is used by poll(). The default value is -1. An signed int pointer must be passed to memcached_behavior_set() to change this value. For memcached_behavior_get() a signed int value will be cast and returned as the unsigned long long. -.. c:var:: MEMCACHED_BEHAVIOR_USER_DATA - -DEPRECATED +.. c:type:: MEMCACHED_BEHAVIOR_USER_DATA +.. deprecated:: < 0.30 -.. c:var:: MEMCACHED_BEHAVIOR_BUFFER_REQUESTS +.. c:type:: MEMCACHED_BEHAVIOR_BUFFER_REQUESTS Enabling buffered IO causes commands to "buffer" instead of being sent. Any action that gets data causes this buffer to be be sent to the remote connection. Quiting the connection or closing down the connection will also cause the buffered data to be pushed to the remote connection. -.. c:var:: MEMCACHED_BEHAVIOR_VERIFY_KEY +.. c:type:: MEMCACHED_BEHAVIOR_VERIFY_KEY Enabling this will cause :manpage:`libmemcached(3)` to test all keys to verify that they are valid keys. -.. c:var:: MEMCACHED_BEHAVIOR_SORT_HOSTS +.. c:type:: MEMCACHED_BEHAVIOR_SORT_HOSTS Enabling this will cause hosts that are added to be placed in the host list in sorted order. This will defeat consisten hashing. -.. c:var:: MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT +.. c:type:: MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT In non-blocking mode this changes the value of the timeout during socket connection. -.. c:var:: MEMCACHED_BEHAVIOR_BINARY_PROTOCOL +.. c:type:: MEMCACHED_BEHAVIOR_BINARY_PROTOCOL Enable the use of the binary protocol. Please note that you cannot toggle this flag on an open connection. -.. c:var:: MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT +.. c:type:: MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT Set this value to enable the server be removed after continuous MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT times connection failure. -.. c:var:: MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK +.. c:type:: MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK Set this value to tune the number of messages that may be sent before libmemcached should start to automatically drain the input queue. Setting this value to high, may cause libmemcached to deadlock (trying to send data, but the send will block because the input buffer in the kernel is full). -.. c:var:: MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK +.. c:type:: MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK Set this value to tune the number of bytes that may be sent before libmemcached should start to automatically drain the input queue (need at least 10 IO requests sent without reading the input buffer). Setting this value to high, may cause libmemcached to deadlock (trying to send data, but the send will block because the input buffer in the kernel is full). -.. c:var:: MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH +.. c:type:: MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH The binary protocol works a bit different than the textual protocol in that a multiget is implemented as a pipe of single get-operations which are sent to the server in a chunk. If you are using large multigets from your application, you may improve the latency of the gets by setting this value so you send out the first chunk of requests when you hit the specified limit. It allows the servers to start processing the requests to send the data back while the rest of the requests are created and sent to the server. -.. c:var:: MEMCACHED_BEHAVIOR_NOREPLY +.. c:type:: MEMCACHED_BEHAVIOR_NOREPLY Set this value to specify that you really don't care about the result from your storage commands (set, add, replace, append, prepend). -.. c:var:: MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS +.. c:type:: MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS If you just want "a poor mans HA", you may specify the numbers of replicas libmemcached should store of each item (on different servers). This replication does not dedicate certain memcached servers to store the replicas in, but instead it will store the replicas together with all of the other objects (on the 'n' next servers specified in your server list). -.. c:var:: MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ +.. c:type:: MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ Allows randomizing the replica reads starting point. Normally the read is done from primary server and in case of miss the read is done from primary + 1, then primary + 2 all the way to 'n' replicas. If this option is set on the starting point of the replica reads is randomized between the servers. This allows distributing read load to multiple servers with the expense of more write traffic. -.. c:var:: MEMCACHED_BEHAVIOR_CORK +.. c:type:: MEMCACHED_BEHAVIOR_CORK This open has been deprecated with the behavior now built and used appropriately on selected platforms. -.. c:var:: MEMCACHED_BEHAVIOR_KEEPALIVE +.. c:type:: MEMCACHED_BEHAVIOR_KEEPALIVE Enable TCP_KEEPALIVE behavior. -.. c:var:: MEMCACHED_BEHAVIOR_KEEPALIVE_IDLE +.. c:type:: MEMCACHED_BEHAVIOR_KEEPALIVE_IDLE Specify time, in seconds, to mark a connection as idle. This is only available as an option Linux. -.. c:var:: MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE +.. c:type:: MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE Find the current size of SO_SNDBUF. A value of 0 means either an error occured or no hosts were available. It is safe to assume system default if this occurs. If an error occurs you can checked the last cached errno statement to find the specific error. -.. c:var:: MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE +.. c:type:: MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE Find the current size of SO_RCVBUF. A value of 0 means either an error occured or no hosts were available. It is safe to assume system default if this occurs. If an error occurs you can checked the last cached errno statement to find the specific error. -.. c:var:: MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT +.. c:type:: MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT +.. deprecated:: 0.48 + See :c:type:`MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS` -DEPRECATED, please see MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS. This number of times a host can have an error before it is disabled. + This number of times a host can have an error before it is disabled. -.. c:var:: MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS +.. c:type:: MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS +.. deprecated:: 0.48 + See :c:type:`MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS` -DEPRECATED, please see MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS. If enabled any hosts which have been flagged as disabled will be removed from the list of servers in the memcached_st structure. This must be used in combination with MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT. + If enabled any hosts which have been flagged as disabled will be removed from the list of servers in the memcached_st structure. This must be used in combination with MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT. -.. c:var:: MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS +.. c:type:: MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS -If enabled any hosts which have been flagged as disabled will be removed from the list of servers in the memcached_st structure. + If enabled any hosts which have been flagged as disabled will be removed from the list of servers in the memcached_st structure. -.. c:var:: MEMCACHED_BEHAVIOR_RETRY_TIMEOUT +.. c:type:: MEMCACHED_BEHAVIOR_RETRY_TIMEOUT When enabled a host which is problematic will only be checked for usage based on the amount of time set by this behavior. -.. c:var:: MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY +.. c:type:: MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY When enabled the prefix key will be added to the key when determining server by hash. diff --git a/docs/memcached_callback.rst b/docs/memcached_callback.rst index bec57f81..e5723d90 100644 --- a/docs/memcached_callback.rst +++ b/docs/memcached_callback.rst @@ -30,85 +30,85 @@ libmemcached(3) can have callbacks set key execution points. These either provide function calls at points in the code, or return pointers to structures for particular usages. -memcached_callback_get() takes a callback flag and returns the structure or -function set by memcached_callback_set(). +:c:func:`memcached_callback_get()` takes a callback flag and returns the +structure or function set by :c:func:`memcached_callback_set()`. -memcached_callback_set() changes the function/structure assigned by a +:c:func:`memcached_callback_set()` changes the function/structure assigned by a callback flag. No connections are reset. -You can use MEMCACHED_CALLBACK_USER_DATA to provide custom context if required for any of the callbacks. +You can use :c:type:`MEMCACHED_CALLBACK_USER_DATA` to provide custom context +if required for any of the callbacks. -.. c:var:: MEMCACHED_CALLBACK_CLEANUP_FUNCTION +.. c:type:: MEMCACHED_CALLBACK_CLEANUP_FUNCTION -When memcached_delete() is called this function will be excuted. At the point of its execution all connections are closed. +When :c:func:`memcached_delete()` is called this function will be excuted. At +the point of its execution all connections are closed. -.. c:var:: MEMCACHED_CALLBACK_CLONE_FUNCTION +.. c:type:: MEMCACHED_CALLBACK_CLONE_FUNCTION -When memcached_delete() is called this function will be excuted. At the -point of its execution all connections are closed. - - +When :c:func:`memcached_delete()` is called this function will be excuted. +At the point of its execution all connections are closed. -.. c:var:: MEMCACHED_CALLBACK_PREFIX_KEY +.. c:type:: MEMCACHED_CALLBACK_PREFIX_KEY You can set a value which will be used to create a domain for your keys. -The value specified here will be prefixed to each of your keys. The value can not be greater then MEMCACHED_PREFIX_KEY_MAX_SIZE - 1 and will reduce MEMCACHED_MAX_KEY by the value of your key. +The value specified here will be prefixed to each of your keys. The value can +not be greater then :c:type:`MEMCACHED_PREFIX_KEY_MAX_SIZE - 1` and will +reduce :c:type:`MEMCACHED_MAX_KEY` by the value of your key. -The prefix key is only applied to the primary key, not the master key. MEMCACHED_FAILURE will be returned if no key is set. In the case of a key which is too long, MEMCACHED_BAD_KEY_PROVIDED will be returned. +The prefix key is only applied to the primary key, not the master key. +:c:type:`MEMCACHED_FAILURE` will be returned if no key is set. In the case of +a key which is too long, :c:type:`MEMCACHED_BAD_KEY_PROVIDED` will be returned. If you set a value with the value being NULL then the prefix key is disabled. - -.. c:var:: MEMCACHED_CALLBACK_USER_DATA +.. c:type:: MEMCACHED_CALLBACK_USER_DATA This allows you to store a pointer to a specifc piece of data. This can be -retrieved from inside of memcached_fetch_execute(). Cloning a memcached_st -will copy the pointer to the clone. - - - -.. c:var:: MEMCACHED_CALLBACK_MALLOC_FUNCTION - -DEPRECATED: use memcached_set_memory_allocators instead. - - - -.. c:var:: MEMCACHED_CALLBACK_REALLOC_FUNCTION +retrieved from inside of :c:func:`memcached_fetch_execute()`. Cloning a +:c:type:`memcached_st` will copy the pointer to the clone. -DEPRECATED: use memcached_set_memory_allocators instead. - - +.. c:type:: MEMCACHED_CALLBACK_MALLOC_FUNCTION +.. deprecated:: <0.32 + Use :c:type:`memcached_set_memory_allocators` instead. -.. c:var:: MEMCACHED_CALLBACK_FREE_FUNCTION +.. c:type:: MEMCACHED_CALLBACK_REALLOC_FUNCTION +.. deprecated:: <0.32 + Use :c:type:`memcached_set_memory_allocators` instead. -DEPRECATED: use memcached_set_memory_allocators instead. - - +.. c:type:: MEMCACHED_CALLBACK_FREE_FUNCTION +.. deprecated:: <0.32 + Use :c:type:`memcached_set_memory_allocators` instead. -.. c:var:: MEMCACHED_CALLBACK_GET_FAILURE +.. c:type:: MEMCACHED_CALLBACK_GET_FAILURE This function implements the read through cache behavior. On failure of retrieval this callback will be called. You are responsible for populating the result object provided. This result object will then be stored in the server and returned to the calling process. -You must clone the memcached_st in order to +You must clone the :c:type:`memcached_st` in order to make use of it. The value will be stored only if you return -MEMCACHED_SUCCESS or MEMCACHED_BUFFERED. Returning MEMCACHED_BUFFERED will -cause the object to be buffered and not sent immediatly (if this is the default behavior based on your connection setup this will happen automatically). +:c:type:`MEMCACHED_SUCCESS` or :c:type:`MEMCACHED_BUFFERED`. Returning +:c:type:`MEMCACHED_BUFFERED` will cause the object to be buffered and not sent +immediatly (if this is the default behavior based on your connection setup +this will happen automatically). The prototype for this is: -memcached_return_t (\*memcached_trigger_key)(memcached_st \*ptr, char \*key, size_t key_length, memcached_result_st \*result); + +.. c:function:: memcached_return_t (\*memcached_trigger_key)(memcached_st \*ptr, char \*key, size_t key_length, memcached_result_st \*result); -.. c:var:: MEMCACHED_CALLBACK_DELETE_TRIGGER +.. c:type:: MEMCACHED_CALLBACK_DELETE_TRIGGER This function implements a trigger upon successful deletion of a key. The memcached_st structure will need to be cloned in order to make use of it. -The prototype for this is: typedef memcached_return_t (\*memcached_trigger_delete_key)(memcached_st \*ptr, char \*key, size_t key_length); +The prototype for this is: + +.. c:function:: typedef memcached_return_t (\*memcached_trigger_delete_key)(memcached_st \*ptr, char \*key, size_t key_length); @@ -118,12 +118,12 @@ RETURN ------ -memcached_callback_get() return the function or structure that was provided. -Upon error, nothing is set, null is returned, and the memcached_return_t -argument is set to MEMCACHED_FAILURE. +:c:func:`memcached_callback_get()` return the function or structure that was +provided. Upon error, nothing is set, null is returned, and the +:c:type:`memcached_return_t` argument is set to :c:type:`MEMCACHED_FAILURE`. -memcached_callback_set() returns MEMCACHED_SUCCESS upon successful setting, -otherwise MEMCACHED_FAILURE on error. +:c:func:`memcached_callback_set()` returns :c:type:`MEMCACHED_SUCCESS` upon +successful setting, otherwise :c:type:`MEMCACHED_FAILURE` on error. ---- diff --git a/docs/memcached_cas.rst b/docs/memcached_cas.rst index 9d2188a6..c2138bc8 100644 --- a/docs/memcached_cas.rst +++ b/docs/memcached_cas.rst @@ -23,33 +23,30 @@ Compile and link with -lmemcached DESCRIPTION ----------- -memcached_cas() overwrites data in the server as long as the "cas" value is -still the same in the server. You can get the cas value of a result by -calling memcached_result_cas() on a memcached_result_st(3) structure. At the point -that this note was written cas is still buggy in memached. Turning on tests -for it in libmemcached(3) is optional. Please see memcached_set() for -information on how to do this. - -memcached_cas_by_key() method behaves in a similar method as the non key -methods. The difference is that it uses the group_key parameter to map -objects to particular servers. - -memcached_cas() is testsed with the \ ``MEMCACHED_BEHAVIOR_USE_UDP``\ -behavior enabled. However, when using these operations with this behavior on, there -are limits to the size of the payload being sent to the server. The reason for -these limits is that the Memcached Server does not allow multi-datagram requests -and the current server implementation sets a datagram size to 1400 bytes. Due -to protocol overhead, the actual limit of the user supplied data is less than -1400 bytes and depends on the protocol in use as, well as the operation being -executed. When running with the binary protocol, \ `` MEMCACHED_BEHAVIOR_BINARY_PROTOCOL``\ , -the size of the key,value, flags and expiry combined may not exceed 1368 bytes. -When running with the ASCII protocol, the exact limit fluctuates depending on -which function is being executed and whether the function is a cas operation -or not. For non-cas ASCII set operations, there are at least 1335 bytes available -to split among the key, key_prefix, and value; for cas ASCII operations there are -at least 1318 bytes available to split among the key, key_prefix and value. If the -total size of the command, including overhead, exceeds 1400 bytes, a \ ``MEMCACHED_WRITE_FAILURE``\ -will be returned. +:c:func:`memcached_cas()` overwrites data in the server as long as the "cas" +value is still the same in the server. You can get the cas value of a result +by calling :c:func:`memcached_result_cas()` on a memcached_result_st(3) +structure. At the point that this note was written cas is still buggy in memached. Turning on tests for it in libmemcached(3) is optional. Please see +:c:func:`memcached_set()` for information on how to do this. + +:c:func:`memcached_cas_by_key()` method behaves in a similar method as the non +key methods. The difference is that it uses the :c:type:`group_key` parameter +to map objects to particular servers. + +:c:func:`memcached_cas()` is testsed with the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior enabled. However, when using these operations with this behavior +on, there are limits to the size of the payload being sent to the server. The +reason for these limits is that the Memcached Server does not allow +multi-datagram requests and the current server implementation sets a datagram +size to 1400 bytes. Due to protocol overhead, the actual limit of the user +supplied data is less than 1400 bytes and depends on the protocol in use as, +well as the operation being executed. When running with the binary protocol, +:c:type:`MEMCACHED_BEHAVIOR_BINARY_PROTOCOL`, the size of the key,value, +flags and expiry combined may not exceed 1368 bytes. When running with the +ASCII protocol, the exact limit fluctuates depending on which function is +being executed and whether the function is a cas operation or not. For +non-cas ASCII set operations, there are at least 1335 bytes available to +split among the key, key_prefix, and value; for cas ASCII operations there +are at least 1318 bytes available to split among the key, key_prefix and value. If the total size of the command, including overhead, exceeds 1400 bytes, a :c:type:`MEMCACHED_WRITE_FAILURE` will be returned. ------ @@ -57,9 +54,10 @@ RETURN ------ -All methods return a value of type \ ``memcached_return_t``\ . -On success the value will be \ ``MEMCACHED_SUCCESS``\ . -Use memcached_strerror() to translate this value to a printable string. +All methods return a value of type :c:type:`memcached_return_t`. +On success the value will be :c:type:`MEMCACHED_SUCCESS`. +Use :c:func:`memcached_strerror()` to translate this value to a printable +string. ---- @@ -76,5 +74,5 @@ SEE ALSO -------- -memcached(1) libmemached(3) memcached_strerror(3) memcached_set(3) memcached_append(3) memcached_add(3) memcached_prepend(3) memcached_replace(3) +:manpage:`memcached(1)` :manpage:`libmemached(3)` :manpage:`memcached_strerror(3)` :manpage:`memcached_set(3)` :manpage:`memcached_append(3)` :manpage:`memcached_add(3)` :manpage:`memcached_prepend(3)` :manpage:`memcached_replace(3)` diff --git a/docs/memcached_create.rst b/docs/memcached_create.rst index 12bf92c5..8e1d30f5 100644 --- a/docs/memcached_create.rst +++ b/docs/memcached_create.rst @@ -2,21 +2,21 @@ Creating and destroying a memcached_st ====================================== -.. index:: object: memcached_st - -------- SYNOPSIS -------- #include + +.. c:type:: memcachd_st + +.. c:function:: memcached_st* memcached_create(memcached_st *ptr) -.. c:function:: memcached_st *memcached_create (memcached_st *ptr); - -.. c:function:: void memcached_free (memcached_st *ptr); +.. c:function:: void memcached_free(memcached_st *ptr) -.. c:function:: memcached_st *memcached_clone (memcached_st *destination, memcached_st *source); +.. c:function:: memcached_st* memcached_clone(memcached_st *destination, memcached_st *source) -.. c:function:: void memcached_servers_reset(memcached_st); +.. c:function:: void memcached_servers_reset(memcached_st) Compile and link with -lmemcached @@ -25,25 +25,30 @@ Compile and link with -lmemcached DESCRIPTION ----------- -memcached_create() is used to create a \ ``memcached_st``\ structure that will then -be used by other libmemcached(3) functions to communicate with the server. You -should either pass a statically declared \ ``memcached_st``\ to memcached_create() or +:c:func:`memcached_create()` is used to create a :c:type:`memcached_st` +structure that will then be used by other libmemcached(3) functions to +communicate with the server. You should either pass a statically declared +:c:type:`memcached_st` to :c:func:`memcached_create()` or a NULL. If a NULL passed in then a structure is allocated for you. -Please note, when you write new application use memcached_create_with_options() over memcached_create(). +Please note, when you write new application use +:c:func:`memcached_create_with_options()` over +:c:func:`memcached_create()`. -memcached_clone() is similar to memcached_create(3) but it copies the -defaults and list of servers from the source \ ``memcached_st``\ . If you pass a null as -the argument for the source to clone, it is the same as a call to memcached_create(). -If the destination argument is NULL a \ ``memcached_st``\ will be allocated for you. +:c:func:`memcached_clone()` is similar to :c:func:`memcached_create()` but +it copies the defaults and list of servers from the source +:c:type:`memcached_st`. If you pass a null as the argument for the source +to clone, it is the same as a call to :c:func:`memcached_create()`. +If the destination argument is NULL a :c:type:`memcached_st` will be allocated +for you. -memcached_servers_reset() allows you to zero out the list of servers that -the memcached_st has. +:c:func:`memcached_servers_reset()` allows you to zero out the list of +servers that the :c:type:`memcached_st` has. -To clean up memory associated with a \ ``memcached_st``\ structure you should pass -it to memcached_free() when you are finished using it. memcached_free() is -the only way to make sure all memory is deallocated when you finish using -the structure. +To clean up memory associated with a :c:type:`memcached_st` structure you +should pass it to :c:func:`memcached_free()` when you are finished using it. +:c:func:`memcached_free()` is the only way to make sure all memory is +deallocated when you finish using the structure. You may wish to avoid using memcached_create(3) or memcached_clone(3) with a stack based allocation. The most common issues related to ABI safety involve @@ -55,11 +60,11 @@ RETURN ------ -memcached_create() returns a pointer to the memcached_st that was created -(or initialized). On an allocation failure, it returns NULL. +:c:func:`memcached_create()` returns a pointer to the :c:type:`memcached_st` +that was created (or initialized). On an allocation failure, it returns NULL. -memcached_clone() returns a pointer to the memcached_st that was created -(or initialized). On an allocation failure, it returns NULL. +:c:func:`memcached_clone()` returns a pointer to the :c:type:`memcached_st` +that was created (or initialized). On an allocation failure, it returns NULL. ---- diff --git a/docs/memcached_delete.rst b/docs/memcached_delete.rst index 5c373b08..acea40fa 100644 --- a/docs/memcached_delete.rst +++ b/docs/memcached_delete.rst @@ -22,9 +22,9 @@ DESCRIPTION ----------- -memcached_delete() is used to delete a particular key. -memcached_delete_by_key() works the same, but it takes a master key to -find the given value. +:c:func:`memcached_delete()` is used to delete a particular key. +:c:func:`memcached_delete_by_key()` works the same, but it takes a master key +to find the given value. Expiration works by placing the item into a delete queue, which means that it won't be possible to retrieve it by the "get" command. The "add" and @@ -40,9 +40,10 @@ RETURN ------ -A value of type \ ``memcached_return_t``\ is returned -On success that value will be \ ``MEMCACHED_SUCCESS``\ . -Use memcached_strerror() to translate this value to a printable string. +A value of type :c:type:`memcached_return_t` is returned +On success that value will be :c:type:`MEMCACHED_SUCCESS`. +Use :c:func:`memcached_strerror()` to translate this value to a printable +string. If you are using the non-blocking mode of the library, success only means that the message was queued for delivery. diff --git a/docs/memcached_dump.rst b/docs/memcached_dump.rst index 08c21c46..3ef1c43c 100644 --- a/docs/memcached_dump.rst +++ b/docs/memcached_dump.rst @@ -28,9 +28,9 @@ DESCRIPTION ----------- -memcached_dump() is used to get a list of keys found in memcached(1) servers. -Because memcached(1) does not guarentee to dump all keys you can not assume -you have fetched all keys from the server. The function takes an array +:c:func:`memcached_dump()` is used to get a list of keys found in memcached(1) +servers. Because memcached(1) does not guarentee to dump all keys you can not +assume you have fetched all keys from the server. The function takes an array of callbacks that it will use to execute on keys as they are found. Currently the binary protocol is not testsed. @@ -41,9 +41,10 @@ RETURN ------ -A value of type \ ``memcached_return_t``\ is returned -On success that value will be \ ``MEMCACHED_SUCCESS``\ . -Use memcached_strerror() to translate this value to a printable string. +A value of type :c:type:`memcached_return_t` is returned +On success that value will be :c:type:`MEMCACHED_SUCCESS`. +Use :c:func:`memcached_strerror()` to translate this value to a printable +string. ---- diff --git a/docs/memcached_flush.rst b/docs/memcached_flush.rst index 42453b35..a5c273de 100644 --- a/docs/memcached_flush.rst +++ b/docs/memcached_flush.rst @@ -24,7 +24,7 @@ DESCRIPTION ----------- -:c:func::`memcached_flush()` is used to wipe clean the contents of memcached(1) servers. +:c:func::`memcached_flush()` is used to wipe clean the contents of :program:`memcached` servers. It will either do this immediately or expire the content based on the expiration time passed to the method (a value of zero causes an immediate flush). The operation is not atomic to multiple servers, just atomic to a @@ -37,11 +37,10 @@ RETURN ------ -A value of type :c:type:`memcached_return_t` is returned +A value of type :c:type:`memcached_return_t` is returned On success that value will be :c:type:`MEMCACHED_SUCCESS`. Use :c:type:`memcached_strerror()` to translate this value to a printable string. - ---- HOME ---- diff --git a/docs/memcached_flush_buffers.rst b/docs/memcached_flush_buffers.rst index 5419c900..1a6088c2 100644 --- a/docs/memcached_flush_buffers.rst +++ b/docs/memcached_flush_buffers.rst @@ -23,9 +23,8 @@ DESCRIPTION ----------- -memcached_flush_buffers() is used in conjunction with -MEMCACHED_BEHAVIOR_BUFFER_REQUESTS (see memcached_behavior(3)) to flush -all buffers by sending the buffered commands to the server for processing. +:c:func:`memcached_flush_buffers()` is used in conjunction with +:c:type:`MEMCACHED_BEHAVIOR_BUFFER_REQUESTS` (see memcached_behavior(3)) to flush all buffers by sending the buffered commands to the server for processing. ------ @@ -33,9 +32,10 @@ RETURN ------ -A value of type \ ``memcached_return_t``\ is returned -On success that value will be \ ``MEMCACHED_SUCCESS``\ . -Use memcached_strerror() to translate this value to a printable string. +A value of type :c:type:`memcached_return_t` is returned +On success that value will be :c:type:`MEMCACHED_SUCCESS`. +Use :c:func:`memcached_strerror()` to translate this value to a printable +string. ---- diff --git a/docs/memcached_generate_hash_value.rst b/docs/memcached_generate_hash_value.rst index 4bfe2f07..3da05dfd 100644 --- a/docs/memcached_generate_hash_value.rst +++ b/docs/memcached_generate_hash_value.rst @@ -26,17 +26,17 @@ DESCRIPTION ----------- -memcached_generate_hash_value() allows you to hash a key using one of +:c:func:`memcached_generate_hash_value()` allows you to hash a key using one of the hash functions defined in the library. This method is provided for the convenience of higher-level language bindings and is not necessary for normal memcache operations. The allowed hash algorithm constants are listed in the manpage for -memcached_behavior_set(). +:c:func:`memcached_behavior_set()`. -memcached_generate_hash() takes a memcached_st struture and produces -the hash value that would have been generated based on the defaults -of the memcached_st structure. +:c:func:`memcached_generate_hash()` takes a :c:type:`memcached_st` struture +and produces the hash value that would have been generated based on the +defaults of the :c:type:`memcached_st structure`. As of version 0.36 all hash methods have been placed into the library libhashkit(3) which is linked with libmemcached(3). For more information please see its documentation. diff --git a/docs/memcached_get.rst b/docs/memcached_get.rst index 2a87e913..4285b3ae 100644 --- a/docs/memcached_get.rst +++ b/docs/memcached_get.rst @@ -11,23 +11,21 @@ SYNOPSIS #include -.. c:function:: memcached_result_st * memcached_fetch_result (memcached_st *ptr, memcached_result_st *result, memcached_return_t *error); +.. c:function:: memcached_result_st * memcached_fetch_result (memcached_st *ptr, memcached_result_st *result, memcached_return_t *error) -.. c:function:: char * memcached_get (memcached_st *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error); +.. c:function:: char * memcached_get (memcached_st *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error) -.. c:function:: memcached_return_t memcached_mget (memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys); +.. c:function:: memcached_return_t memcached_mget (memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys) -.. c:function:: char * memcached_get_by_key (memcached_st *ptr, const char *group_key, size_t group_key_length, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error); +.. c:function:: char * memcached_get_by_key (memcached_st *ptr, const char *group_key, size_t group_key_length, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error) -.. c:function:: memcached_return_t memcached_mget_by_key (memcached_st *ptr, const char *group_key, size_t group_key_length, const char * const *keys, const size_t *key_length, size_t number_of_keys); +.. c:function:: memcached_return_t memcached_mget_by_key (memcached_st *ptr, const char *group_key, size_t group_key_length, const char * const *keys, const size_t *key_length, size_t number_of_keys) -.. c:function:: char * memcached_fetch (memcached_st *ptr, char *key, size_t *key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error); +.. c:function:: memcached_return_t memcached_fetch_execute (memcached_st *ptr, memcached_execute_fn *callback, void *context, uint32_t number_of_callbacks) -.. c:function:: memcached_return_t memcached_fetch_execute (memcached_st *ptr, memcached_execute_fn *callback, void *context, uint32_t number_of_callbacks); +.. c:function:: memcached_return_t memcached_mget_execute (memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys, memcached_execute_fn *callback, void *context, uint32_t number_of_callbacks) -.. c:function:: memcached_return_t memcached_mget_execute (memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys, memcached_execute_fn *callback, void *context, uint32_t number_of_callbacks); - -.. c:function:: memcached_return_t memcached_mget_execute_by_key (memcached_st *ptr, const char *group_key, size_t group_key_length, const char * const *keys, const size_t *key_length, size_t number_of_keys, memcached_execute_fn *callback, void *context, uint32_t number_of_callbacks); +.. c:function:: memcached_return_t memcached_mget_execute_by_key (memcached_st *ptr, const char *group_key, size_t group_key_length, const char * const *keys, const size_t *key_length, size_t number_of_keys, memcached_execute_fn *callback, void *context, uint32_t number_of_callbacks) Compile and link with -lmemcached @@ -37,75 +35,63 @@ DESCRIPTION ----------- -memcached_get() is used to fetch an individual value from the server. You -must pass in a key and its length to fetch the object. You must supply +:c:func:`memcached_get()` is used to fetch an individual value from the server. +You must pass in a key and its length to fetch the object. You must supply three pointer variables which will give you the state of the returned -object. A uint32_t pointer to contain whatever flags you stored with the value, -a size_t pointer which will be filled with size of of the object, and a -memcached_return_t pointer to hold any error. The object will be returned -upon success and NULL will be returned on failure. Any object returned by -memcached_get() must be released by the caller application. - -memcached_mget() is used to select multiple keys at once. For multiple key -operations it is always faster to use this function. This function always -works asynchronously. memcached_fetch() is then used to retrieve any keys -found. No error is given on keys that are not found. You must call either -memcached_fetch() or memcached_fetch_result() after a successful call to -memcached_mget(). You should continue to call these functions until they -return NULL (aka no more values). If you need to quit in the middle of a -memcached_get() call, execute a memcached_quit(). After you do this, you can -issue new queries against the server. - -memcached_fetch() is used to fetch an individual value from the server. -memcached_mget() must always be called before using this method. You -must pass in a key and its length to fetch the object. You must supply +object. A :c:type:`uint32_t` pointer to contain whatever flags you stored with the value, a :c:type:`size_t` pointer which will be filled with size of of +the object, and a :c:type:`memcached_return_t` pointer to hold any error. The +object will be returned upon success and NULL will be returned on failure. Any +object returned by :c:func:`memcached_get()` must be released by the caller +application. + +:c:func:`memcached_mget()` is used to select multiple keys at once. For +multiple key operations it is always faster to use this function. This function always works asynchronously. + +To retrieve data after a successful execution of :c:func:`memcached_mget()`, you will need to +call :c:func:`memcached_fetch_result()`. You should continue to call this function until +it returns a NULL (i.e. no more values). If you need to quit in the middle of a +:c:func:`memcached_mget()` call, you can execute a :c:func:`memcached_quit()`, those this is not required. + +:c:func:`memcached_fetch_result()` is used to fetch an individual value from the server. :c:func:`memcached_mget()` must always be called before using this method. +You must pass in a key and its length to fetch the object. You must supply three pointer variables which will give you the state of the returned -object. A uint32_t pointer to contain whatever flags you stored with the value, -a size_t pointer which will be filled with size of of the object, and a -memcached_return_t pointer to hold any error. The object will be returned -upon success and NULL will be returned on failure. :c:type:`MEMCACHD_END` is -returned by the \*error value when all objects that have been found are -returned. The final value upon :c:type:`MEMCACHED_END` is null. Values -returned by memcached_fetch() must be freed by the caller. memcached_fetch() -will be DEPRECATED in the near future, memcached_fetch_result() should be -used instead. - -memcached_fetch_result() is used to return a memcached_result_st(3) structure -from a memcached server. The result object is forward compatible with changes -to the server. For more information please refer to the memcached_result_st(3) -help. This function will dynamically allocate a result structure for you -if you do not pass one to the function. - -memcached_fetch_execute() is a callback function for result sets. Instead -of returning the results to you for processing, it passes each of the +object. A :c:type:`uint32_t` pointer to contain whatever flags you stored with the value, a :c:type:`size_t` pointer which will be filled with size of of the +object, and a :c:type:`memcached_return_t` pointer to hold any error. The +object will be returned upon success and NULL will be returned on failure. :c:type:`MEMCACHD_END` is returned by the \*error value when all objects that have been found are returned. The final value upon :c:type:`MEMCACHED_END` is null. + +:c:func:`memcached_fetch_result()` is used to return a :c:type:`memcached_result_st` structure from a memcached server. The result object is forward compatible +with changes to the server. For more information please refer to the +:c:type:`memcached_result_st` help. This function will dynamically allocate a +result structure for you if you do not pass one to the function. + +:c:func:`memcached_fetch_execute()` is a callback function for result sets. +Instead of returning the results to you for processing, it passes each of the result sets to the list of functions you provide. It passes to the function -a memcached_st that can be cloned for use in the called function (it can not -be used directly). It also passes a result set which does not need to be freed. -Finally it passes a "context". This is just a pointer to a memory reference -you supply the calling function. Currently only one value is being passed -to each function call. In the future there will be an option to allow this -to be an array. - -memcached_mget_execute() and memcached_mget_execute_by_key() is -similar to memcached_mget(), but it may trigger the supplied callbacks -with result sets while sending out the queries. If you try to perform -a really large multiget with memcached_mget() you may encounter a -deadlock in the OS kernel (it will fail to write data to the socket because -the input buffer is full). memcached_mget_execute() solves this -problem by processing some of the results before continuing sending -out requests. Please note that this function is only available in the -binary protocol. - -memcached_get_by_key() and memcached_mget_by_key() behave in a similar nature -as memcached_get() and memcached_mget(). The difference is that they take -a master key that is used for determining which server an object was stored -if key partitioning was used for storage. - -All of the above functions are not tested when the \ ``MEMCACHED_BEHAVIOR_USE_UDP``\ -has been set. Executing any of these functions with this behavior on will result in -\ ``MEMCACHED_NOT_SUPPORTED``\ being returned, or for those functions which do not return -a \ ``memcached_return_t``\ , the error function parameter will be set to -\ ``MEMCACHED_NOT_SUPPORTED``\ . +a :c:type:`memcached_st` that can be cloned for use in the called +function (it can not be used directly). It also passes a result set which does +not need to be freed. Finally it passes a "context". This is just a pointer to +a memory reference you supply the calling function. Currently only one value +is being passed to each function call. In the future there will be an option +to allow this to be an array. + +:c:func:`memcached_mget_execute()` and :c:func:`memcached_mget_execute_by_key()` +is similar to :c:func:`memcached_mget()`, but it may trigger the supplied +callbacks with result sets while sending out the queries. If you try to +perform a really large multiget with :c:func:`memcached_mget()` you may +encounter a deadlock in the OS kernel (it will fail to write data to the +socket because the input buffer is full). :c:func:`memcached_mget_execute()` +solves this problem by processing some of the results before continuing +sending out requests. Please note that this function is only available in +the binary protocol. + +:c:func:`memcached_get_by_key()` and :c:func:`memcached_mget_by_key()` behave +in a similar nature as :c:func:`memcached_get()` and :c:func:`memcached_mget()`. +The difference is that they take a master key that is used for determining +which server an object was stored if key partitioning was used for storage. + +All of the above functions are not tested when the +:c:type:`MEMCACHED_BEHAVIOR_USE_UDP` has been set. Executing any of these +functions with this behavior on will result in :c:type:`MEMCACHED_NOT_SUPPORTED` being returned, or for those functions which do not return a :c:type:`memcached_return_t`, the error function parameter will be set to :c:type:`MEMCACHED_NOT_SUPPORTED`. ------ @@ -113,23 +99,20 @@ RETURN ------ -All objects returned must be freed by the calling application. -memcached_get() and memcached_fetch() will return NULL on error. You must -look at the value of error to determine what the actual error was. +All objects retrieved via :c:func:`memcached_get()` or :c:func:`memcached_get_by_key()` must be freed with :manpage:`free(3)`. + +:c:func:`memcached_get()` will return NULL on +error. You must look at the value of error to determine what the actual error +was. :c:func:`memcached_fetch_execute()` return :c:type:`MEMCACHED_SUCCESS` if all keys were successful. :c:type:`MEMCACHED_NOTFOUND` will be return if no keys at all were found. -:c:func:`memcached_fetch()` and :c:func:`memcached_fetch_result()` set error +:c:func:`memcached_fetch_result()` sets error to :c:type:`MEMCACHED_END` upon successful conclusion. :c:type:`MEMCACHED_NOTFOUND` will be return if no keys at all were found. -MEMCACHED_KEY_TOO_BIG is set to error whenever memcached_fetch() was used -and the key was set larger then MEMCACHED_MAX_KEY, which was the largest -key allowed for the original memcached ascii server. - - ---- HOME ---- @@ -139,7 +122,6 @@ To find out more information please check: `http://libmemcached.org/ `_ - -------- SEE ALSO -------- diff --git a/docs/memcached_memory_allocators.rst b/docs/memcached_memory_allocators.rst index 33f3d3a7..ce8af386 100644 --- a/docs/memcached_memory_allocators.rst +++ b/docs/memcached_memory_allocators.rst @@ -39,18 +39,18 @@ DESCRIPTION libmemcached(3) allows you to specify your own memory allocators, optimized for your application. This enables libmemcached to be used inside of applications that have their own malloc implementation. -memcached_set_memory_allocators() is used to set the memory allocators used -by the memcached instance specified by ptr. Please note that you cannot -override only one of the memory allocators, you have to specify a complete -new set if you want to override one of them. All of the memory allocation -functions should behave as specified in the C99 standard. Specify NULL as -all functions to reset them to the default values. +:c:func:`memcached_set_memory_allocators()` is used to set the memory +allocators used by the memcached instance specified by ptr. Please note that +you cannot override only one of the memory allocators, you have to specify a +complete new set if you want to override one of them. All of the memory +allocation functions should behave as specified in the C99 standard. Specify +NULL as all functions to reset them to the default values. -memcached_get_memory_allocators() is used to get the currently used memory -allocators by a mamcached handle. +:c:func:`memcached_get_memory_allocators()` is used to get the currently used +memory allocators by a mamcached handle. -memcached_get_memory_allocators_context() returns the void \* that was -passed in during the call to memcached_set_memory_allocators(). +:c:func:`memcached_get_memory_allocators_context()` returns the void \* that +was passed in during the call to :c:func:`memcached_set_memory_allocators()`. The first argument to the memory allocator functions is a pointer to a memcached structure, the is passed as const and you will need to clone @@ -72,8 +72,9 @@ RETURN ------ -memcached_set_memory_allocators() return MEMCACHED_SUCCESS upon success, -and MEMCACHED_FAILURE if you don't pass a complete set of function pointers. +:c:func:`memcached_set_memory_allocators()` return :c:type:`MEMCACHED_SUCCESS` +upon success, and :c:type:`MEMCACHED_FAILURE` if you don't pass a complete set +of function pointers. ---- diff --git a/docs/memcached_pool.rst b/docs/memcached_pool.rst index aa914e50..7dcc707a 100644 --- a/docs/memcached_pool.rst +++ b/docs/memcached_pool.rst @@ -2,25 +2,25 @@ Working with memcached pools ============================ -.. index:: object: memcached_pool_st - -------- SYNOPSIS -------- #include -.. c:function:: memcached_pool_st *memcached_pool(const char *option_string, size_t option_string_length); +.. c:type:: memcached_pool_st -.. c:function:: memcached_pool_st * memcached_pool_create(memcached_st* mmc, int initial, int max); DEPRECATED - -.. c:function:: memcached_st * memcached_pool_destroy(memcached_pool_st* pool); +.. c:function:: memcached_pool_st* memcached_pool(const char *option_string, size_t option_string_length) + +.. c:function:: memcached_pool_st* memcached_pool_create(memcached_st* mmc, int initial, int max) +.. deprecated:: 0.46 + Use :c:func:`memcached_pool()` instead. -.. c:function:: memcached_st * memcached_pool_pop (memcached_pool_st* pool, bool block, memcached_return_t *rc); +.. c:function:: memcached_st* memcached_pool_destroy(memcached_pool_st* pool) -.. c:function:: memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *mmc); +.. c:function:: memcached_st* memcached_pool_pop (memcached_pool_st* pool, bool block, memcached_return_t *rc) -.. c:function:: memcached_st *memcached_create (memcached_st *ptr); +.. c:function:: memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *mmc) .. c:function:: memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool, memcached_behavior_t flag, uint64_t data) @@ -34,60 +34,36 @@ DESCRIPTION ----------- -memcached_pool() is used to create a connection pool of objects you may use -to remove the overhead of using memcached_clone for short lived -\ ``memcached_st``\ objects. Please see :manpage:`libmemcached_configuration` for details on the format of the configuration string. - -DEPRECATED memcached_pool_create() is used to create a connection pool of -objects you may use to remove the overhead of using memcached_clone for -short lived \ ``memcached_st``\ objects. The mmc argument should be an -initialised \ ``memcached_st``\ structure, and a successfull invocation of -memcached_pool_create takes full ownership of the variable (until it is -released by memcached_pool_destroy). The \ ``initial``\ argument specifies -the initial size of the connection pool, and the \ ``max``\ argument -specifies the maximum size the connection pool should grow to. Please note -that the library will allocate a fixed size buffer scaled to the max size of -the connection pool, so you should not pass MAXINT or some other large -number here. - -memcached_pool_destroy() is used to destroy the connection pool -created with memcached_pool_create() and release all allocated -resources. It will return the pointer to the \ ``memcached_st``\ structure -passed as an argument to memcached_pool_create(), and returns the ownership -of the pointer to the caller when created with memcached_pool_create, -otherwise NULL is returned.. - -memcached_pool_pop() is used to grab a connection structure from the +:c:func:`memcached_pool()` is used to create a connection pool of objects you +may use to remove the overhead of using memcached_clone for short lived +:c:type:`memcached_st` objects. Please see :doc:`libmemcached_configuration` for details on the format of the configuration string. + +:c:func:`memcached_pool_destroy()` is used to destroy the connection pool +created with :c:func:`memcached_pool_create()` and release all allocated +resources. It will return the pointer to the :c:type:`memcached_st` structure +passed as an argument to :c:func:`memcached_pool_create()`, and returns the ownership of the pointer to the caller when created with :c:func:`memcached_pool_create()`, otherwise NULL is returned.. + +:c:func:`memcached_pool_pop()` is used to grab a connection structure from the connection pool. The block argument specifies if the function should block and wait for a connection structure to be available if we try to exceed the maximum size. -memcached_pool_push() is used to return a connection structure back to the pool. +:c:func:`memcached_pool_push()` is used to return a connection structure back to the pool. -memcached_pool_behavior_set() and memcached_pool_behagior_get() is -used to get/set behavior flags on all connections in the pool. +:c:func:`memcached_pool_behavior_get()` and :c:func:`memcached_pool_behavior_set()` is used to get/set behavior flags on all connections in the pool. ------ RETURN ------ +:c:func:`memcached_pool_destroy()` returns the pointer (and ownership) to the :c:type:`memcached_st` structure used to create the pool. If connections are in use it returns NULL. -memcached_pool_create() returns a pointer to the newly created -memcached_pool_st structure. On an allocation failure, it returns -NULL. - -memcached_pool_destroy() returns the pointer (and ownership) to the -memcached_st structure used to create the pool. If connections are in -use it returns NULL. - -memcached_pool_pop() returns a pointer to a memcached_st structure -from the pool (or NULL if an allocation cannot be satisfied). +:c:func:`memcached_pool_pop()` returns a pointer to a :c:type:`memcached_st` structure from the pool (or NULL if an allocation cannot be satisfied). -memcached_pool_push() returns MEMCACHED_SUCCESS upon success. +:c:func:`memcached_pool_push()` returns :c:type:`MEMCACHED_SUCCESS` upon success. -memcached_pool_behavior_get() and memcached_pool_behavior_get() -returns MEMCACHED_SUCCESS upon success. +:c:func:`memcached_pool_behavior_get()` and :c:func:`memcached_pool_behavior_get()` returns :c:type:`MEMCACHED_SUCCESS` upon success. ---- @@ -113,4 +89,4 @@ Trond Norbye, SEE ALSO -------- -:manpage:`memcached(1)` :manpage:`libmemcached(3)` :manpage:`memcached_strerror(3)` +:manpage:`memcached(1)` :manpage:`libmemcached(3)` :manpage:`memcached_strerror(3)` :manpage:`libmemcached_configuration(3)` diff --git a/docs/memcached_quit.rst b/docs/memcached_quit.rst index 06e98e8f..8377f63c 100644 --- a/docs/memcached_quit.rst +++ b/docs/memcached_quit.rst @@ -19,15 +19,14 @@ DESCRIPTION ----------- -memcached_quit() will disconnect you from all currently connected servers. -It will also reset the state of the connection (ie, any memcached_fetch() you -are in the middle of will be terminated). This function is called -automatically when you call memcached_free() on the \ ``memcached_st``\ structure. +:c:func:`memcached_quit()` will disconnect you from all currently connected +servers. It will also reset the state of the connection (ie, any :c:func:`memcached_fetch()` you are in the middle of will be terminated). This function is +called automatically when you call :c:func:`memcached_free()` on the :c:type:`memcached_st` structure. You do not need to call this on your own. All operations to change server hashes and parameters will handle connections to the server for you. This function is provided mainly so that you can timeout your connections or -reset connections during the middle of a memcached_fetch(). +reset connections during the middle of a :c:func:`memcached_fetch()`. ------ @@ -35,9 +34,9 @@ RETURN ------ -A value of type \ ``memcached_return``\ is returned -On success that value will be \ ``MEMCACHED_SUCCESS``\ . -Use memcached_strerror() to translate this value to a printable string. +A value of type :c:type:`memcached_return` is returned +On success that value will be :c:type:`MEMCACHED_SUCCESS`. +Use :c:func:`memcached_strerror()` to translate this value to a printable string. ---- diff --git a/docs/memcached_result_st.rst b/docs/memcached_result_st.rst index dbbbfd20..295b2229 100644 --- a/docs/memcached_result_st.rst +++ b/docs/memcached_result_st.rst @@ -41,51 +41,50 @@ DESCRIPTION ----------- -libmemcached(3) can optionally return a memcached_result_st which acts as a -result object. The result objects have added benefits over the character -pointer returns, in that they are forward compatible with new return items -that future memcached servers may implement (the best current example of -this is the CAS return item). The structures can also be reused, which will -save on calls to malloc(3). It is suggested that you use result objects over -char \* return functions. +libmemcached(3) can optionally return a :c:type:`memcached_result_st` which +acts as a result object. The result objects have added benefits over the +character pointer returns, in that they are forward compatible with new +return items that future memcached servers may implement (the best current +example of this is the CAS return item). The structures can also be reused, +which will save on calls to malloc(3). It is suggested that you use result +objects over char \* return functions. -The structure of memcached_result_st has been encapsulated, you should not -write code to directly access members of the structure. +The structure of :c:type:`memcached_result_st` has been encapsulated, you should +not write code to directly access members of the structure. -memcached_result_create() will either allocate memory for a -memcached_result_st or will initialize a structure passed to it. +:c:func:`memcached_result_create()` will either allocate memory for a +:c:type:`memcached_result_st` or will initialize a structure passed to it. -memcached_result_free() will deallocate any memory attached to the +:c:func:`memcached_result_free()` will deallocate any memory attached to the structure. If the structure was also allocated, it will deallocate it. -memcached_result_key_value() returns the key value associated with the +:c:func:`memcached_result_key_value()` returns the key value associated with the current result object. -memcached_result_key_length() returns the key length associated with the -current result object. +:c:func:`memcached_result_key_length()` returns the key length associated with +the current result object. -memcached_result_value() returns the result value associated with the +:c:func:`memcached_result_value()` returns the result value associated with the current result object. -memcached_result_length() returns the result length associated with the -current result object. +:c:func:`memcached_result_length()` returns the result length associated with +the current result object. -memcached_result_flags() returns the flags associated with the +:c:func:`memcached_result_flags()` returns the flags associated with the current result object. -memcached_result_cas() returns the cas associated with the +:c:func:`memcached_result_cas()` returns the cas associated with the current result object. This value will only be available if the server tests it. -memcached_result_set_value() takes a byte array and a size and sets +:c:func:`memcached_result_set_value()` takes a byte array and a size and sets the result to this value. This function is used for trigger responses. -void memcached_result_set_flags() takes a result structure and stores +:c:func:`void memcached_result_set_flags()` takes a result structure and stores a new value for the flags field. -void memcached_result_set_expiration(A) takes a result structure and stores -a new value for the expiration field (this is only used by read through -triggers). +:c:func:`void memcached_result_set_expiration(A)` takes a result structure and stores a new value for the expiration field (this is only used by read +through triggers). You may wish to avoid using memcached_result_create(3) with a stack based allocation. The most common issues related to ABI safety involve @@ -98,8 +97,8 @@ RETURN Varies, see particular functions. All structures must have -memcached_result_free() called on them for cleanup purposes. Failure to -do this will result in leaked memory. +:c:func:`memcached_result_free()` called on them for cleanup purposes. Failure +to do this will result in leaked memory. ---- diff --git a/docs/memcached_sasl.rst b/docs/memcached_sasl.rst index 4dc4039c..bd51348b 100644 --- a/docs/memcached_sasl.rst +++ b/docs/memcached_sasl.rst @@ -34,16 +34,16 @@ libsasl to perform SASL authentication. Please note that SASL requires the memcached binary protocol, and you have to specify the callbacks before you connect to the server. -memcached_set_sasl_auth_data() is a helper function defining +:c:func:`memcached_set_sasl_auth_data()` is a helper function defining the basic functionality for you, but it will store the username and password in memory. If you choose to use this method you have to call -memcached_destroy_sasl_auth_data before calling memcached_free to avoid -a memory leak. You should NOT call memcached_destroy_sasl_auth_data if you -specify your own callback function with memcached_set_sasl_callbacks(). +:c:type:`memcached_destroy_sasl_auth_data` before calling +:c:type:`memcached_free` to avoid a memory leak. You should NOT call +:c:type:`memcached_destroy_sasl_auth_data` if you specify your own callback +function with :c:func:`memcached_set_sasl_callbacks()`. -You as a client user have to initialize libsasl by using sasl_client_init -before enabling it in libmemcached, and you have to shut down libsasl by -calling sasl_done() when you are done using SASL from libmemcached. +You as a client user have to initialize libsasl by using :c:type:`sasl_client_init` before enabling it in libmemcached, and you have to shut down libsasl by +calling :c:func:`sasl_done()` when you are done using SASL from libmemcached. ------ @@ -51,9 +51,8 @@ RETURN ------ -memcached_get_sasl_callbacks() returns the callbacks currently used -by this memcached handle. -memcached_get_sasl_set_auth_data() returns MEMCACHED_SUCCESS upon success. +:c:func:`memcached_get_sasl_callbacks()` returns the callbacks currently used +by this memcached handle. :c:func:`memcached_get_sasl_set_auth_data()` returns :c:type:`MEMCACHED_SUCCESS` upon success. ---- diff --git a/docs/memcached_server_st.rst b/docs/memcached_server_st.rst index e7ec65c9..9a8c8fc2 100644 --- a/docs/memcached_server_st.rst +++ b/docs/memcached_server_st.rst @@ -36,30 +36,25 @@ DESCRIPTION libmemcached(3) operates on a list of hosts which are stored in -memcached_server_st structures. You should not modify these structures +:c:type:`memcached_server_st` structures. You should not modify these structures directly. Functions are provided to modify these structures (and more can be added, just ask!). -:c:func:`memcached_server_list()` is used to provide an array of all defined hosts. -This was incorrectly documented as "requiring free()" up till version 0.39. +:c:func:`memcached_server_list()` is used to provide an array of all defined hosts. This was incorrectly documented as "requiring free()" up till version 0.39. -:c:func:`memcached_server_list_free()` deallocates all memory associated with the array -of memcached_server_st that you passed to it. +:c:func:`memcached_server_list_free()` deallocates all memory associated with the array of :c:type:`memcached_server_st` that you passed to it. :c:func:`memcached_server_list_append()` adds a server to the end of a -memcached_server_st array. On error null will be returned and the -memcached_return_t pointer you passed into the function will be set with the -appropriate error. If the value of port is zero, it is set to the default +:c:type:`memcached_server_st` array. On error null will be returned and the +:c:type:`memcached_return_t` pointer you passed into the function will be set with the appropriate error. If the value of port is zero, it is set to the default port of a memcached server. DEPRECATED :c:func:`memcached_servers_parse()`, please see :c:func:`memcached()` -:c:func:`memcached_server_error()` can be used to look at the text of the last error -message sent by the server to to the client. +:c:func:`memcached_server_error()` can be used to look at the text of the last error message sent by the server to to the client. -Before version 0.39 these functions used a memcache_server_st \*. In 0.39 -memcached_server_st \* was aliased to :c:type:`memcached_server_list_st`. This was -done for a style reason/to help clean up some concepts in the code. +Before version 0.39 theses functions used a memcache_server_st \*. In 0.39 +memcached_server_st \* was aliased to :c:type:`memcached_server_list_st`. This was done for a style reason to help clean up some concepts in the code. ------ diff --git a/docs/memcached_servers.rst b/docs/memcached_servers.rst index e280071d..72da2764 100644 --- a/docs/memcached_servers.rst +++ b/docs/memcached_servers.rst @@ -38,52 +38,43 @@ DESCRIPTION :doc:`libmemcached` performs operations on a list of hosts. The order of these hosts determine routing to keys. Functions are provided to add keys to memcached_st structures. To manipulate lists of servers see -:c:type:`memcached_server_st()`. - -:c:func:`memcached_server_count()` provides you a count of the current -number of servers being used by a :c:type:`memcached_st` structure. - -:c:func:`memcached_server_add()` pushes a single TCP server into the -:c:type:`memcached_st` structure. This server will be placed at the end. -Duplicate servers are allowed, so duplication is not checked. Executing this -function with the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior set will -result in a :c:type:`MEMCACHED_INVALID_HOST_PROTOCOL`. - -:c:func:`memcached_server_add_udp()` pushes a single UDP server into the -:c:type:`memcached_st` structure. This server will be placed at the end. -Duplicate servers are allowed, so duplication is not checked. Executing this -function with out setting the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior -will result in a :c:type:`MEMCACHED_INVALID_HOST_PROTOCOL`. - -:c:func:`memcached_server_add_unix_socket()` pushes a single UNIX socket -into the :c:type:`memcached_st` structure. This UNIX socket will be placed -at the end. Duplicate servers are allowed, so duplication is not checked. -The length of the filename must be one character less then -:c:macro:`MEMCACHED_MAX_HOST_LENGTH`. - -:c:func:`memcached_server_push()` pushes an array of -:c:type:`memcached_server_st` into the :c:type:`memcached_st` structure. -These servers will be placed at the end. Duplicate servers are allowed, so -duplication is not checked. A copy is made of structure so the list provided -(and any operations on the list) are not saved. - -:c:func:`memcached_server_by_key()` allows you to provide a key and retrieve -the server which would be used for assignment. This structure is cloned from -its original structure and must be freed. If NULL is returned you should -consult \*error. The returning structure should be freed with +memcached_server_st(3). + +:c:func:`memcached_server_count()` provides you a count of the current number of +servers being used by a :c:type:`memcached_st` structure. + +:c:func:`memcached_server_add()` pushes a single TCP server into the :c:type:`memcached_st` structure. This server will be placed at the end. Duplicate servers + are allowed, so duplication is not checked. Executing this function with the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior set will result in a :c:type:`MEMCACHED_INVALID_HOST_PROTOCOL`. + +:c:func:`memcached_server_add_udp()` pushes a single UDP server into the :c:type:`memcached_st` structure. This server will be placed at the end. Duplicate +servers are allowed, so duplication is not checked. Executing this function with out setting the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior will result in a +:c:type:`MEMCACHED_INVALID_HOST_PROTOCOL`. + +:c:func:`memcached_server_add_unix_socket()` pushes a single UNIX socket into the :c:type:`memcached_st` structure. This UNIX socket will be placed at the end. +Duplicate servers are allowed, so duplication is not checked. The length +of the filename must be one character less than :c:type:`MEMCACHED_MAX_HOST_LENGTH`. + +:c:func:`memcached_server_push()` pushes an array of :c:type:`memcached_server_st` into the :c:type:`memcached_st` structure. These servers will be placed at +the end. Duplicate servers are allowed, so duplication is not checked. A +copy is made of structure so the list provided (and any operations on +the list) are not saved. + +:c:func:`memcached_server_by_key()` allows you to provide a key and retrieve the +server which would be used for assignment. This structure is cloned +from its original structure and must be freed. If NULL is returned you +should consult \*error. The returning structure should be freed with :c:func:`memcached_server_free()`. -:c:func:`memcached_server_get_last_disconnect()` returns a pointer to the -last server for which there was a connection problem. It does not mean this -particular server is currently dead but if the library is reporting a server +:c:func:`memcached_server_get_last_disconnect()` returns a pointer to the last +server for which there was a connection problem. It does not mean this +particular server is currently dead but if the library is reporting a server is, the returned server is a very good candidate. -:c:func:`memcached_server_cursor()` takes a memcached_st and loops through -the list of hosts currently in the cursor calling the list of callback -functions provided. You can optionally pass in a value via context which -will be provided to each callback function. An error return from any -callback will terminate the loop. :c:func:`memcached_server_cursor()` is -passed the original caller memcached_st in its current state. +:c:func:`memcached_server_cursor()` takes a memcached_st and loops through the +list of hosts currently in the cursor calling the list of callback +functions provided. You can optionally pass in a value via +context which will be provided to each callback function. An error +return from any callback will terminate the loop. :c:func:`memcached_server_cursor()` is passed the original caller :c:type:`memcached_st` in its current state. ------ diff --git a/docs/memcached_set.rst b/docs/memcached_set.rst index db668b22..29d8d241 100644 --- a/docs/memcached_set.rst +++ b/docs/memcached_set.rst @@ -32,55 +32,43 @@ DESCRIPTION ----------- -memcached_set(), memcached_add(), and memcached_replace() are all used to -store information on the server. All methods take a key, and its length to -store the object. Keys are currently limited to 250 characters when using either a version of memcached(1) which is 1.4 or below, or when using the text protocol. -You must supply both a value and a length. Optionally you -may test an expiration time for the object and a 16 byte value (it is -meant to be used as a bitmap). "flags" is a 4byte space that is stored alongside of the main value. Many sub libraries make use of this field, so in most cases users should avoid making use of it. - -memcached_set() will write an object to the server. If an object already -exists it will overwrite what is in the server. If the object does not exist -it will be written. If you are using the non-blocking mode this function +:c:func:`memcached_set()`, :c:func:`memcached_add()`, and :c:func:`memcached_replace()` are all used to store information on the server. All methods take a key, and its length to store the object. Keys are currently limited to 250 characters when using either a version of memcached(1) which is 1.4 or below, or when using the text protocol. You must supply both a value and a length. Optionally you +store the object. Keys are currently limited to 250 characters by the +memcached(1) server. You must supply both a value and a length. Optionally you +may test an expiration time for the object and a 16 byte value (it is meant to be used as a bitmap). "flags" is a 4byte space that is stored alongside of the main value. Many sub libraries make use of this field, so in most cases users should avoid making use of it. + +:c:func:`memcached_set()` will write an object to the server. If an object +already exists it will overwrite what is in the server. If the object does not +exist it will be written. If you are using the non-blocking mode this function will always return true unless a network error occurs. -memcached_replace() replaces an object on the server. If the object is not -found on the server an error occurs. +:c:func:`memcached_replace()` replaces an object on the server. If the object is not found on the server an error occurs. -memcached_add() adds an object to the server. If the object is found on the -server an error occurs, otherwise the value is stored. +:c:func:`memcached_add()` adds an object to the server. If the object is found on the server an error occurs, otherwise the value is stored. -memcached_cas() overwrites data in the server as long as the "cas" value is -still the same in the server. You can get the cas value of a result by -calling memcached_result_cas() on a memcached_result_st(3) structure. At the point +:c:func:`memcached_cas()` overwrites data in the server as long as the "cas" +value is still the same in the server. You can get the cas value of a result by +calling :c:func:`memcached_result_cas()` on a memcached_result_st(3) structure. At the point that this note was written cas is still buggy in memached. Turning on tests for it in libmemcached(3) is optional. Please see memcached_set() for information on how to do this. -memcached_set_by_key(), memcached_add_by_key(), and memcached_replace_by_key() -methods all behave in a similar method as the non key -methods. The difference is that they use their group_key parameter to map +:c:func:`memcached_set_by_key()`, :c:func:`memcached_add_by_key()`, and :c:func:`memcached_replace_by_key()` methods all behave in a similar method as the non +key methods. The difference is that they use their group_key parameter to map objects to particular servers. -If you are looking for performance, memcached_set() with non-blocking IO is -the fastest way to store data on the server. - -All of the above functions are testsed with the \ ``MEMCACHED_BEHAVIOR_USE_UDP``\ -behavior enabled. However, when using these operations with this behavior on, there -are limits to the size of the payload being sent to the server. The reason for -these limits is that the Memcached Server does not allow multi-datagram requests -and the current server implementation sets a datagram size to 1400 bytes. Due -to protocol overhead, the actual limit of the user supplied data is less than -1400 bytes and depends on the protocol in use as, well as the operation being -executed. When running with the binary protocol, \ `` MEMCACHED_BEHAVIOR_BINARY_PROTOCOL``\ , -the size of the key,value, flags and expiry combined may not exceed 1368 bytes. -When running with the ASCII protocol, the exact limit fluctuates depending on -which function is being executed and whether the function is a cas operation -or not. For non-cas ASCII set operations, there are at least 1335 bytes available -to split among the key, key_prefix, and value; for cas ASCII operations there are -at least 1318 bytes available to split among the key, key_prefix and value. If the -total size of the command, including overhead, exceeds 1400 bytes, a \ ``MEMCACHED_WRITE_FAILURE``\ -will be returned. +If you are looking for performance, :c:func:`memcached_set()` with non-blocking IO is the fastest way to store data on the server. + +All of the above functions are testsed with the :c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior enabled. However, when using these operations with this behavior +on, there are limits to the size of the payload being sent to the server. +The reason for these limits is that the Memcached Server does not allow +multi-datagram requests and the current server implementation sets a datagram +size to 1400 bytes. Due to protocol overhead, the actual limit of the user supplied data is less than 1400 bytes and depends on the protocol in use as, well as the operation being +executed. When running with the binary protocol, :c:type:`MEMCACHED_BEHAVIOR_BINARY_PROTOCOL`, the size of the key,value, flags and expiry combined may not +exceed 1368 bytes. When running with the ASCII protocol, the exact limit fluctuates depending on which function is being executed and whether the function is a cas operation or not. For non-cas ASCII set operations, there are at least +1335 bytes available to split among the key, key_prefix, and value; for cas +ASCII operations there are at least 1318 bytes available to split among the key, key_prefix and value. If the total size of the command, including overhead, +exceeds 1400 bytes, a :c:type:`MEMCACHED_WRITE_FAILURE` will be returned. ------ @@ -88,12 +76,11 @@ RETURN ------ -All methods return a value of type \ ``memcached_return_t``\ . -On success the value will be \ ``MEMCACHED_SUCCESS``\ . -Use memcached_strerror() to translate this value to a printable string. +All methods return a value of type :c:type:`memcached_return_t`. +On success the value will be :c:type:`MEMCACHED_SUCCESS`. +Use :c:func:`memcached_strerror()` to translate this value to a printable string. -For memcached_replace() and memcached_add(), \ ``MEMCACHED_NOTSTORED``\ is a -legitmate error in the case of a collision. +For :c:func:`memcached_replace()` and :c:func:`memcached_add()`, :c:type:`MEMCACHED_NOTSTORED` is a legitmate error in the case of a collision. ---- @@ -110,5 +97,5 @@ SEE ALSO -------- -memcached(1) libmemached(3) memcached_strerror(3) memcached_prepend(3) memcached_cas(3) memcached_append(3) +:manpage:`memcached(1)` :manpage:`libmemached(3)` :manpage:`memcached_strerror(3)` :manpage:`memcached_prepend(3)` :manpage:`memcached_cas(3)` :manpage:`memcached_append(3)` diff --git a/docs/memcached_stats.rst b/docs/memcached_stats.rst index 56cce256..2cd36b6b 100644 --- a/docs/memcached_stats.rst +++ b/docs/memcached_stats.rst @@ -33,34 +33,20 @@ DESCRIPTION libmemcached(3) has the ability to query a memcached server (or collection of servers) for their current state. Queries to find state return a -\ ``memcached_stat_st``\ structure. You are responsible for freeing this structure. -While it is possible to access the structure directly it is not advisable. -`_ - - ------- -AUTHOR ------- - - -Trond Norbye, - - --------- -SEE ALSO --------- - -:manpage:`memcached(1)` :manpage:`libmemcached(3)` - diff --git a/docs/memcat.rst b/docs/memcat.rst deleted file mode 100644 index 8fa8268a..00000000 --- a/docs/memcat.rst +++ /dev/null @@ -1,62 +0,0 @@ -================================= -memcat - "cat" data from a server -================================= - - -Copy a set of keys to stdout - - --------- -SYNOPSIS --------- - - -:program:`memcat` - -.. program:: memcat - -.. option:: --help - - ------------ -DESCRIPTION ------------ - - -\ **memcat**\ outputs to stdout the value a single or multiple set of keys -stored in a memcached(1) server. If any key is not found an error is returned. - -It is similar to the standard UNIX cat(1) utility. - -You can specify servers via the \ **--servers**\ option or via the -environment variable \ ``MEMCACHED_SERVERS``\ . - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - ------- -AUTHOR ------- - - -Brian Aker, - -Mark Atwood - - --------- -SEE ALSO --------- - - -memcached(1) libmemcached(3) - diff --git a/docs/memcp.rst b/docs/memcp.rst deleted file mode 100644 index 7e620cca..00000000 --- a/docs/memcp.rst +++ /dev/null @@ -1,63 +0,0 @@ -============================= -memcp - Copy data to a server -============================= - - -Copies files to a collection of memcached servers - - --------- -SYNOPSIS --------- - -:program: `memcp` - -.. program:: memcp - -.. option:: --help - - ------------ -DESCRIPTION ------------ - - -\ **memcp**\ copies one or more files into memcached(1) servers. -It is similar to the standard UNIX cp(1) command. - -The key names will be the names of the files, -without any directory path. - -You can specify servers via the \ **--servers**\ option or via the -environment variable \ ``MEMCACHED_SERVERS``\. If you do not specify either these, the final value in the command line list is the name of a -server(s). - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - ------- -AUTHOR ------- - - -Brian Aker, - -Mark Atwood, - - --------- -SEE ALSO --------- - - -memcached(1) libmemcached(3) - diff --git a/docs/memdump.rst b/docs/memdump.rst deleted file mode 100644 index fbdb8c1c..00000000 --- a/docs/memdump.rst +++ /dev/null @@ -1,44 +0,0 @@ -============================= -memdump - Dumping your server -============================= - - -Dump a list of keys from a server. - - --------- -SYNOPSIS --------- - -:program: `memdump` - -.. program:: memdump - -.. option:: --help - ------------ -DESCRIPTION ------------ - - -\ **memdump**\ dumps a list of "keys" from all servers that -it is told to fetch from. Because memcached does not guarentee to -provide all keys it is not possible to get a complete "dump". - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - --------- -SEE ALSO --------- - -:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/memerror.rst b/docs/memerror.rst deleted file mode 100644 index 16ee6147..00000000 --- a/docs/memerror.rst +++ /dev/null @@ -1,45 +0,0 @@ -============================================== -memerror - translate an error code to a string -============================================== - - -Translates a memcached error code into a string - - --------- -SYNOPSIS --------- - -:program: `memerror` - -.. program:: memerror - -.. option:: --help - ------------ -DESCRIPTION ------------ - - -\ **memerror**\ translate an error code from libmemcached(3) into a human -readable string. - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more infoerroration please check: -`http://libmemcached.org/ `_ - - --------- -SEE ALSO --------- - - -memcached(1) libmemcached(3) - diff --git a/docs/memflush.rst b/docs/memflush.rst deleted file mode 100644 index e02969bd..00000000 --- a/docs/memflush.rst +++ /dev/null @@ -1,56 +0,0 @@ -======================================= -memflush - flush all data from a server -======================================= - - -Reset a server or list of servers - - --------- -SYNOPSIS --------- - -:program: `memflush` - -.. program:: memflush - -.. option:: --help - ------------ -DESCRIPTION ------------ - - -\ **memflush**\ resets the contents of memcached(1) servers. -This means that all data in the specified servers will be deleted. - -You can specify servers via the \ **--servers**\ option or via the -environment variable \ ``MEMCACHED_SERVERS``\ . - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - ------- -AUTHOR ------- - - -Brian Aker, - -Mark Atwood - - --------- -SEE ALSO --------- - -memcached(1) libmemcached(3) diff --git a/docs/memrm.rst b/docs/memrm.rst deleted file mode 100644 index 4dad9f75..00000000 --- a/docs/memrm.rst +++ /dev/null @@ -1,59 +0,0 @@ -================================= -memrm - Remove data from a server -================================= - - -memrm - Remove a key(s) from a collection of memcached servers - - --------- -SYNOPSIS --------- - -:program: `memrm` - -.. program:: memrm - -.. option:: --help - - - ------------ -DESCRIPTION ------------ - - -\ **memrm**\ removes items, specified by key, from memcached(1) servers. - -You can specify servers via the \ **--servers**\ option or via the -environment variable \ ``MEMCACHED_SERVERS``\ . - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - ------- -AUTHOR ------- - - -Brian Aker, - -Mark Atwood, - - --------- -SEE ALSO --------- - - -memcached(1) libmemcached(3) - diff --git a/docs/memslap.rst b/docs/memslap.rst deleted file mode 100644 index 1996b99f..00000000 --- a/docs/memslap.rst +++ /dev/null @@ -1,33 +0,0 @@ -================================================= -memslap - Load testing and benchmarking a server -================================================= - - --------- -SYNOPSIS --------- - - -:program: `memslap` - -.. program:: memslap - -.. option:: --help - ------------ -DESCRIPTION ------------ - - -\ **memslap**\ 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. - -You can specify servers via the \ **--servers**\ option or via the environment variable \ ``MEMCACHED_SERVERS``\ . - - --------- -SEE ALSO --------- - - -:manpage:`memcached(1)` :manpage:`libmemcached(3)` diff --git a/docs/memstat.rst b/docs/memstat.rst deleted file mode 100644 index e5aa0e06..00000000 --- a/docs/memstat.rst +++ /dev/null @@ -1,50 +0,0 @@ -========================================= -memstat - Gather statistics from a server -========================================= - - -memstat - Display the operating status of a single or group of memcached servers - - --------- -SYNOPSIS --------- - -:program: `memstat` - -.. program:: memstat - -.. option:: --help - ------------ -DESCRIPTION ------------ - - -\ **memstat**\ dumps the state of memcached(1) servers. -It displays all data to stdout. - -You can specify servers via the \ **--servers**\ option or via the -environment variable \ ``MEMCACHED_SERVERS``\ . \ **--args**\ can be used -to specify the "argument" sent to the stats command (ie slab, size, items, -etc..). - -For a full list of operations run the tool with the \ **--help**\ option. - - ----- -HOME ----- - - -To find out more information please check: -`http://libmemcached.org/ `_ - - --------- -SEE ALSO --------- - - -memcached(1) libmemcached(3) - diff --git a/libmemcached/behavior.cc b/libmemcached/behavior.cc index 6546efba..60aa6b17 100644 --- a/libmemcached/behavior.cc +++ b/libmemcached/behavior.cc @@ -36,6 +36,7 @@ */ #include +#include #include #include diff --git a/libmemcached/connect.cc b/libmemcached/connect.cc index 77cfb3bd..5e6c77f5 100644 --- a/libmemcached/connect.cc +++ b/libmemcached/connect.cc @@ -49,18 +49,14 @@ static memcached_return_t connect_poll(memcached_server_st *ptr) size_t loop_max= 5; - while (--loop_max) // Should only loop on cases of ERESTART or EINTR + if (ptr->root->poll_timeout == 0) { - int error; - if (ptr->root->poll_timeout) - { - error= poll(fds, 1, ptr->root->connect_timeout); - } - else - { - error= 0; - } + return memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT); + } + while (--loop_max) // Should only loop on cases of ERESTART or EINTR + { + int error= poll(fds, 1, ptr->root->connect_timeout); switch (error) { case 1: diff --git a/libmemcached/hosts.cc b/libmemcached/hosts.cc index 11b31630..32bf8ce3 100644 --- a/libmemcached/hosts.cc +++ b/libmemcached/hosts.cc @@ -186,7 +186,7 @@ static memcached_return_t update_continuum(memcached_st *ptr) memcached_continuum_item_st *new_ptr; new_ptr= static_cast(libmemcached_realloc(ptr, ptr->ketama.continuum, - sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server)); + sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server)); if (new_ptr == 0) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; diff --git a/libmemcached/include.am b/libmemcached/include.am index bd07da6d..e799093f 100644 --- a/libmemcached/include.am +++ b/libmemcached/include.am @@ -22,6 +22,7 @@ noinst_HEADERS+= \ libmemcached/is.h \ libmemcached/libmemcached_probes.h \ libmemcached/memory.h \ + libmemcached/options.hpp \ libmemcached/protocol/ascii_handler.h \ libmemcached/protocol/binary_handler.h \ libmemcached/protocol/common.h \ diff --git a/libmemcached/io.cc b/libmemcached/io.cc index 6594aa75..a787b0c2 100644 --- a/libmemcached/io.cc +++ b/libmemcached/io.cc @@ -57,8 +57,6 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, fds.fd= ptr->fd; fds.events= POLLIN; - int error; - if (read_or_write == MEM_WRITE) /* write */ { fds.events= POLLOUT; @@ -86,18 +84,16 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, } } + if (ptr->root->poll_timeout == 0) // Mimic 0 causes timeout behavior (not all platforms do this) + { + return memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT); + } + size_t loop_max= 5; while (--loop_max) // While loop is for ERESTART or EINTR { - if (ptr->root->poll_timeout) // Mimic 0 causes timeout behavior (not all platforms do this) - { - error= poll(&fds, 1, ptr->root->poll_timeout); - } - else - { - error= 0; - } + int error= poll(&fds, 1, ptr->root->poll_timeout); switch (error) { case 1: // Success! @@ -145,8 +141,6 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr, } } - /* Imposssible for anything other then -1 */ - WATCHPOINT_ASSERT(error == -1); ptr->cached_errno= get_socket_errno(); memcached_quit_server(ptr, true); @@ -619,7 +613,8 @@ memcached_server_write_instance_st memcached_io_get_readable_server(memcached_st return NULL; } - switch (poll(fds, host_index, memc->poll_timeout)) + int error= poll(fds, host_index, memc->poll_timeout); + switch (error) { case -1: memcached_set_errno(*memc, get_socket_errno(), MEMCACHED_AT); diff --git a/libmemcached/memcached.cc b/libmemcached/memcached.cc index ee95eaa1..f93f74b4 100644 --- a/libmemcached/memcached.cc +++ b/libmemcached/memcached.cc @@ -36,6 +36,8 @@ */ #include + +#include #include #if 0 @@ -238,7 +240,7 @@ memcached_st *memcached(const char *string, size_t length) if (memcached_success(rc) and memcached_parse_filename(self)) { - rc= memcached_parse_configure_file(self, memcached_parse_filename(self), memcached_parse_filename_length(self)); + rc= memcached_parse_configure_file(*self, memcached_parse_filename(self), memcached_parse_filename_length(self)); } if (memcached_failed(rc)) @@ -266,7 +268,7 @@ memcached_return_t memcached_reset(memcached_st *ptr) if (ptr->configure.filename) { - return memcached_parse_configure_file(ptr, memcached_param_array(ptr->configure.filename)); + return memcached_parse_configure_file(*ptr, memcached_param_array(ptr->configure.filename)); } return MEMCACHED_SUCCESS; diff --git a/libmemcached/memcached.hpp b/libmemcached/memcached.hpp index 0b27291b..58fff4df 100644 --- a/libmemcached/memcached.hpp +++ b/libmemcached/memcached.hpp @@ -117,7 +117,17 @@ public: */ bool configure(const std::string &configuration) { - return memcached_success(memcached_parse_configuration(memc, configuration.c_str(), configuration.size())); + memcached_st *new_memc= memcached(configuration.c_str(), configuration.size()); + + if (new_memc) + { + memcached_free(memc); + memc= new_memc; + + return true; + } + + return false; } /** diff --git a/libmemcached/options.cc b/libmemcached/options.cc index 16f378e8..c1e591d8 100644 --- a/libmemcached/options.cc +++ b/libmemcached/options.cc @@ -36,7 +36,9 @@ */ #include -#include +#include + +#include #include @@ -51,13 +53,13 @@ size_t memcached_parse_filename_length(memcached_st *memc) return memcached_array_size(memc->configure.filename); } -static memcached_return_t _parse_file_options(memcached_st *self, memcached_array_st *real_name) +static memcached_return_t _parse_file_options(memcached_st& self, memcached_array_st *real_name) { FILE *fp= fopen(memcached_array_string(real_name), "r"); if (not fp) { memcached_string_t error_message= memcached_array_to_string(real_name); - memcached_return_t rc= memcached_set_errno(*self, errno, MEMCACHED_AT, error_message); + memcached_return_t rc= memcached_set_errno(self, errno, MEMCACHED_AT, error_message); return rc; } @@ -70,7 +72,7 @@ static memcached_return_t _parse_file_options(memcached_st *self, memcached_arra if (length == 1 and buffer[0] == '\n') continue; - if (memcached_failed(rc= memcached_parse_configuration(self, buffer, length))) + if (memcached_failed(rc= memcached_parse_configuration(&self, buffer, length))) break; } fclose(fp); @@ -101,7 +103,7 @@ memcached_return_t libmemcached_check_configuration(const char *option_string, s assert(memcached_parse_filename(memc_ptr)); assert(memcached_parse_filename_length(memc_ptr)); memcached_string_t filename= memcached_array_to_string(memc_ptr->configure.filename); - rc= _parse_file_options(memc_ptr, memc_ptr->configure.filename); + rc= _parse_file_options(*memc_ptr, memc_ptr->configure.filename); if (memcached_failed(rc) and error_buffer && error_buffer_size) { @@ -138,47 +140,39 @@ void memcached_set_configuration_file(memcached_st *self, const char *filename, self->configure.filename= memcached_strcpy(self, filename, filename_length); } -memcached_return_t memcached_parse_configure_file(memcached_st *self, const char *filename, size_t length) +memcached_return_t memcached_parse_configure_file(memcached_st& self, const char *filename, size_t length) { - WATCHPOINT_ASSERT(self); - if (not self) - { - return MEMCACHED_INVALID_ARGUMENTS; - } - - WATCHPOINT_ASSERT(self); if (not filename) { - return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT); + return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT); } WATCHPOINT_ASSERT(self); if (not length) { - return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT); + return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT); } - memcached_array_st *tmp_array= memcached_strcpy(self, filename, length); + memcached_array_st *tmp_array= memcached_strcpy(&self, filename, length); - memcached_return_t rc= memcached_parse_configure_file(self, tmp_array); + if (not tmp_array) + { + return memcached_set_error(self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT); + } + + memcached_return_t rc= memcached_parse_configure_file(self, *tmp_array); memcached_array_free(tmp_array); return rc; } -memcached_return_t memcached_parse_configure_file(memcached_st *self, memcached_array_st *filename) +memcached_return_t memcached_parse_configure_file(memcached_st& self, memcached_array_st& filename) { - WATCHPOINT_ASSERT(self); - if (not self) - { - return MEMCACHED_INVALID_ARGUMENTS; - } - - WATCHPOINT_ASSERT(memcached_array_size(filename)); - if (not memcached_array_size(filename)) + WATCHPOINT_ASSERT(memcached_array_size(&filename)); + if (not memcached_array_size(&filename)) { - return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT); + return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT); } - return _parse_file_options(self, filename); + return _parse_file_options(self, &filename); } diff --git a/libmemcached/options.h b/libmemcached/options.h index 893da2ac..f5a6e06d 100644 --- a/libmemcached/options.h +++ b/libmemcached/options.h @@ -44,28 +44,6 @@ extern "C" { LIBMEMCACHED_API memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size); -LIBMEMCACHED_LOCAL - void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length); - -LIBMEMCACHED_LOCAL - memcached_return_t memcached_parse_configuration(memcached_st *ptr, const char *option_string, size_t length); - -LIBMEMCACHED_LOCAL - const char *memcached_parse_filename(memcached_st *memc); - -LIBMEMCACHED_LOCAL - size_t memcached_parse_filename_length(memcached_st *memc); - #ifdef __cplusplus } #endif - -#ifdef __cplusplus - -LIBMEMCACHED_LOCAL - memcached_return_t memcached_parse_configure_file(memcached_st *self, const char *filename, size_t length); - -LIBMEMCACHED_LOCAL - memcached_return_t memcached_parse_configure_file(memcached_st *self, memcached_array_st *filename); - -#endif diff --git a/libmemcached/options.hpp b/libmemcached/options.hpp new file mode 100644 index 00000000..bc717322 --- /dev/null +++ b/libmemcached/options.hpp @@ -0,0 +1,56 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * 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. + * + */ + +#pragma once + +LIBMEMCACHED_LOCAL + void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length); + +LIBMEMCACHED_LOCAL + const char *memcached_parse_filename(memcached_st *memc); + +LIBMEMCACHED_LOCAL + memcached_return_t memcached_parse_configuration(memcached_st *ptr, const char *option_string, size_t length); + +LIBMEMCACHED_LOCAL + size_t memcached_parse_filename_length(memcached_st *memc); + +LIBMEMCACHED_LOCAL + memcached_return_t memcached_parse_configure_file(memcached_st&, const char *filename, size_t length); + +LIBMEMCACHED_LOCAL + memcached_return_t memcached_parse_configure_file(memcached_st&, memcached_array_st& filename); diff --git a/libmemcached/options/parser.cc b/libmemcached/options/parser.cc index d199a5fa..2e478dcc 100644 --- a/libmemcached/options/parser.cc +++ b/libmemcached/options/parser.cc @@ -83,6 +83,8 @@ #include #include +#include + #include #include #include @@ -102,7 +104,7 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error) /* Line 189 of yacc.c */ -#line 106 "libmemcached/options/parser.cc" +#line 108 "libmemcached/options/parser.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -213,7 +215,7 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error) /* Line 264 of yacc.c */ -#line 217 "libmemcached/options/parser.cc" +#line 219 "libmemcached/options/parser.cc" #ifdef short # undef short @@ -522,13 +524,13 @@ static const yytype_int8 yyrhs[] = /* 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, 205, 213, 217, 221, 225, 229, 236, - 243, 254, 261, 268, 275, 281, 285, 289, 293, 297, - 301, 305, 309, 313, 317, 321, 325, 332, 336, 340, - 344, 348, 352, 356, 360, 364, 368, 372, 376, 383, - 384, 389, 390, 395, 399, 403, 407, 411, 415, 419, - 423, 427, 434, 438, 446, 450, 454 + 0, 159, 159, 160, 164, 166, 168, 170, 175, 180, + 184, 188, 199, 207, 215, 219, 223, 227, 231, 238, + 245, 256, 263, 270, 277, 283, 287, 291, 295, 299, + 303, 307, 311, 315, 319, 323, 327, 334, 338, 342, + 346, 350, 354, 358, 362, 366, 370, 374, 378, 385, + 386, 391, 392, 397, 401, 405, 409, 413, 417, 421, + 425, 429, 436, 440, 448, 452, 456 }; #endif @@ -1520,28 +1522,28 @@ yyreduce: case 4: /* Line 1464 of yacc.c */ -#line 163 "libmemcached/options/parser.yy" +#line 165 "libmemcached/options/parser.yy" { ;} break; case 5: /* Line 1464 of yacc.c */ -#line 165 "libmemcached/options/parser.yy" +#line 167 "libmemcached/options/parser.yy" { ;} break; case 6: /* Line 1464 of yacc.c */ -#line 167 "libmemcached/options/parser.yy" +#line 169 "libmemcached/options/parser.yy" { ;} break; case 7: /* Line 1464 of yacc.c */ -#line 169 "libmemcached/options/parser.yy" +#line 171 "libmemcached/options/parser.yy" { context->set_end(); YYACCEPT; @@ -1551,7 +1553,7 @@ yyreduce: case 8: /* Line 1464 of yacc.c */ -#line 174 "libmemcached/options/parser.yy" +#line 176 "libmemcached/options/parser.yy" { context->rc= MEMCACHED_PARSE_USER_ERROR; parser_abort(context, NULL); @@ -1561,7 +1563,7 @@ yyreduce: case 9: /* Line 1464 of yacc.c */ -#line 179 "libmemcached/options/parser.yy" +#line 181 "libmemcached/options/parser.yy" { memcached_reset(context->memc); ;} @@ -1570,7 +1572,7 @@ yyreduce: case 10: /* Line 1464 of yacc.c */ -#line 183 "libmemcached/options/parser.yy" +#line 185 "libmemcached/options/parser.yy" { yydebug= 1; ;} @@ -1579,9 +1581,9 @@ yyreduce: case 11: /* Line 1464 of yacc.c */ -#line 187 "libmemcached/options/parser.yy" +#line 189 "libmemcached/options/parser.yy" { - if ((context->rc= memcached_parse_configure_file(context->memc, (yyvsp[(3) - (3)].string).c_str, (yyvsp[(3) - (3)].string).size)) != MEMCACHED_SUCCESS) + if ((context->rc= memcached_parse_configure_file(*context->memc, (yyvsp[(3) - (3)].string).c_str, (yyvsp[(3) - (3)].string).size)) != MEMCACHED_SUCCESS) { parser_abort(context, NULL); } @@ -1591,7 +1593,7 @@ yyreduce: case 12: /* Line 1464 of yacc.c */ -#line 198 "libmemcached/options/parser.yy" +#line 200 "libmemcached/options/parser.yy" { if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, (yyvsp[(2) - (4)].server).c_str, (yyvsp[(3) - (4)].number), (yyvsp[(4) - (4)].number)))) { @@ -1604,7 +1606,7 @@ yyreduce: case 13: /* Line 1464 of yacc.c */ -#line 206 "libmemcached/options/parser.yy" +#line 208 "libmemcached/options/parser.yy" { if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, (yyvsp[(2) - (4)].server).c_str, (yyvsp[(3) - (4)].number), (yyvsp[(4) - (4)].number)))) { @@ -1617,7 +1619,7 @@ yyreduce: case 14: /* Line 1464 of yacc.c */ -#line 214 "libmemcached/options/parser.yy" +#line 216 "libmemcached/options/parser.yy" { memcached_set_configuration_file(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size); ;} @@ -1626,7 +1628,7 @@ yyreduce: case 15: /* Line 1464 of yacc.c */ -#line 218 "libmemcached/options/parser.yy" +#line 220 "libmemcached/options/parser.yy" { context->memc->configure.initial_pool_size= (yyvsp[(2) - (2)].number); ;} @@ -1635,7 +1637,7 @@ yyreduce: case 16: /* Line 1464 of yacc.c */ -#line 222 "libmemcached/options/parser.yy" +#line 224 "libmemcached/options/parser.yy" { context->memc->configure.max_pool_size= (yyvsp[(2) - (2)].number); ;} @@ -1644,7 +1646,7 @@ yyreduce: case 18: /* Line 1464 of yacc.c */ -#line 230 "libmemcached/options/parser.yy" +#line 232 "libmemcached/options/parser.yy" { if ((context->rc= memcached_set_prefix_key(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size)) != MEMCACHED_SUCCESS) { @@ -1656,7 +1658,7 @@ yyreduce: case 19: /* Line 1464 of yacc.c */ -#line 237 "libmemcached/options/parser.yy" +#line 239 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, (yyvsp[(2) - (2)].distribution))) != MEMCACHED_SUCCESS) { @@ -1668,7 +1670,7 @@ yyreduce: case 20: /* Line 1464 of yacc.c */ -#line 244 "libmemcached/options/parser.yy" +#line 246 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, (yyvsp[(2) - (4)].distribution))) != MEMCACHED_SUCCESS) { @@ -1684,7 +1686,7 @@ yyreduce: case 21: /* Line 1464 of yacc.c */ -#line 255 "libmemcached/options/parser.yy" +#line 257 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_HASH, (yyvsp[(2) - (2)].hash))) != MEMCACHED_SUCCESS) { @@ -1696,7 +1698,7 @@ yyreduce: case 22: /* Line 1464 of yacc.c */ -#line 262 "libmemcached/options/parser.yy" +#line 264 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, (yyvsp[(1) - (2)].behavior), (yyvsp[(2) - (2)].number))) != MEMCACHED_SUCCESS) { @@ -1708,7 +1710,7 @@ yyreduce: case 23: /* Line 1464 of yacc.c */ -#line 269 "libmemcached/options/parser.yy" +#line 271 "libmemcached/options/parser.yy" { if ((context->rc= memcached_behavior_set(context->memc, (yyvsp[(1) - (1)].behavior), true)) != MEMCACHED_SUCCESS) { @@ -1720,7 +1722,7 @@ yyreduce: case 24: /* Line 1464 of yacc.c */ -#line 276 "libmemcached/options/parser.yy" +#line 278 "libmemcached/options/parser.yy" { ;} break; @@ -1728,7 +1730,7 @@ yyreduce: case 25: /* Line 1464 of yacc.c */ -#line 282 "libmemcached/options/parser.yy" +#line 284 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS; ;} @@ -1737,7 +1739,7 @@ yyreduce: case 26: /* Line 1464 of yacc.c */ -#line 286 "libmemcached/options/parser.yy" +#line 288 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT; ;} @@ -1746,7 +1748,7 @@ yyreduce: case 27: /* Line 1464 of yacc.c */ -#line 290 "libmemcached/options/parser.yy" +#line 292 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK; ;} @@ -1755,7 +1757,7 @@ yyreduce: case 28: /* Line 1464 of yacc.c */ -#line 294 "libmemcached/options/parser.yy" +#line 296 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK; ;} @@ -1764,7 +1766,7 @@ yyreduce: case 29: /* Line 1464 of yacc.c */ -#line 298 "libmemcached/options/parser.yy" +#line 300 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH; ;} @@ -1773,7 +1775,7 @@ yyreduce: case 30: /* Line 1464 of yacc.c */ -#line 302 "libmemcached/options/parser.yy" +#line 304 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS; ;} @@ -1782,7 +1784,7 @@ yyreduce: case 31: /* Line 1464 of yacc.c */ -#line 306 "libmemcached/options/parser.yy" +#line 308 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_POLL_TIMEOUT; ;} @@ -1791,7 +1793,7 @@ yyreduce: case 32: /* Line 1464 of yacc.c */ -#line 310 "libmemcached/options/parser.yy" +#line 312 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_RCV_TIMEOUT; ;} @@ -1800,7 +1802,7 @@ yyreduce: case 33: /* Line 1464 of yacc.c */ -#line 314 "libmemcached/options/parser.yy" +#line 316 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT; ;} @@ -1809,7 +1811,7 @@ yyreduce: case 34: /* Line 1464 of yacc.c */ -#line 318 "libmemcached/options/parser.yy" +#line 320 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SND_TIMEOUT; ;} @@ -1818,7 +1820,7 @@ yyreduce: case 35: /* Line 1464 of yacc.c */ -#line 322 "libmemcached/options/parser.yy" +#line 324 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE; ;} @@ -1827,7 +1829,7 @@ yyreduce: case 36: /* Line 1464 of yacc.c */ -#line 326 "libmemcached/options/parser.yy" +#line 328 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE; ;} @@ -1836,7 +1838,7 @@ yyreduce: case 37: /* Line 1464 of yacc.c */ -#line 333 "libmemcached/options/parser.yy" +#line 335 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL; ;} @@ -1845,7 +1847,7 @@ yyreduce: case 38: /* Line 1464 of yacc.c */ -#line 337 "libmemcached/options/parser.yy" +#line 339 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS; ;} @@ -1854,7 +1856,7 @@ yyreduce: case 39: /* Line 1464 of yacc.c */ -#line 341 "libmemcached/options/parser.yy" +#line 343 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY; ;} @@ -1863,7 +1865,7 @@ yyreduce: case 40: /* Line 1464 of yacc.c */ -#line 345 "libmemcached/options/parser.yy" +#line 347 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_NOREPLY; ;} @@ -1872,7 +1874,7 @@ yyreduce: case 41: /* Line 1464 of yacc.c */ -#line 349 "libmemcached/options/parser.yy" +#line 351 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ; ;} @@ -1881,7 +1883,7 @@ yyreduce: case 42: /* Line 1464 of yacc.c */ -#line 353 "libmemcached/options/parser.yy" +#line 355 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SORT_HOSTS; ;} @@ -1890,7 +1892,7 @@ yyreduce: case 43: /* Line 1464 of yacc.c */ -#line 357 "libmemcached/options/parser.yy" +#line 359 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_SUPPORT_CAS; ;} @@ -1899,7 +1901,7 @@ yyreduce: case 44: /* Line 1464 of yacc.c */ -#line 361 "libmemcached/options/parser.yy" +#line 363 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_NODELAY; ;} @@ -1908,7 +1910,7 @@ yyreduce: case 45: /* Line 1464 of yacc.c */ -#line 365 "libmemcached/options/parser.yy" +#line 367 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE; ;} @@ -1917,7 +1919,7 @@ yyreduce: case 46: /* Line 1464 of yacc.c */ -#line 369 "libmemcached/options/parser.yy" +#line 371 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE; ;} @@ -1926,7 +1928,7 @@ yyreduce: case 47: /* Line 1464 of yacc.c */ -#line 373 "libmemcached/options/parser.yy" +#line 375 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_USE_UDP; ;} @@ -1935,7 +1937,7 @@ yyreduce: case 48: /* Line 1464 of yacc.c */ -#line 377 "libmemcached/options/parser.yy" +#line 379 "libmemcached/options/parser.yy" { (yyval.behavior)= MEMCACHED_BEHAVIOR_VERIFY_KEY; ;} @@ -1944,35 +1946,35 @@ yyreduce: case 49: /* Line 1464 of yacc.c */ -#line 383 "libmemcached/options/parser.yy" +#line 385 "libmemcached/options/parser.yy" { (yyval.number)= MEMCACHED_DEFAULT_PORT;;} break; case 50: /* Line 1464 of yacc.c */ -#line 385 "libmemcached/options/parser.yy" +#line 387 "libmemcached/options/parser.yy" { ;} break; case 51: /* Line 1464 of yacc.c */ -#line 389 "libmemcached/options/parser.yy" +#line 391 "libmemcached/options/parser.yy" { (yyval.number)= 1; ;} break; case 52: /* Line 1464 of yacc.c */ -#line 391 "libmemcached/options/parser.yy" +#line 393 "libmemcached/options/parser.yy" { ;} break; case 53: /* Line 1464 of yacc.c */ -#line 396 "libmemcached/options/parser.yy" +#line 398 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_MD5; ;} @@ -1981,7 +1983,7 @@ yyreduce: case 54: /* Line 1464 of yacc.c */ -#line 400 "libmemcached/options/parser.yy" +#line 402 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_CRC; ;} @@ -1990,7 +1992,7 @@ yyreduce: case 55: /* Line 1464 of yacc.c */ -#line 404 "libmemcached/options/parser.yy" +#line 406 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1_64; ;} @@ -1999,7 +2001,7 @@ yyreduce: case 56: /* Line 1464 of yacc.c */ -#line 408 "libmemcached/options/parser.yy" +#line 410 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1A_64; ;} @@ -2008,7 +2010,7 @@ yyreduce: case 57: /* Line 1464 of yacc.c */ -#line 412 "libmemcached/options/parser.yy" +#line 414 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1_32; ;} @@ -2017,7 +2019,7 @@ yyreduce: case 58: /* Line 1464 of yacc.c */ -#line 416 "libmemcached/options/parser.yy" +#line 418 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_FNV1A_32; ;} @@ -2026,7 +2028,7 @@ yyreduce: case 59: /* Line 1464 of yacc.c */ -#line 420 "libmemcached/options/parser.yy" +#line 422 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_HSIEH; ;} @@ -2035,7 +2037,7 @@ yyreduce: case 60: /* Line 1464 of yacc.c */ -#line 424 "libmemcached/options/parser.yy" +#line 426 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_MURMUR; ;} @@ -2044,7 +2046,7 @@ yyreduce: case 61: /* Line 1464 of yacc.c */ -#line 428 "libmemcached/options/parser.yy" +#line 430 "libmemcached/options/parser.yy" { (yyval.hash)= MEMCACHED_HASH_JENKINS; ;} @@ -2053,7 +2055,7 @@ yyreduce: case 62: /* Line 1464 of yacc.c */ -#line 435 "libmemcached/options/parser.yy" +#line 437 "libmemcached/options/parser.yy" { (yyval.string)= (yyvsp[(1) - (1)].string); ;} @@ -2062,7 +2064,7 @@ yyreduce: case 63: /* Line 1464 of yacc.c */ -#line 439 "libmemcached/options/parser.yy" +#line 441 "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).size= (yyvsp[(1) - (1)].string).size -2; // -2 removes the begin and end quote @@ -2072,7 +2074,7 @@ yyreduce: case 64: /* Line 1464 of yacc.c */ -#line 447 "libmemcached/options/parser.yy" +#line 449 "libmemcached/options/parser.yy" { (yyval.distribution)= MEMCACHED_DISTRIBUTION_CONSISTENT; ;} @@ -2081,7 +2083,7 @@ yyreduce: case 65: /* Line 1464 of yacc.c */ -#line 451 "libmemcached/options/parser.yy" +#line 453 "libmemcached/options/parser.yy" { (yyval.distribution)= MEMCACHED_DISTRIBUTION_MODULA; ;} @@ -2090,7 +2092,7 @@ yyreduce: case 66: /* Line 1464 of yacc.c */ -#line 455 "libmemcached/options/parser.yy" +#line 457 "libmemcached/options/parser.yy" { (yyval.distribution)= MEMCACHED_DISTRIBUTION_RANDOM; ;} @@ -2099,7 +2101,7 @@ yyreduce: /* Line 1464 of yacc.c */ -#line 2103 "libmemcached/options/parser.cc" +#line 2105 "libmemcached/options/parser.cc" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -2311,7 +2313,7 @@ yyreturn: /* Line 1684 of yacc.c */ -#line 460 "libmemcached/options/parser.yy" +#line 462 "libmemcached/options/parser.yy" void Context::start() diff --git a/libtest/callbacks.h b/libtest/callbacks.h new file mode 100644 index 00000000..ea7ae182 --- /dev/null +++ b/libtest/callbacks.h @@ -0,0 +1,21 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* (test_callback_create_fn)(enum test_return_t*); +typedef enum test_return_t (test_callback_fn)(void *); +typedef enum test_return_t (test_callback_runner_fn)(test_callback_fn*, void *); +typedef enum test_return_t (test_callback_error_fn)(const enum test_return_t, void *); + +#ifdef __cplusplus +} +#endif + diff --git a/libtest/collection.h b/libtest/collection.h new file mode 100644 index 00000000..e8f8f62c --- /dev/null +++ b/libtest/collection.h @@ -0,0 +1,19 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +/** + A structure which describes a collection of test cases. +*/ +struct collection_st { + const char *name; + test_callback_fn *pre; + test_callback_fn *post; + struct test_st *tests; +}; + + diff --git a/libtest/common.h b/libtest/common.h new file mode 100644 index 00000000..9b00f6de --- /dev/null +++ b/libtest/common.h @@ -0,0 +1,50 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * uTest + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ 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. + * + */ + +/* + Common include file for libmemached +*/ + +#pragma once + +#include + +#include +#include +#include + +#include diff --git a/libtest/core.h b/libtest/core.h new file mode 100644 index 00000000..2b62161b --- /dev/null +++ b/libtest/core.h @@ -0,0 +1,11 @@ +/* + * uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +LIBTEST_API +void create_core(void); diff --git a/libtest/error.h b/libtest/error.h new file mode 100644 index 00000000..c4a3a702 --- /dev/null +++ b/libtest/error.h @@ -0,0 +1,18 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +enum test_return_t { + TEST_SUCCESS= 0, /* Backwards compatibility */ + TEST_FAILURE, + TEST_MEMORY_ALLOCATION_FAILURE, + TEST_SKIPPED, + TEST_FATAL // Collection should not be continued +}; + + +#define test_failed(__test_return_t) ((__test_return_t) != TEST_SUCCESS) diff --git a/libtest/failed.h b/libtest/failed.h index 16d1aecc..a4b2cacc 100644 --- a/libtest/failed.h +++ b/libtest/failed.h @@ -36,7 +36,6 @@ */ #pragma once -#include #ifdef __cplusplus extern "C" { diff --git a/libtest/framework.cc b/libtest/framework.cc new file mode 100644 index 00000000..ff67f20b --- /dev/null +++ b/libtest/framework.cc @@ -0,0 +1,57 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#include + +test_return_t Framework::destroy(void* arg) +{ + if (_destroy) + { + return _destroy(arg); + } + + return TEST_SUCCESS; +} + +test_return_t Framework::Item::flush(void* arg, test_st* run) +{ + if (run->requires_flush and _flush) + { + return _flush(arg); + } + + return TEST_SUCCESS; +} + +test_return_t Framework::on_error(const test_return_t rc, void* arg) +{ + if (_on_error and test_failed(_on_error(rc, arg))) + { + return TEST_FAILURE; + } + + return TEST_SUCCESS; +} + +test_return_t Framework::startup(void* arg) +{ + if (collection_startup) + { + return collection_startup(arg); + } + + return TEST_SUCCESS; +} + +test_return_t Framework::Item::startup(void* arg) +{ + if (_startup) + { + return _startup(arg); + } + + return TEST_SUCCESS; +} diff --git a/libtest/framework.h b/libtest/framework.h new file mode 100644 index 00000000..7a58cbee --- /dev/null +++ b/libtest/framework.h @@ -0,0 +1,137 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +/** + Framework is the structure which is passed to the test implementation to be filled. + This must be implemented in order for the test framework to load the tests. We call + get_world() in order to fill this structure. +*/ + +struct Framework { + collection_st *collections; + + /* These methods are called outside of any collection call. */ + test_callback_create_fn *_create; + test_callback_fn *_destroy; + + void* create(test_return_t* arg) + { + if (_create) + { + return _create(arg); + } + + return NULL; + } + + test_return_t destroy(void*); + + /* This is called a the beginning of any collection run. */ + test_callback_fn *collection_startup; + + test_return_t startup(void*); + + /* This is called a the end of any collection run. */ + test_callback_fn *collection_shutdown; + + test_return_t shutdown(void* arg) + { + if (collection_shutdown) + { + return collection_shutdown(arg); + } + + return TEST_SUCCESS; + } + + /** + These are run before/after the test. If implemented. Their execution is not controlled + by the test. + */ + struct Item { + /* This is called a the beginning of any run. */ + test_callback_fn *_startup; + + test_return_t startup(void*); + + /* + This called on a test if the test requires a flush call (the bool is + from test_st) + */ + test_callback_fn *_flush; + + /* + Run before and after the runnner is executed. + */ + test_callback_fn *pre_run; + test_callback_fn *post_run; + + Item() : + _startup(NULL), + _flush(NULL), + pre_run(NULL), + post_run(NULL) + { } + + test_return_t flush(void* arg, test_st* run); + + void set_pre(test_callback_fn *arg) + { + pre_run= arg; + } + + void set_post(test_callback_fn *arg) + { + pre_run= arg; + } + + test_return_t pre(void *arg) + { + if (pre_run) + { + return pre_run(arg); + } + + return TEST_SUCCESS; + } + + test_return_t post(void *arg) + { + if (post_run) + { + return post_run(arg); + } + + return TEST_SUCCESS; + } + + } item; + + /** + If an error occurs during the test, this is called. + */ + test_callback_error_fn *_on_error; + + test_return_t on_error(const enum test_return_t, void *); + + /** + Runner represents the callers for the tests. If not implemented we will use + a set of default implementations. + */ + Runner *runner; + + Framework(); + + virtual ~Framework() + { } + + Framework(const Framework&); + +private: + Framework& operator=(const Framework&); +}; diff --git a/libtest/get.h b/libtest/get.h new file mode 100644 index 00000000..2cd9dec8 --- /dev/null +++ b/libtest/get.h @@ -0,0 +1,22 @@ +/* + * uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + /* How we make all of this work :) */ + LIBTEST_API + void get_world(Framework *world); + +#ifdef __cplusplus +} +#endif + + diff --git a/libtest/include.am b/libtest/include.am index fb859b66..610521a7 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -16,8 +16,18 @@ CLEANFILES+= \ tests/var/tmp/* noinst_HEADERS+= \ + libtest/callbacks.h \ + libtest/collection.h \ + libtest/common.h \ + libtest/core.h \ + libtest/error.h \ libtest/failed.h \ + libtest/framework.h \ + libtest/get.h \ + libtest/runner.h \ libtest/server.h \ + libtest/stats.h \ + libtest/strerror.h \ libtest/test.h \ libtest/visibility.h @@ -26,8 +36,9 @@ libtest_libserver_la_SOURCES= libtest/server.c noinst_LTLIBRARIES+= libtest/libtest.la libtest_libtest_la_SOURCES=\ - libtest/test.c -libtest_libtest_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} + libtest/framework.cc \ + libtest/test.cc +libtest_libtest_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} -DBUILDING_LIBTEST libtest_libtest_la_CPPFLAGS= ${AM_CPPFLAGS} tests/var: tests/var/log tests/var/tmp diff --git a/libtest/runner.h b/libtest/runner.h new file mode 100644 index 00000000..8678c4c0 --- /dev/null +++ b/libtest/runner.h @@ -0,0 +1,19 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + + +/** + Structure which houses the actual callers for the test cases contained in + the collections. +*/ +struct Runner { + test_callback_runner_fn *pre; + test_callback_runner_fn *run; + test_callback_runner_fn *post; +}; + diff --git a/libtest/stats.h b/libtest/stats.h new file mode 100644 index 00000000..29be06c6 --- /dev/null +++ b/libtest/stats.h @@ -0,0 +1,30 @@ +/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once +struct Stats { + int32_t collection_success; + int32_t collection_skipped; + int32_t collection_failed; + int32_t collection_total; + + uint32_t success; + uint32_t skipped; + uint32_t failed; + uint32_t total; + + Stats() : + collection_success(0), + collection_skipped(0), + collection_failed(0), + collection_total(0), + success(0), + skipped(0), + failed(0), + total(0) + { } +}; + diff --git a/libtest/strerror.h b/libtest/strerror.h new file mode 100644 index 00000000..2d6e6536 --- /dev/null +++ b/libtest/strerror.h @@ -0,0 +1,14 @@ +/* + * uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +#pragma once + +/** + @note Friendly print function for errors. +*/ +LIBTEST_API +const char *test_strerror(test_return_t code); diff --git a/libtest/test.c b/libtest/test.c deleted file mode 100644 index 0905e13b..00000000 --- a/libtest/test.c +++ /dev/null @@ -1,399 +0,0 @@ -/* uTest - * Copyright (C) 2006-2009 Brian Aker - * All rights reserved. - * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. - */ - -/* - Sample test application. -*/ - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static void world_stats_print(world_stats_st *stats) -{ - fputc('\n', stderr); - fprintf(stderr, "Total Collections\t\t\t\t%u\n", stats->collection_total); - fprintf(stderr, "\tFailed Collections\t\t\t%u\n", stats->collection_failed); - fprintf(stderr, "\tSkipped Collections\t\t\t%u\n", stats->collection_skipped); - fprintf(stderr, "\tSucceeded Collections\t\t%u\n", stats->collection_success); - fputc('\n', stderr); - fprintf(stderr, "Total\t\t\t\t%u\n", stats->total); - fprintf(stderr, "\tFailed\t\t\t%u\n", stats->failed); - fprintf(stderr, "\tSkipped\t\t\t%u\n", stats->skipped); - fprintf(stderr, "\tSucceeded\t\t%u\n", stats->success); -} - -long int timedif(struct timeval a, struct timeval b) -{ - long us, s; - - us = (int)(a.tv_usec - b.tv_usec); - us /= 1000; - s = (int)(a.tv_sec - b.tv_sec); - s *= 1000; - return s + us; -} - -const char *test_strerror(test_return_t code) -{ - switch (code) { - case TEST_SUCCESS: - return "ok"; - case TEST_FAILURE: - return "failed"; - case TEST_FATAL: - return "failed"; - case TEST_SKIPPED: - return "skipped"; - case TEST_MEMORY_ALLOCATION_FAILURE: - return "memory allocation"; - case TEST_MAXIMUM_RETURN: - default: - fprintf(stderr, "Unknown return value\n"); - abort(); - } -} - -void create_core(void) -{ - if (getenv("LIBMEMCACHED_NO_COREDUMP") == NULL) - { - pid_t pid= fork(); - - if (pid == 0) - { - abort(); - } - else - { - while (waitpid(pid, NULL, 0) != pid) - { - ; - } - } - } -} - - -static test_return_t _runner_default(test_callback_fn func, void *p) -{ - if (func) - { - return func(p); - } - else - { - return TEST_SUCCESS; - } -} - -static world_runner_st defualt_runners= { - _runner_default, - _runner_default, - _runner_default -}; - -static test_return_t _default_callback(void *p) -{ - (void)p; - - return TEST_SUCCESS; -} - -static inline void set_default_fn(test_callback_fn *fn) -{ - if (*fn == NULL) - { - *fn= _default_callback; - } -} - -static collection_st *init_world(world_st *world) -{ - if (! world->runner) - { - world->runner= &defualt_runners; - } - - set_default_fn(&world->collection.startup); - set_default_fn(&world->collection.shutdown); - - return world->collections; -} - - -int main(int argc, char *argv[]) -{ - test_return_t return_code; - unsigned int x; - char *collection_to_run= NULL; - char *wildcard= NULL; - world_st world; - collection_st *collection; - void *world_ptr; - - world_stats_st stats; - -#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT - if (sasl_client_init(NULL) != SASL_OK) - { - fprintf(stderr, "Failed to initialize sasl library!\n"); - return EXIT_FAILURE; - } -#endif - - memset(&stats, 0, sizeof(stats)); - memset(&world, 0, sizeof(world)); - get_world(&world); - - collection= init_world(&world); - - if (world.create) - { - test_return_t error; - world_ptr= world.create(&error); - if (error != TEST_SUCCESS) - exit(1); - } - else - { - world_ptr= NULL; - } - - if (argc > 1) - { - collection_to_run= argv[1]; - } - else if (getenv("TEST_COLLECTION")) - { - collection_to_run= getenv("TEST_COLLECTION"); - } - - if (collection_to_run) - printf("Only testing %s\n", collection_to_run); - - if (argc == 3) - { - wildcard= argv[2]; - } - - for (collection_st *next= collection; next->name; next++) - { - test_return_t collection_rc= TEST_SUCCESS; - test_st *run; - bool failed= false; - bool skipped= false; - - run= next->tests; - if (collection_to_run && fnmatch(collection_to_run, next->name, 0)) - continue; - - stats.collection_total++; - - collection_rc= world.collection.startup(world_ptr); - - if (collection_rc != TEST_SUCCESS) - goto skip_pre; - - if (next->pre) - { - collection_rc= world.runner->pre(next->pre, world_ptr); - } - -skip_pre: - switch (collection_rc) - { - case TEST_SUCCESS: - fprintf(stderr, "\n%s\n\n", next->name); - break; - case TEST_FATAL: - fprintf(stderr, "\n%s [ failed ]\n\n", next->name); - stats.collection_failed++; - goto cleanup; - case TEST_FAILURE: - fprintf(stderr, "\n%s [ failed ]\n\n", next->name); - stats.collection_failed++; - goto cleanup; - case TEST_SKIPPED: - fprintf(stderr, "\n%s [ skipping ]\n\n", next->name); - stats.collection_skipped++; - goto cleanup; - case TEST_MEMORY_ALLOCATION_FAILURE: - case TEST_MAXIMUM_RETURN: - default: - assert(0); - break; - } - - - for (x= 0; run->name; run++) - { - struct timeval start_time, end_time; - long int load_time= 0; - - if (wildcard && fnmatch(wildcard, run->name, 0)) - continue; - - fprintf(stderr, "Testing %s", run->name); - - if (world.test.startup) - { - world.test.startup(world_ptr); - } - - if (run->requires_flush && world.test.flush) - { - world.test.flush(world_ptr); - } - - if (world.test.pre_run) - { - world.test.pre_run(world_ptr); - } - - - // Runner code - { -#if 0 - if (next->pre && world.runner->pre) - { - return_code= world.runner->pre(next->pre, world_ptr); - - if (return_code != TEST_SUCCESS) - { - goto error; - } - } -#endif - - gettimeofday(&start_time, NULL); - return_code= world.runner->run(run->test_fn, world_ptr); - gettimeofday(&end_time, NULL); - load_time= timedif(end_time, start_time); - -#if 0 - if (next->post && world.runner->post) - { - (void) world.runner->post(next->post, world_ptr); - } -#endif - } - - if (world.test.post_run) - { - world.test.post_run(world_ptr); - } - - stats.total++; - - fprintf(stderr, "\t\t\t\t\t"); - - switch (return_code) - { - case TEST_SUCCESS: - fprintf(stderr, "%ld.%03ld ", load_time / 1000, load_time % 1000); - stats.success++; - break; - - case TEST_FATAL: - case TEST_FAILURE: -#if 0 - push_failed_test(next->name, run->name); -#endif - stats.failed++; - failed= true; - break; - - case TEST_SKIPPED: - stats.skipped++; - skipped= true; - break; - - case TEST_MEMORY_ALLOCATION_FAILURE: - fprintf(stderr, "Exhausted memory, quitting\n"); - abort(); - - case TEST_MAXIMUM_RETURN: - default: - assert(0); // Coding error. - break; - } - - fprintf(stderr, "[ %s ]\n", test_strerror(return_code)); - - if (world.test.on_error) - { - test_return_t rc; - rc= world.test.on_error(return_code, world_ptr); - - if (rc != TEST_SUCCESS) - break; - } - - // If we get a TEST_FATAL we move onto the next collection - if (return_code == TEST_FATAL) - { - break; - } - } - - if (next->post && world.runner->post) - { - (void) world.runner->post(next->post, world_ptr); - } - - if (! failed && ! skipped) - { - stats.collection_success++; - } -cleanup: - - world.collection.shutdown(world_ptr); - } - - if (stats.collection_failed || stats.collection_skipped) - { - fprintf(stderr, "Some test failures and/or skipped test occurred.\n\n"); -#if 0 - print_failed_test(); -#endif - } - else - { - fprintf(stderr, "All tests completed successfully\n\n"); - } - - if (world.destroy) - { - test_return_t error; - error= world.destroy(world_ptr); - - if (error != TEST_SUCCESS) - { - fprintf(stderr, "Failure during shutdown.\n"); - stats.failed++; // We do this to make our exit code return EXIT_FAILURE - } - } - - world_stats_print(&stats); - - return stats.failed == 0 ? 0 : 1; -} diff --git a/libtest/test.cc b/libtest/test.cc new file mode 100644 index 00000000..ee743983 --- /dev/null +++ b/libtest/test.cc @@ -0,0 +1,319 @@ +/* uTest + * 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 in the parent directory for full text. + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef __INTEL_COMPILER +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +static in_port_t global_port= 0; + +in_port_t default_port() +{ + assert(global_port); + return global_port; +} + +void set_default_port(in_port_t port) +{ + global_port= port; +} + +static void stats_print(Stats *stats) +{ + std::cout << "\tTotal Collections\t\t\t\t" << stats->collection_total << std::endl; + std::cout << "\tFailed Collections\t\t\t\t" << stats->collection_failed << std::endl; + std::cout << "\tSkipped Collections\t\t\t\t" << stats->collection_skipped << std::endl; + std::cout << "\tSucceeded Collections\t\t\t\t" << stats->collection_success << std::endl; + std::cout << std::endl; + std::cout << "Total\t\t\t\t" << stats->total << std::endl; + std::cout << "\tFailed\t\t\t" << stats->failed << std::endl; + std::cout << "\tSkipped\t\t\t" << stats->skipped << std::endl; + std::cout << "\tSucceeded\t\t" << stats->success << std::endl; +} + +static long int timedif(struct timeval a, struct timeval b) +{ + long us, s; + + us = (long)(a.tv_usec - b.tv_usec); + us /= 1000; + s = (long)(a.tv_sec - b.tv_sec); + s *= 1000; + return s + us; +} + +const char *test_strerror(test_return_t code) +{ + switch (code) { + case TEST_SUCCESS: + return "ok"; + + case TEST_FAILURE: + return "failed"; + + case TEST_MEMORY_ALLOCATION_FAILURE: + return "memory allocation"; + + case TEST_SKIPPED: + return "skipped"; + + case TEST_FATAL: + break; + } + + return "failed"; +} + +void create_core(void) +{ + if (getenv("LIBMEMCACHED_NO_COREDUMP") == NULL) + { + pid_t pid= fork(); + + if (pid == 0) + { + abort(); + } + else + { + while (waitpid(pid, NULL, 0) != pid) {}; + } + } +} + + +static test_return_t _runner_default(test_callback_fn func, void *p) +{ + if (func) + { + return func(p); + } + + return TEST_SUCCESS; +} + +static Runner defualt_runners= { + _runner_default, + _runner_default, + _runner_default +}; + +static test_return_t _default_callback(void *p) +{ + (void)p; + + return TEST_SUCCESS; +} + +Framework::Framework() : + collections(NULL), + _create(NULL), + _destroy(NULL), + collection_startup(_default_callback), + collection_shutdown(_default_callback), + _on_error(NULL), + runner(&defualt_runners) +{ +} + + +int main(int argc, char *argv[]) +{ + Framework world; + + Stats stats; + + get_world(&world); + + if (not world.runner) + { + world.runner= &defualt_runners; + } + + test_return_t error; + void *world_ptr= world.create(&error); + if (test_failed(error)) + { + return EXIT_FAILURE; + } + + char *collection_to_run= NULL; + if (argc > 1) + { + collection_to_run= argv[1]; + } + else if (getenv("TEST_COLLECTION")) + { + collection_to_run= getenv("TEST_COLLECTION"); + } + + if (collection_to_run) + { + std::cout << "Only testing " << collection_to_run << std::endl; + } + + char *wildcard= NULL; + if (argc == 3) + { + wildcard= argv[2]; + } + + for (collection_st *next= world.collections; next->name; next++) + { + test_return_t collection_rc= TEST_SUCCESS; + bool failed= false; + bool skipped= false; + + if (collection_to_run && fnmatch(collection_to_run, next->name, 0)) + continue; + + stats.collection_total++; + + collection_rc= world.startup(world_ptr); + + if (collection_rc == TEST_SUCCESS and next->pre) + { + collection_rc= world.runner->pre(next->pre, world_ptr); + } + + switch (collection_rc) + { + case TEST_SUCCESS: + std::cerr << std::endl << next->name << std::endl << std::endl; + break; + + case TEST_FATAL: + case TEST_FAILURE: + std::cerr << std::endl << next->name << " [ failed ]" << std::endl << std::endl; + stats.collection_failed++; + goto cleanup; + + case TEST_SKIPPED: + std::cerr << std::endl << next->name << " [ skipping ]" << std::endl << std::endl; + stats.collection_skipped++; + goto cleanup; + + case TEST_MEMORY_ALLOCATION_FAILURE: + test_assert(0, "Allocation failure, or unknown return"); + } + + for (test_st *run= next->tests; run->name; run++) + { + struct timeval start_time, end_time; + long int load_time= 0; + + if (wildcard && fnmatch(wildcard, run->name, 0)) + { + continue; + } + + std::cerr << "\tTesting " << run->name; + + world.item.startup(world_ptr); + + world.item.flush(world_ptr, run); + + world.item.pre(world_ptr); + + test_return_t return_code; + { // Runner Code + gettimeofday(&start_time, NULL); + return_code= world.runner->run(run->test_fn, world_ptr); + gettimeofday(&end_time, NULL); + load_time= timedif(end_time, start_time); + } + + world.item.post(world_ptr); + + stats.total++; + + std::cerr << "\t\t\t\t\t"; + + switch (return_code) + { + case TEST_SUCCESS: + std::cerr << load_time / 1000 << "." << load_time % 1000; + stats.success++; + break; + + case TEST_FATAL: + case TEST_FAILURE: + stats.failed++; + failed= true; + break; + + case TEST_SKIPPED: + stats.skipped++; + skipped= true; + break; + + case TEST_MEMORY_ALLOCATION_FAILURE: + test_assert(0, "Memory Allocation Error"); + } + + std::cerr << "[ " << test_strerror(return_code) << " ]" << std::endl; + + if (test_failed(world.on_error(return_code, world_ptr))) + { + break; + } + } + + if (next->post && world.runner->post) + { + (void) world.runner->post(next->post, world_ptr); + } + + if (failed == 0 and skipped == 0) + { + stats.collection_success++; + } +cleanup: + + world.shutdown(world_ptr); + } + + if (stats.collection_failed || stats.collection_skipped) + { + std::cerr << std::endl << std::endl << "Some test failures and/or skipped test occurred." << std::endl << std::endl; +#if 0 + print_failed_test(); +#endif + } + else + { + std::cout << std::endl << std::endl << "All tests completed successfully." << std::endl << std::endl; + } + + if (test_failed(world.destroy(world_ptr))) + { + stats.failed++; // We do this to make our exit code return EXIT_FAILURE + } + + stats_print(&stats); + + return stats.failed == 0 ? 0 : 1; +} diff --git a/libtest/test.h b/libtest/test.h index 2245e798..c36572ea 100644 --- a/libtest/test.h +++ b/libtest/test.h @@ -1,215 +1,50 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * - * Gearmand client and server library. - * - * Copyright (C) 2011 Data Differential, http://datadifferential.com/ - * Copyright (C) 2006-2010 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. +/* + * uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/ * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. */ #pragma once -#include - -/* - Structures for generic tests. -*/ - -#include -#include -#include - -#if !defined(__cplusplus) -# include -#endif - -typedef struct world_st world_st; -typedef struct collection_st collection_st; -typedef struct test_st test_st; - -enum test_return_t { - TEST_SUCCESS, /* Backwards compatibility */ - TEST_FAILURE, - TEST_MEMORY_ALLOCATION_FAILURE, - TEST_SKIPPED, - TEST_FATAL, // Collection should not be continued - TEST_MAXIMUM_RETURN /* Always add new error code before */ -}; - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum test_return_t test_return_t; - -#ifdef __cplusplus -} -#endif - - -typedef void *(*test_callback_create_fn)(test_return_t *error); -typedef test_return_t (*test_callback_fn)(void *); -typedef test_return_t (*test_callback_runner_fn)(test_callback_fn, void *); -typedef test_return_t (*test_callback_error_fn)(test_return_t, void *); - /** A structure describing the test case. */ struct test_st { const char *name; bool requires_flush; - test_callback_fn test_fn; -}; - - -/** - A structure which describes a collection of test cases. -*/ -struct collection_st { - const char *name; - test_callback_fn pre; - test_callback_fn post; - test_st *tests; -}; - - -/** - Structure which houses the actual callers for the test cases contained in - the collections. -*/ -typedef struct { - test_callback_runner_fn pre; - test_callback_runner_fn run; - test_callback_runner_fn post; -} world_runner_st; - - -/** - world_st is the structure which is passed to the test implementation to be filled. - This must be implemented in order for the test framework to load the tests. We call - get_world() in order to fill this structure. -*/ - -struct world_st { - collection_st *collections; - - /* These methods are called outside of any collection call. */ - test_callback_create_fn create; - test_callback_fn destroy; - - struct { - /* This is called a the beginning of any test run. */ - test_callback_fn startup; - - /* This called on a test if the test requires a flush call (the bool is from test_st) */ - test_callback_fn flush; - - /** - These are run before/after the test. If implemented. Their execution is not controlled - by the test. - */ - test_callback_fn pre_run; - test_callback_fn post_run; - - /** - If an error occurs during the test, this is called. - */ - test_callback_error_fn on_error; - } test; - - struct { - /* This is called a the beginning of any collection run. */ - test_callback_fn startup; - - /* This is called at the end of any collection run. */ - test_callback_fn shutdown; - } collection; - - - /** - Runner represents the callers for the tests. If not implemented we will use - a set of default implementations. - */ - world_runner_st *runner; + test_callback_fn *test_fn; }; +#define TEST_STRINGIFY(x) #x +#define TEST_TOSTRING(x) TEST_STRINGIFY(x) +#define TEST_AT __FILE__ ":" TEST_TOSTRING(__LINE__) -/** - @note world_stats_st is a simple structure for tracking test successes. -*/ -typedef struct { - uint32_t collection_success; - uint32_t collection_skipped; - uint32_t collection_failed; - uint32_t collection_total; - uint32_t success; - uint32_t skipped; - uint32_t failed; - uint32_t total; -} world_stats_st; - -#ifdef __cplusplus -extern "C" { -#endif - -/* Help function for use with gettimeofday() */ -LIBTEST_API -long int timedif(struct timeval a, struct timeval b); - -/* How we make all of this work :) */ -LIBTEST_API -void get_world(world_st *world); - -LIBTEST_INTERNAL_API -void create_core(void); - -/** - @note Friendly print function for errors. -*/ -LIBTEST_API -const char *test_strerror(test_return_t code); +#define test_assert_errno(A) \ +do \ +{ \ + if ((A)) { \ + fprintf(stderr, "\nAssertion failed at %s:%d: ", __FILE__, __LINE__);\ + perror(#A); \ + fprintf(stderr, "\n"); \ + create_core(); \ + assert((A)); \ + } \ +} while (0) -#define test_fail(A) \ +#define test_assert(A, B) \ do \ { \ - if (1) { \ - fprintf(stderr, "\nFailed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ + if ((A)) { \ + fprintf(stderr, "\nAssertion, %s(%s), failed at %s:%d: ", (B), #A, __FILE__, __LINE__);\ + fprintf(stderr, "\n"); \ create_core(); \ - return TEST_FAILURE; \ + assert((A)); \ } \ } while (0) -#define test_true(A) \ +#define test_truth(A) \ do \ { \ if (! (A)) { \ @@ -219,22 +54,21 @@ do \ } \ } while (0) -#define test_true_got(A,B) \ +#define test_true(A) \ do \ { \ if (! (A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: \"%s\" received \"%s\"\n", __FILE__, __LINE__, #A, (B));\ + fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ create_core(); \ return TEST_FAILURE; \ } \ } while (0) -#define test_compare(A,B) \ +#define test_true_got(A,B) \ do \ { \ - if ((A) != (B)) \ - { \ - fprintf(stderr, "\n%s:%d: Expected %s, got %lu\n", __FILE__, __LINE__, #A, (unsigned long)(B)); \ + if (! (A)) { \ + fprintf(stderr, "\nAssertion failed at %s:%d: \"%s\" received \"%s\"\n", __FILE__, __LINE__, #A, (B));\ create_core(); \ return TEST_FAILURE; \ } \ @@ -249,22 +83,22 @@ do \ } \ } while (0) -#define test_compare_got(A,B,C) \ +#define test_fail(A) \ do \ { \ - if ((A) != (B)) \ - { \ - fprintf(stderr, "\n%s:%d: Expected %s, got %s\n", __FILE__, __LINE__, #A, (C)); \ + if (1) { \ + fprintf(stderr, "\nFailed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ create_core(); \ return TEST_FAILURE; \ } \ } while (0) + #define test_false(A) \ do \ { \ if ((A)) { \ - fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\ + fprintf(stderr, "\nAssertion failed in %s:%d: %s\n", __FILE__, __LINE__, #A);\ create_core(); \ return TEST_FAILURE; \ } \ @@ -280,12 +114,36 @@ do \ } \ } while (0) + +#define test_compare(A,B) \ +do \ +{ \ + if ((A) != (B)) \ + { \ + fprintf(stderr, "\n%s:%d: Expected %s, got %lu\n", __FILE__, __LINE__, #A, (unsigned long)(B)); \ + create_core(); \ + return TEST_FAILURE; \ + } \ +} while (0) + +#define test_compare_got(A,B,C) \ +do \ +{ \ + if ((A) != (B)) \ + { \ + fprintf(stderr, "\n%s:%d: Expected %s, got %s\n", __FILE__, __LINE__, #A, (C)); \ + create_core(); \ + return TEST_FAILURE; \ + } \ +} while (0) + + #define test_strcmp(A,B) \ do \ { \ if (strcmp((A), (B))) \ { \ - fprintf(stderr, "\n%s:%d: `%s` -> `%s`\n", __FILE__, __LINE__, (A), (B)); \ + fprintf(stderr, "\n%s:%d: Expected %s, got %s\n", __FILE__, __LINE__, (A), (B)); \ create_core(); \ return TEST_FAILURE; \ } \ @@ -302,22 +160,3 @@ do \ } \ } while (0) -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) -#define AT __FILE__ ":" TOSTRING(__LINE__) - -#ifdef __cplusplus -#define STRING_WITH_LEN(X) (X), (static_cast((sizeof(X) - 1))) -#else -#define STRING_WITH_LEN(X) (X), ((size_t)((sizeof(X) - 1))) -#endif - -#ifdef __cplusplus -#define STRING_PARAM_WITH_LEN(X) X, static_cast(sizeof(X) - 1) -#else -#define STRING_PARAM_WITH_LEN(X) X, (size_t)((sizeof(X) - 1)) -#endif - -#ifdef __cplusplus -} -#endif diff --git a/libtest/test.hpp b/libtest/test.hpp new file mode 100644 index 00000000..5953f82c --- /dev/null +++ b/libtest/test.hpp @@ -0,0 +1,46 @@ +/* uTest + * 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 in the parent directory for full text. + */ + +/* + Structures for generic tests. +*/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma once + +LIBTEST_API + in_port_t default_port(); + +LIBTEST_API + void set_default_port(in_port_t port); + +#ifdef __cplusplus +#define test_literal_param(X) (X), (static_cast((sizeof(X) - 1))) +#else +#define test_literal_param(X) (X), ((size_t)((sizeof(X) - 1))) +#endif + +#define test_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0) diff --git a/support/libmemcached.spec.in b/support/libmemcached.spec.in index ccc093ea..337d1ec6 100644 --- a/support/libmemcached.spec.in +++ b/support/libmemcached.spec.in @@ -83,11 +83,11 @@ you will need to install %{name}-devel. %exclude %{_libdir}/libmemcachedutil.la %exclude %{_libdir}/libmemcachedprotocol.la %{_libdir}/libhashkit.so.1.0.0 -%{_libdir}/libmemcached.so.7.0.0 +%{_libdir}/libmemcached.so.8.0.0 %{_libdir}/libmemcachedutil.so.2.0.0 %{_libdir}/libmemcachedprotocol.so.0.0.0 %{_libdir}/libhashkit.so.1 -%{_libdir}/libmemcached.so.7 +%{_libdir}/libmemcached.so.8 %{_libdir}/libmemcachedprotocol.so.0 %{_libdir}/libmemcachedutil.so.2 %{_mandir}/man1/memcapable.1.gz diff --git a/tests/atomsmasher.c b/tests/atomsmasher.c deleted file mode 100644 index 8563e4ec..00000000 --- a/tests/atomsmasher.c +++ /dev/null @@ -1,296 +0,0 @@ -/* LibMemcached - * Copyright (C) 2006-2009 Brian Aker - * All rights reserved. - * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. - * - * Summary: - * - */ - -/* - Sample test application. -*/ -#include "config.h" - -#include "libmemcached/memcached.h" -#include "libmemcached/watchpoint.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* Number of items generated for tests */ -#define GLOBAL_COUNT 100000 - -/* Number of times to run the test loop */ -#define TEST_COUNTER 500000 -static uint32_t global_count; - -static pairs_st *global_pairs; -static char *global_keys[GLOBAL_COUNT]; -static size_t global_keys_length[GLOBAL_COUNT]; - -static test_return_t cleanup_pairs(memcached_st *memc) -{ - (void)memc; - pairs_free(global_pairs); - - return EXIT_SUCCESS; -} - -static test_return_t generate_pairs(memcached_st *memc) -{ - (void)memc; - global_pairs= pairs_generate(GLOBAL_COUNT, 400); - global_count= GLOBAL_COUNT; - - for (size_t x= 0; x < global_count; x++) - { - global_keys[x]= global_pairs[x].key; - global_keys_length[x]= global_pairs[x].key_length; - } - - return EXIT_SUCCESS; -} - -static test_return_t drizzle(memcached_st *memc) -{ - memcached_return_t rc; - char *return_value; - size_t return_value_length; - uint32_t flags; - -infinite: - for (size_t x= 0; x < TEST_COUNTER; x++) - { - uint32_t test_bit; - uint8_t which; - - test_bit= (uint32_t)(random() % GLOBAL_COUNT); - which= (uint8_t)(random() % 2); - - if (which == 0) - { - return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit], - &return_value_length, &flags, &rc); - if (rc == MEMCACHED_SUCCESS && return_value) - { - free(return_value); - } - else if (rc == MEMCACHED_NOTFOUND) - { - continue; - } - else - { - WATCHPOINT_ERROR(rc); - WATCHPOINT_ASSERT(rc); - } - } - else - { - rc= memcached_set(memc, global_pairs[test_bit].key, - global_pairs[test_bit].key_length, - global_pairs[test_bit].value, - global_pairs[test_bit].value_length, - 0, 0); - if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) - { - WATCHPOINT_ERROR(rc); - WATCHPOINT_ASSERT(0); - } - } - } - - if (getenv("MEMCACHED_ATOM_BURIN_IN")) - goto infinite; - - return TEST_SUCCESS; -} - -static test_return_t pre_nonblock(memcached_st *memc) -{ - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0); - - return TEST_SUCCESS; -} - -/* - Set the value, then quit to make sure it is flushed. - Come back in and test that add fails. -*/ -static test_return_t add_test(memcached_st *memc) -{ - memcached_return_t rc; - const char *key= "foo"; - const char *value= "when we sanitize"; - unsigned long long setting_value; - - setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK); - - rc= memcached_set(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); - memcached_quit(memc); - rc= memcached_add(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); - - /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */ - if (setting_value) - { - test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED); - } - else - { - test_true(rc == MEMCACHED_NOTSTORED); - } - - return EXIT_SUCCESS; -} - -/* - * repeating add_tests many times - * may show a problem in timing - */ -static test_return_t many_adds(memcached_st *memc) -{ - for (size_t x= 0; x < TEST_COUNTER; x++) - { - add_test(memc); - } - return EXIT_SUCCESS; -} - -test_st smash_tests[] ={ - {"generate_pairs", 1, (test_callback_fn)generate_pairs }, - {"drizzle", 1, (test_callback_fn)drizzle }, - {"cleanup", 1, (test_callback_fn)cleanup_pairs }, - {"many_adds", 1, (test_callback_fn)many_adds }, - {0, 0, 0} -}; - -#define BENCHMARK_TEST_LOOP 20000 - -struct benchmark_state_st -{ - bool create_init; - bool clone_init; - memcached_st *create; - memcached_st *clone; -} benchmark_state; - -static test_return_t memcached_create_benchmark(memcached_st *memc) -{ - (void)memc; - benchmark_state.create_init= true; - - for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++) - { - memcached_st *ptr; - ptr= memcached_create(&benchmark_state.create[x]); - - test_true(ptr); - } - - return TEST_SUCCESS; -} - -static test_return_t memcached_clone_benchmark(memcached_st *memc) -{ - benchmark_state.clone_init= true; - - for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++) - { - memcached_st *ptr; - ptr= memcached_clone(&benchmark_state.clone[x], memc); - - test_true(ptr); - } - - return TEST_SUCCESS; -} - -static test_return_t pre_allocate(memcached_st *memc) -{ - (void)memc; - memset(&benchmark_state, 0, sizeof(benchmark_state)); - - benchmark_state.create= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st)); - test_true(benchmark_state.create); - benchmark_state.clone= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st)); - test_true(benchmark_state.clone); - - return TEST_SUCCESS; -} - -static test_return_t post_allocate(memcached_st *memc) -{ - (void)memc; - for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++) - { - if (benchmark_state.create_init) - memcached_free(&benchmark_state.create[x]); - - if (benchmark_state.clone_init) - memcached_free(&benchmark_state.clone[x]); - } - - free(benchmark_state.create); - free(benchmark_state.clone); - - return TEST_SUCCESS; -} - - -test_st micro_tests[] ={ - {"memcached_create", 1, (test_callback_fn)memcached_create_benchmark }, - {"memcached_clone", 1, (test_callback_fn)memcached_clone_benchmark }, - {0, 0, 0} -}; - - -collection_st collection[] ={ - {"smash", 0, 0, smash_tests}, - {"smash_nonblock", (test_callback_fn)pre_nonblock, 0, smash_tests}, - {"micro-benchmark", (test_callback_fn)pre_allocate, (test_callback_fn)post_allocate, micro_tests}, - {0, 0, 0, 0} -}; - - -#define SERVERS_TO_CREATE 5 - -#include "libmemcached_world.h" - -void get_world(world_st *world) -{ - world->collections= collection; - - world->create= (test_callback_create_fn)world_create; - world->destroy= (test_callback_fn)world_destroy; - - world->test.startup= (test_callback_fn)world_test_startup; - world->test.flush= (test_callback_fn)world_flush; - world->test.pre_run= (test_callback_fn)world_pre_run; - world->test.post_run= (test_callback_fn)world_post_run; - world->test.on_error= (test_callback_error_fn)world_on_error; - - world->collection.startup= (test_callback_fn)world_container_startup; - world->collection.shutdown= (test_callback_fn)world_container_shutdown; - - world->runner= &defualt_libmemcached_runner; -} diff --git a/tests/atomsmasher.cc b/tests/atomsmasher.cc new file mode 100644 index 00000000..a525b95e --- /dev/null +++ b/tests/atomsmasher.cc @@ -0,0 +1,296 @@ +/* LibMemcached + * Copyright (C) 2006-2009 Brian Aker + * All rights reserved. + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + * + * Summary: + * + */ + +/* + Sample test application. +*/ +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Number of items generated for tests */ +#define GLOBAL_COUNT 100000 + +/* Number of times to run the test loop */ +#define TEST_COUNTER 500000 +static uint32_t global_count; + +static pairs_st *global_pairs; +static char *global_keys[GLOBAL_COUNT]; +static size_t global_keys_length[GLOBAL_COUNT]; + +static test_return_t cleanup_pairs(memcached_st *memc) +{ + (void)memc; + pairs_free(global_pairs); + + return TEST_SUCCESS; +} + +static test_return_t generate_pairs(memcached_st *memc) +{ + (void)memc; + global_pairs= pairs_generate(GLOBAL_COUNT, 400); + global_count= GLOBAL_COUNT; + + for (size_t x= 0; x < global_count; x++) + { + global_keys[x]= global_pairs[x].key; + global_keys_length[x]= global_pairs[x].key_length; + } + + return TEST_SUCCESS; +} + +static test_return_t drizzle(memcached_st *memc) +{ + memcached_return_t rc; + char *return_value; + size_t return_value_length; + uint32_t flags; + +infinite: + for (size_t x= 0; x < TEST_COUNTER; x++) + { + uint32_t test_bit; + uint8_t which; + + test_bit= (uint32_t)(random() % GLOBAL_COUNT); + which= (uint8_t)(random() % 2); + + if (which == 0) + { + return_value= memcached_get(memc, global_keys[test_bit], global_keys_length[test_bit], + &return_value_length, &flags, &rc); + if (rc == MEMCACHED_SUCCESS && return_value) + { + free(return_value); + } + else if (rc == MEMCACHED_NOTFOUND) + { + continue; + } + else + { + WATCHPOINT_ERROR(rc); + WATCHPOINT_ASSERT(rc); + } + } + else + { + rc= memcached_set(memc, global_pairs[test_bit].key, + global_pairs[test_bit].key_length, + global_pairs[test_bit].value, + global_pairs[test_bit].value_length, + 0, 0); + if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) + { + WATCHPOINT_ERROR(rc); + WATCHPOINT_ASSERT(0); + } + } + } + + if (getenv("MEMCACHED_ATOM_BURIN_IN")) + goto infinite; + + return TEST_SUCCESS; +} + +static test_return_t pre_nonblock(memcached_st *memc) +{ + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0); + + return TEST_SUCCESS; +} + +/* + Set the value, then quit to make sure it is flushed. + Come back in and test that add fails. +*/ +static test_return_t add_test(memcached_st *memc) +{ + memcached_return_t rc; + const char *key= "foo"; + const char *value= "when we sanitize"; + unsigned long long setting_value; + + setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK); + + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); + memcached_quit(memc); + rc= memcached_add(memc, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + + /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */ + if (setting_value) + { + test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED); + } + else + { + test_true(rc == MEMCACHED_NOTSTORED); + } + + return TEST_SUCCESS; +} + +/* + * repeating add_tests many times + * may show a problem in timing + */ +static test_return_t many_adds(memcached_st *memc) +{ + for (size_t x= 0; x < TEST_COUNTER; x++) + { + add_test(memc); + } + return TEST_SUCCESS; +} + +test_st smash_tests[] ={ + {"generate_pairs", 1, (test_callback_fn*)generate_pairs }, + {"drizzle", 1, (test_callback_fn*)drizzle }, + {"cleanup", 1, (test_callback_fn*)cleanup_pairs }, + {"many_adds", 1, (test_callback_fn*)many_adds }, + {0, 0, 0} +}; + +#define BENCHMARK_TEST_LOOP 20000 + +struct benchmark_state_st +{ + bool create_init; + bool clone_init; + memcached_st *create; + memcached_st *clone; +} benchmark_state; + +static test_return_t memcached_create_benchmark(memcached_st *memc) +{ + (void)memc; + benchmark_state.create_init= true; + + for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++) + { + memcached_st *ptr; + ptr= memcached_create(&benchmark_state.create[x]); + + test_true(ptr); + } + + return TEST_SUCCESS; +} + +static test_return_t memcached_clone_benchmark(memcached_st *memc) +{ + benchmark_state.clone_init= true; + + for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++) + { + memcached_st *ptr; + ptr= memcached_clone(&benchmark_state.clone[x], memc); + + test_true(ptr); + } + + return TEST_SUCCESS; +} + +static test_return_t pre_allocate(memcached_st *memc) +{ + (void)memc; + memset(&benchmark_state, 0, sizeof(benchmark_state)); + + benchmark_state.create= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st)); + test_true(benchmark_state.create); + benchmark_state.clone= (memcached_st *)calloc(BENCHMARK_TEST_LOOP, sizeof(memcached_st)); + test_true(benchmark_state.clone); + + return TEST_SUCCESS; +} + +static test_return_t post_allocate(memcached_st *memc) +{ + (void)memc; + for (size_t x= 0; x < BENCHMARK_TEST_LOOP; x++) + { + if (benchmark_state.create_init) + memcached_free(&benchmark_state.create[x]); + + if (benchmark_state.clone_init) + memcached_free(&benchmark_state.clone[x]); + } + + free(benchmark_state.create); + free(benchmark_state.clone); + + return TEST_SUCCESS; +} + + +test_st micro_tests[] ={ + {"memcached_create", 1, (test_callback_fn*)memcached_create_benchmark }, + {"memcached_clone", 1, (test_callback_fn*)memcached_clone_benchmark }, + {0, 0, 0} +}; + + +collection_st collection[] ={ + {"smash", 0, 0, smash_tests}, + {"smash_nonblock", (test_callback_fn*)pre_nonblock, 0, smash_tests}, + {"micro-benchmark", (test_callback_fn*)pre_allocate, (test_callback_fn*)post_allocate, micro_tests}, + {0, 0, 0, 0} +}; + + +#define SERVERS_TO_CREATE 5 + +#include "libmemcached_world.h" + +void get_world(Framework *world) +{ + world->collections= collection; + + world->_create= (test_callback_create_fn*)world_create; + world->_destroy= (test_callback_fn*)world_destroy; + + world->item._startup= (test_callback_fn*)world_test_startup; + world->item._flush= (test_callback_fn*)world_flush; + world->item.set_pre((test_callback_fn*)world_pre_run); + world->item.set_post((test_callback_fn*)world_post_run); + world->_on_error= (test_callback_error_fn*)world_on_error; + + world->collection_startup= (test_callback_fn*)world_container_startup; + world->collection_shutdown= (test_callback_fn*)world_container_shutdown; + + world->runner= &defualt_libmemcached_runner; +} diff --git a/tests/basic.cc b/tests/basic.cc index 85e96591..8f57e4c5 100644 --- a/tests/basic.cc +++ b/tests/basic.cc @@ -37,7 +37,9 @@ #include #include -#include + +#include + #include "tests/basic.h" #include diff --git a/tests/deprecated.cc b/tests/deprecated.cc index 03cfdaaa..eebc7d06 100644 --- a/tests/deprecated.cc +++ b/tests/deprecated.cc @@ -39,7 +39,7 @@ #include -#include +#include #include #include diff --git a/tests/error_conditions.cc b/tests/error_conditions.cc index 50a64da5..09a01eb4 100644 --- a/tests/error_conditions.cc +++ b/tests/error_conditions.cc @@ -41,7 +41,9 @@ #include #include -#include + +#include + #include test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *) diff --git a/tests/error_conditions.h b/tests/error_conditions.h index 1bfa9ed2..54991973 100644 --- a/tests/error_conditions.h +++ b/tests/error_conditions.h @@ -37,8 +37,6 @@ #pragma once -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/tests/hash_plus.cc b/tests/hash_plus.cc index 20cf79db..e3130786 100644 --- a/tests/hash_plus.cc +++ b/tests/hash_plus.cc @@ -4,7 +4,7 @@ #include -#include +#include #include #include @@ -93,7 +93,7 @@ static test_return_t set_function_test(void *) { hashkit_return_t rc= hashk.set_function(*algo); - test_true(rc == HASHKIT_SUCCESS); + test_compare(HASHKIT_SUCCESS, rc); uint32_t *list; switch (*algo) @@ -101,30 +101,38 @@ static test_return_t set_function_test(void *) case HASHKIT_HASH_DEFAULT: list= one_at_a_time_values; break; + case HASHKIT_HASH_MD5: list= md5_values; break; + case HASHKIT_HASH_CRC: list= crc_values; break; + case HASHKIT_HASH_FNV1_64: list= fnv1_64_values; break; + case HASHKIT_HASH_FNV1A_64: list= fnv1a_64_values; break; + case HASHKIT_HASH_FNV1_32: list= fnv1_32_values; break; + case HASHKIT_HASH_FNV1A_32: 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; @@ -134,9 +142,11 @@ static test_return_t set_function_test(void *) #endif list= murmur_values; break; + case HASHKIT_HASH_JENKINS: list= jenkins_values; break; + case HASHKIT_HASH_CUSTOM: case HASHKIT_HASH_MAX: default: @@ -195,14 +205,14 @@ static test_return_t compare_function_test(void *obj) } 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) }, - { "digest", 0, reinterpret_cast(digest_test) }, - { "set_function", 0, reinterpret_cast(set_function_test) }, - { "set_distribution_function", 0, reinterpret_cast(set_distribution_function_test) }, - { "compare", 0, reinterpret_cast(compare_function_test) }, + { "exists", 0, reinterpret_cast(exists_test) }, + { "new", 0, reinterpret_cast(new_test) }, + { "copy", 0, reinterpret_cast(copy_test) }, + { "assign", 0, reinterpret_cast(assign_test) }, + { "digest", 0, reinterpret_cast(digest_test) }, + { "set_function", 0, reinterpret_cast(set_function_test) }, + { "set_distribution_function", 0, reinterpret_cast(set_distribution_function_test) }, + { "compare", 0, reinterpret_cast(compare_function_test) }, { 0, 0, 0} }; @@ -211,7 +221,7 @@ collection_st collection[] ={ {0, 0, 0, 0} }; -void get_world(world_st *world) +void get_world(Framework *world) { world->collections= collection; } diff --git a/tests/hashkit_functions.c b/tests/hashkit_functions.c deleted file mode 100644 index 23feb9e5..00000000 --- a/tests/hashkit_functions.c +++ /dev/null @@ -1,602 +0,0 @@ -/* libHashKit Functions Test - * Copyright (C) 2006-2009 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 -#include -#include - -#include - -#include - -#include "hash_results.h" - -static hashkit_st global_hashk; - -/** - @brief hash_test_st is a structure we use in testing. It is currently empty. -*/ -typedef struct hash_test_st hash_test_st; - -struct hash_test_st -{ - bool _unused; -}; - -static test_return_t init_test(void *not_used) -{ - hashkit_st hashk; - hashkit_st *hashk_ptr; - (void)not_used; - - hashk_ptr= hashkit_create(&hashk); - test_true(hashk_ptr); - test_true(hashk_ptr == &hashk); - test_true(hashkit_is_allocated(hashk_ptr) == false); - - hashkit_free(hashk_ptr); - - return TEST_SUCCESS; -} - -static test_return_t allocation_test(void *not_used) -{ - hashkit_st *hashk_ptr; - (void)not_used; - - hashk_ptr= hashkit_create(NULL); - test_true(hashk_ptr); - test_true(hashkit_is_allocated(hashk_ptr) == true); - hashkit_free(hashk_ptr); - - return TEST_SUCCESS; -} - -static test_return_t clone_test(hashkit_st *hashk) -{ - // First we make sure that the testing system is giving us what we expect. - assert(&global_hashk == hashk); - - // Second we test if hashk is even valid - - /* All null? */ - { - hashkit_st *hashk_ptr; - hashk_ptr= hashkit_clone(NULL, NULL); - test_true(hashk_ptr); - test_true(hashkit_is_allocated(hashk_ptr)); - hashkit_free(hashk_ptr); - } - - /* Can we init from null? */ - { - hashkit_st *hashk_ptr; - - hashk_ptr= hashkit_clone(NULL, hashk); - - test_true(hashk_ptr); - test_true(hashkit_is_allocated(hashk_ptr)); - - hashkit_free(hashk_ptr); - } - - /* Can we init from struct? */ - { - hashkit_st declared_clone; - hashkit_st *hash_clone; - - hash_clone= hashkit_clone(&declared_clone, NULL); - test_true(hash_clone); - test_true(hash_clone == &declared_clone); - test_false(hashkit_is_allocated(hash_clone)); - - hashkit_free(hash_clone); - } - - /* Can we init from struct? */ - { - hashkit_st declared_clone; - hashkit_st *hash_clone; - - hash_clone= hashkit_clone(&declared_clone, hashk); - test_true(hash_clone); - test_true(hash_clone == &declared_clone); - test_false(hashkit_is_allocated(hash_clone)); - - hashkit_free(hash_clone); - } - - return TEST_SUCCESS; -} - -static test_return_t one_at_a_time_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_one_at_a_time(*ptr, strlen(*ptr)); - test_true(one_at_a_time_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t md5_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_md5(*ptr, strlen(*ptr)); - test_true(md5_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t crc_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_crc32(*ptr, strlen(*ptr)); - assert(crc_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t fnv1_64_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_fnv1_64(*ptr, strlen(*ptr)); - assert(fnv1_64_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t fnv1a_64_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_fnv1a_64(*ptr, strlen(*ptr)); - assert(fnv1a_64_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t fnv1_32_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_fnv1_32(*ptr, strlen(*ptr)); - assert(fnv1_32_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t fnv1a_32_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_fnv1a_32(*ptr, strlen(*ptr)); - assert(fnv1a_32_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t hsieh_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - -#ifdef HAVE_HSIEH_HASH - hash_val= libhashkit_hsieh(*ptr, strlen(*ptr)); -#else - hash_val= 1; -#endif - assert(hsieh_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t murmur_run (hashkit_st *hashk) -{ - (void)hashk; - -#ifdef WORDS_BIGENDIAN - (void)murmur_values; - return TEST_SKIPPED; -#else - uint32_t x; - const char **ptr; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - -#ifdef HAVE_MURMUR_HASH - hash_val= libhashkit_murmur(*ptr, strlen(*ptr)); -#else - hash_val= 1; -#endif - assert(murmur_values[x] == hash_val); - } - - return TEST_SUCCESS; -#endif -} - -static test_return_t jenkins_run (hashkit_st *hashk) -{ - uint32_t x; - const char **ptr; - (void)hashk; - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= libhashkit_jenkins(*ptr, strlen(*ptr)); - assert(jenkins_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - - - - -/** - @brief now we list out the tests. -*/ - -test_st allocation[]= { - {"init", 0, (test_callback_fn)init_test}, - {"create and free", 0, (test_callback_fn)allocation_test}, - {"clone", 0, (test_callback_fn)clone_test}, - {0, 0, 0} -}; - -static test_return_t hashkit_digest_test(hashkit_st *hashk) -{ - uint32_t value; - value= hashkit_digest(hashk, "a", sizeof("a")); - - return TEST_SUCCESS; -} - -static test_return_t hashkit_set_function_test(hashkit_st *hashk) -{ - for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++) - { - hashkit_return_t rc; - uint32_t x; - const char **ptr; - uint32_t *list; - - rc= hashkit_set_function(hashk, algo); - - /* Hsieh is disabled most of the time for patent issues */ -#ifndef HAVE_HSIEH_HASH - if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH) - continue; -#endif - -#ifndef HAVE_MURMUR_HASH - if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_MURMUR) - continue; -#endif - - if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM) - continue; - - test_true_got(rc == HASHKIT_SUCCESS, hashkit_strerror(NULL, rc)); - - switch (algo) - { - case HASHKIT_HASH_DEFAULT: - list= one_at_a_time_values; - break; - case HASHKIT_HASH_MD5: - list= md5_values; - break; - case HASHKIT_HASH_CRC: - list= crc_values; - break; - case HASHKIT_HASH_FNV1_64: - list= fnv1_64_values; - break; - case HASHKIT_HASH_FNV1A_64: - list= fnv1a_64_values; - break; - case HASHKIT_HASH_FNV1_32: - list= fnv1_32_values; - break; - case HASHKIT_HASH_FNV1A_32: - list= fnv1a_32_values; - break; - case HASHKIT_HASH_HSIEH: - list= hsieh_values; - break; - case HASHKIT_HASH_MURMUR: - list= murmur_values; - break; - case HASHKIT_HASH_JENKINS: - list= jenkins_values; - break; - case HASHKIT_HASH_CUSTOM: - case HASHKIT_HASH_MAX: - default: - list= NULL; - break; - } - - // Now we make sure we did set the hash correctly. - if (list) - { - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr)); - test_true(list[x] == hash_val); - } - } - else - { - return TEST_FAILURE; - } - } - - return TEST_SUCCESS; -} - -static uint32_t hash_test_function(const char *string, size_t string_length, void *context) -{ - (void)context; - return libhashkit_md5(string, string_length); -} - -static test_return_t hashkit_set_custom_function_test(hashkit_st *hashk) -{ - hashkit_return_t rc; - uint32_t x; - const char **ptr; - - - rc= hashkit_set_custom_function(hashk, hash_test_function, NULL); - test_true(rc == HASHKIT_SUCCESS); - - for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) - { - uint32_t hash_val; - - hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr)); - test_true(md5_values[x] == hash_val); - } - - return TEST_SUCCESS; -} - -static test_return_t hashkit_set_distribution_function_test(hashkit_st *hashk) -{ - for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++) - { - hashkit_return_t rc; - - rc= hashkit_set_distribution_function(hashk, algo); - - /* Hsieh is disabled most of the time for patent issues */ - if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH) - continue; - - if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM) - continue; - - test_true(rc == HASHKIT_SUCCESS); - } - - return TEST_SUCCESS; -} - -static test_return_t hashkit_set_custom_distribution_function_test(hashkit_st *hashk) -{ - hashkit_return_t rc; - - rc= hashkit_set_custom_distribution_function(hashk, hash_test_function, NULL); - test_true(rc == HASHKIT_SUCCESS); - - return TEST_SUCCESS; -} - - -static test_return_t hashkit_get_function_test(hashkit_st *hashk) -{ - for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++) - { - hashkit_return_t rc; - - if (HASHKIT_HASH_CUSTOM || HASHKIT_HASH_HSIEH) - continue; - - rc= hashkit_set_function(hashk, algo); - test_true(rc == HASHKIT_SUCCESS); - - test_true(hashkit_get_function(hashk) == algo); - } - return TEST_SUCCESS; -} - -static test_return_t hashkit_compare_test(hashkit_st *hashk) -{ - hashkit_st *clone; - - clone= hashkit_clone(NULL, hashk); - - test_true(hashkit_compare(clone, hashk)); - hashkit_free(clone); - - return TEST_SUCCESS; -} - -test_st hashkit_st_functions[] ={ - {"hashkit_digest", 0, (test_callback_fn)hashkit_digest_test}, - {"hashkit_set_function", 0, (test_callback_fn)hashkit_set_function_test}, - {"hashkit_set_custom_function", 0, (test_callback_fn)hashkit_set_custom_function_test}, - {"hashkit_get_function", 0, (test_callback_fn)hashkit_get_function_test}, - {"hashkit_set_distribution_function", 0, (test_callback_fn)hashkit_set_distribution_function_test}, - {"hashkit_set_custom_distribution_function", 0, (test_callback_fn)hashkit_set_custom_distribution_function_test}, - {"hashkit_compare", 0, (test_callback_fn)hashkit_compare_test}, - {0, 0, 0} -}; - -static test_return_t libhashkit_digest_test(hashkit_st *hashk) -{ - uint32_t value; - - (void)hashk; - - value= libhashkit_digest("a", sizeof("a"), HASHKIT_HASH_DEFAULT); - - return TEST_SUCCESS; -} - -test_st library_functions[] ={ - {"libhashkit_digest", 0, (test_callback_fn)libhashkit_digest_test}, - {0, 0, 0} -}; - -test_st hash_tests[] ={ - {"one_at_a_time", 0, (test_callback_fn)one_at_a_time_run }, - {"md5", 0, (test_callback_fn)md5_run }, - {"crc", 0, (test_callback_fn)crc_run }, - {"fnv1_64", 0, (test_callback_fn)fnv1_64_run }, - {"fnv1a_64", 0, (test_callback_fn)fnv1a_64_run }, - {"fnv1_32", 0, (test_callback_fn)fnv1_32_run }, - {"fnv1a_32", 0, (test_callback_fn)fnv1a_32_run }, - {"hsieh", 0, (test_callback_fn)hsieh_run }, - {"murmur", 0, (test_callback_fn)murmur_run }, - {"jenkis", 0, (test_callback_fn)jenkins_run }, - {0, 0, (test_callback_fn)0} -}; - -/* - * The following test suite is used to verify that we don't introduce - * regression bugs. If you want more information about the bug / test, - * you should look in the bug report at - * http://bugs.launchpad.net/libmemcached - */ -test_st regression[]= { - {0, 0, 0} -}; - -collection_st collection[] ={ - {"allocation", 0, 0, allocation}, - {"hashkit_st_functions", 0, 0, hashkit_st_functions}, - {"library_functions", 0, 0, library_functions}, - {"hashing", 0, 0, hash_tests}, - {"regression", 0, 0, regression}, - {0, 0, 0, 0} -}; - -/* Prototypes for functions we will pass to test framework */ -void *world_create(test_return_t *error); -test_return_t world_destroy(hashkit_st *hashk); - -void *world_create(test_return_t *error) -{ - hashkit_st *hashk_ptr; - - hashk_ptr= hashkit_create(&global_hashk); - - if (hashk_ptr != &global_hashk) - { - *error= TEST_FAILURE; - return NULL; - } - - if (hashkit_is_allocated(hashk_ptr) == true) - { - *error= TEST_FAILURE; - return NULL; - } - - *error= TEST_SUCCESS; - - return hashk_ptr; -} - - -test_return_t world_destroy(hashkit_st *hashk) -{ - // Did we get back what we expected? - assert(hashkit_is_allocated(hashk) == false); - hashkit_free(&global_hashk); - - return TEST_SUCCESS; -} - -void get_world(world_st *world) -{ - world->collections= collection; - world->create= (test_callback_create_fn)world_create; - world->destroy= (test_callback_fn)world_destroy; -} diff --git a/tests/hashkit_functions.cc b/tests/hashkit_functions.cc new file mode 100644 index 00000000..98396df5 --- /dev/null +++ b/tests/hashkit_functions.cc @@ -0,0 +1,621 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * libHashKit Functions Test + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-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. + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#include + +#include + +#include "hash_results.h" + +static hashkit_st global_hashk; + +/** + @brief hash_test_st is a structure we use in testing. It is currently empty. +*/ +typedef struct hash_test_st hash_test_st; + +struct hash_test_st +{ + bool _unused; +}; + +static test_return_t init_test(void *not_used) +{ + hashkit_st hashk; + hashkit_st *hashk_ptr; + (void)not_used; + + hashk_ptr= hashkit_create(&hashk); + test_true(hashk_ptr); + test_true(hashk_ptr == &hashk); + test_true(hashkit_is_allocated(hashk_ptr) == false); + + hashkit_free(hashk_ptr); + + return TEST_SUCCESS; +} + +static test_return_t allocation_test(void *not_used) +{ + hashkit_st *hashk_ptr; + (void)not_used; + + hashk_ptr= hashkit_create(NULL); + test_true(hashk_ptr); + test_true(hashkit_is_allocated(hashk_ptr) == true); + hashkit_free(hashk_ptr); + + return TEST_SUCCESS; +} + +static test_return_t clone_test(hashkit_st *hashk) +{ + // First we make sure that the testing system is giving us what we expect. + assert(&global_hashk == hashk); + + // Second we test if hashk is even valid + + /* All null? */ + { + hashkit_st *hashk_ptr; + hashk_ptr= hashkit_clone(NULL, NULL); + test_true(hashk_ptr); + test_true(hashkit_is_allocated(hashk_ptr)); + hashkit_free(hashk_ptr); + } + + /* Can we init from null? */ + { + hashkit_st *hashk_ptr; + + hashk_ptr= hashkit_clone(NULL, hashk); + + test_true(hashk_ptr); + test_true(hashkit_is_allocated(hashk_ptr)); + + hashkit_free(hashk_ptr); + } + + /* Can we init from struct? */ + { + hashkit_st declared_clone; + hashkit_st *hash_clone; + + hash_clone= hashkit_clone(&declared_clone, NULL); + test_true(hash_clone); + test_true(hash_clone == &declared_clone); + test_false(hashkit_is_allocated(hash_clone)); + + hashkit_free(hash_clone); + } + + /* Can we init from struct? */ + { + hashkit_st declared_clone; + hashkit_st *hash_clone; + + hash_clone= hashkit_clone(&declared_clone, hashk); + test_true(hash_clone); + test_true(hash_clone == &declared_clone); + test_false(hashkit_is_allocated(hash_clone)); + + hashkit_free(hash_clone); + } + + return TEST_SUCCESS; +} + +static test_return_t one_at_a_time_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_one_at_a_time(*ptr, strlen(*ptr)); + test_true(one_at_a_time_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t md5_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_md5(*ptr, strlen(*ptr)); + test_true(md5_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t crc_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_crc32(*ptr, strlen(*ptr)); + assert(crc_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t fnv1_64_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_fnv1_64(*ptr, strlen(*ptr)); + assert(fnv1_64_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t fnv1a_64_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_fnv1a_64(*ptr, strlen(*ptr)); + assert(fnv1a_64_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t fnv1_32_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_fnv1_32(*ptr, strlen(*ptr)); + assert(fnv1_32_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t fnv1a_32_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_fnv1a_32(*ptr, strlen(*ptr)); + assert(fnv1a_32_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t hsieh_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + +#ifdef HAVE_HSIEH_HASH + hash_val= libhashkit_hsieh(*ptr, strlen(*ptr)); +#else + hash_val= 1; +#endif + assert(hsieh_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t murmur_run (hashkit_st *hashk) +{ + (void)hashk; + +#ifdef WORDS_BIGENDIAN + (void)murmur_values; + return TEST_SKIPPED; +#else + uint32_t x; + const char **ptr; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + +#ifdef HAVE_MURMUR_HASH + hash_val= libhashkit_murmur(*ptr, strlen(*ptr)); +#else + hash_val= 1; +#endif + assert(murmur_values[x] == hash_val); + } + + return TEST_SUCCESS; +#endif +} + +static test_return_t jenkins_run (hashkit_st *hashk) +{ + uint32_t x; + const char **ptr; + (void)hashk; + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= libhashkit_jenkins(*ptr, strlen(*ptr)); + assert(jenkins_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + + + + +/** + @brief now we list out the tests. +*/ + +test_st allocation[]= { + {"init", 0, (test_callback_fn*)init_test}, + {"create and free", 0, (test_callback_fn*)allocation_test}, + {"clone", 0, (test_callback_fn*)clone_test}, + {0, 0, 0} +}; + +static test_return_t hashkit_digest_test(hashkit_st *hashk) +{ + uint32_t value; + value= hashkit_digest(hashk, "a", sizeof("a")); + + return TEST_SUCCESS; +} + +static test_return_t hashkit_set_function_test(hashkit_st *hashk) +{ + for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++) + { + uint32_t x; + const char **ptr; + uint32_t *list; + + hashkit_return_t rc= hashkit_set_function(hashk, static_cast(algo)); + + /* Hsieh is disabled most of the time for patent issues */ +#ifndef HAVE_HSIEH_HASH + if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH) + continue; +#endif + +#ifndef HAVE_MURMUR_HASH + if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_MURMUR) + continue; +#endif + + if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM) + continue; + + test_true_got(rc == HASHKIT_SUCCESS, hashkit_strerror(NULL, rc)); + + switch (algo) + { + case HASHKIT_HASH_DEFAULT: + list= one_at_a_time_values; + break; + case HASHKIT_HASH_MD5: + list= md5_values; + break; + case HASHKIT_HASH_CRC: + list= crc_values; + break; + case HASHKIT_HASH_FNV1_64: + list= fnv1_64_values; + break; + case HASHKIT_HASH_FNV1A_64: + list= fnv1a_64_values; + break; + case HASHKIT_HASH_FNV1_32: + list= fnv1_32_values; + break; + case HASHKIT_HASH_FNV1A_32: + list= fnv1a_32_values; + break; + case HASHKIT_HASH_HSIEH: + list= hsieh_values; + break; + case HASHKIT_HASH_MURMUR: + list= murmur_values; + break; + case HASHKIT_HASH_JENKINS: + list= jenkins_values; + break; + case HASHKIT_HASH_CUSTOM: + case HASHKIT_HASH_MAX: + default: + list= NULL; + break; + } + + // Now we make sure we did set the hash correctly. + if (list) + { + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr)); + test_true(list[x] == hash_val); + } + } + else + { + return TEST_FAILURE; + } + } + + return TEST_SUCCESS; +} + +static uint32_t hash_test_function(const char *string, size_t string_length, void *context) +{ + (void)context; + return libhashkit_md5(string, string_length); +} + +static test_return_t hashkit_set_custom_function_test(hashkit_st *hashk) +{ + hashkit_return_t rc; + uint32_t x; + const char **ptr; + + + rc= hashkit_set_custom_function(hashk, hash_test_function, NULL); + test_true(rc == HASHKIT_SUCCESS); + + for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) + { + uint32_t hash_val; + + hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr)); + test_true(md5_values[x] == hash_val); + } + + return TEST_SUCCESS; +} + +static test_return_t hashkit_set_distribution_function_test(hashkit_st *hashk) +{ + for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++) + { + hashkit_return_t rc= hashkit_set_distribution_function(hashk, static_cast(algo)); + + /* Hsieh is disabled most of the time for patent issues */ + if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH) + continue; + + if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM) + continue; + + test_true(rc == HASHKIT_SUCCESS); + } + + return TEST_SUCCESS; +} + +static test_return_t hashkit_set_custom_distribution_function_test(hashkit_st *hashk) +{ + hashkit_return_t rc= hashkit_set_custom_distribution_function(hashk, hash_test_function, NULL); + test_true(rc == HASHKIT_SUCCESS); + + return TEST_SUCCESS; +} + + +static test_return_t hashkit_get_function_test(hashkit_st *hashk) +{ + for (int algo= int(HASHKIT_HASH_DEFAULT); algo < int(HASHKIT_HASH_MAX); algo++) + { + + if (HASHKIT_HASH_CUSTOM or HASHKIT_HASH_HSIEH) + continue; + + hashkit_return_t rc= hashkit_set_function(hashk, static_cast(algo)); + test_true(rc == HASHKIT_SUCCESS); + + test_true(hashkit_get_function(hashk) == algo); + } + return TEST_SUCCESS; +} + +static test_return_t hashkit_compare_test(hashkit_st *hashk) +{ + hashkit_st *clone= hashkit_clone(NULL, hashk); + + test_true(hashkit_compare(clone, hashk)); + hashkit_free(clone); + + return TEST_SUCCESS; +} + +test_st hashkit_st_functions[] ={ + {"hashkit_digest", 0, (test_callback_fn*)hashkit_digest_test}, + {"hashkit_set_function", 0, (test_callback_fn*)hashkit_set_function_test}, + {"hashkit_set_custom_function", 0, (test_callback_fn*)hashkit_set_custom_function_test}, + {"hashkit_get_function", 0, (test_callback_fn*)hashkit_get_function_test}, + {"hashkit_set_distribution_function", 0, (test_callback_fn*)hashkit_set_distribution_function_test}, + {"hashkit_set_custom_distribution_function", 0, (test_callback_fn*)hashkit_set_custom_distribution_function_test}, + {"hashkit_compare", 0, (test_callback_fn*)hashkit_compare_test}, + {0, 0, 0} +}; + +static test_return_t libhashkit_digest_test(hashkit_st *hashk) +{ + + (void)hashk; + + uint32_t value= libhashkit_digest("a", sizeof("a"), HASHKIT_HASH_DEFAULT); + test_true(value); + + return TEST_SUCCESS; +} + +test_st library_functions[] ={ + {"libhashkit_digest", 0, (test_callback_fn*)libhashkit_digest_test}, + {0, 0, 0} +}; + +test_st hash_tests[] ={ + {"one_at_a_time", 0, (test_callback_fn*)one_at_a_time_run }, + {"md5", 0, (test_callback_fn*)md5_run }, + {"crc", 0, (test_callback_fn*)crc_run }, + {"fnv1_64", 0, (test_callback_fn*)fnv1_64_run }, + {"fnv1a_64", 0, (test_callback_fn*)fnv1a_64_run }, + {"fnv1_32", 0, (test_callback_fn*)fnv1_32_run }, + {"fnv1a_32", 0, (test_callback_fn*)fnv1a_32_run }, + {"hsieh", 0, (test_callback_fn*)hsieh_run }, + {"murmur", 0, (test_callback_fn*)murmur_run }, + {"jenkis", 0, (test_callback_fn*)jenkins_run }, + {0, 0, (test_callback_fn*)0} +}; + +/* + * The following test suite is used to verify that we don't introduce + * regression bugs. If you want more information about the bug / test, + * you should look in the bug report at + * http://bugs.launchpad.net/libmemcached + */ +test_st regression[]= { + {0, 0, 0} +}; + +collection_st collection[] ={ + {"allocation", 0, 0, allocation}, + {"hashkit_st_functions", 0, 0, hashkit_st_functions}, + {"library_functions", 0, 0, library_functions}, + {"hashing", 0, 0, hash_tests}, + {"regression", 0, 0, regression}, + {0, 0, 0, 0} +}; + +/* Prototypes for functions we will pass to test framework */ +void *world_create(test_return_t *error); +test_return_t world_destroy(hashkit_st *hashk); + +void *world_create(test_return_t *error) +{ + hashkit_st *hashk_ptr= hashkit_create(&global_hashk); + + if (hashk_ptr != &global_hashk) + { + *error= TEST_FAILURE; + return NULL; + } + + if (hashkit_is_allocated(hashk_ptr) == true) + { + *error= TEST_FAILURE; + return NULL; + } + + *error= TEST_SUCCESS; + + return hashk_ptr; +} + + +test_return_t world_destroy(hashkit_st *hashk) +{ + // Did we get back what we expected? + assert(hashkit_is_allocated(hashk) == false); + hashkit_free(&global_hashk); + + return TEST_SUCCESS; +} + +void get_world(Framework *world) +{ + world->collections= collection; + world->_create= (test_callback_create_fn*)world_create; + world->_destroy= (test_callback_fn*)world_destroy; +} diff --git a/tests/include.am b/tests/include.am index abcc0f33..7ce21a12 100644 --- a/tests/include.am +++ b/tests/include.am @@ -84,23 +84,23 @@ tests_testplus_DEPENDENCIES= $(TESTS_LDADDS) tests_testplus_LDADD= $(tests_testplus_DEPENDENCIES) $(LIBSASL) check_PROGRAMS+= tests/testplus -tests_atomsmasher_SOURCES= tests/atomsmasher.c +tests_atomsmasher_SOURCES= tests/atomsmasher.cc tests_atomsmasher_SOURCES+= clients/generator.cc clients/execute.cc tests_atomsmasher_DEPENDENCIES= $(TESTS_LDADDS) tests_atomsmasher_LDADD= $(tests_atomsmasher_DEPENDENCIES) $(LIBSASL) tests_testudp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING) -tests_testudp_SOURCES= tests/mem_udp.c +tests_testudp_SOURCES= tests/mem_udp.cc tests_testudp_DEPENDENCIES= $(TESTS_LDADDS) tests_testudp_LDADD= $(tests_testudp_DEPENDENCIES) $(LIBSASL) -tests_startservers_SOURCES= tests/start.c +tests_startservers_SOURCES= tests/start.cc tests_startservers_DEPENDENCIES= $(TESTS_LDADDS) tests_startservers_LDADD= $(tests_startservers_DEPENDENCIES) $(LIBSASL) -tests_testhashkit_SOURCES = tests/hashkit_functions.c +tests_testhashkit_SOURCES = tests/hashkit_functions.cc tests_testhashkit_DEPENDENCIES = libtest/libtest.la libhashkit/libhashkit.la tests_testhashkit_LDADD = $(tests_testhashkit_DEPENDENCIES) diff --git a/tests/libmemcached_world.h b/tests/libmemcached_world.h index 4793569c..fc0b6ae8 100644 --- a/tests/libmemcached_world.h +++ b/tests/libmemcached_world.h @@ -14,12 +14,19 @@ extern "C" { #endif /* The structure we use for the test system */ -typedef struct +struct libmemcached_test_container_st { server_startup_st construct; memcached_st *parent; memcached_st *memc; -} libmemcached_test_container_st; + + libmemcached_test_container_st() : + parent(NULL), + memc(NULL) + { + memset(&construct, 0, sizeof(server_startup_st)); + } +}; /* Prototypes for functions we will pass to test framework */ libmemcached_test_container_st *world_create(test_return_t *error); @@ -41,12 +48,11 @@ test_return_t world_container_shutdown(libmemcached_test_container_st *container libmemcached_test_container_st *world_create(test_return_t *error) { - memset(&global_container, 0, sizeof(global_container)); global_container.construct.count= SERVERS_TO_CREATE; global_container.construct.udp= 0; server_startup(&global_container.construct); - if (! global_container.construct.servers) + if (not global_container.construct.servers) { *error= TEST_FAILURE; server_shutdown(&global_container.construct); @@ -60,12 +66,11 @@ libmemcached_test_container_st *world_create(test_return_t *error) test_return_t world_container_startup(libmemcached_test_container_st *container) { - memcached_return_t rc; container->parent= memcached_create(NULL); test_true((container->parent != NULL)); - rc= memcached_server_push(container->parent, container->construct.servers); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(MEMCACHED_SUCCESS, + memcached_server_push(container->parent, container->construct.servers)); return TEST_SUCCESS; } @@ -101,8 +106,8 @@ test_return_t world_pre_run(libmemcached_test_container_st *container) memcached_server_instance_st instance= memcached_server_instance_by_position(container->memc, loop); - test_true(instance->fd == -1); - test_true(instance->cursor_active == 0); + test_compare(-1, instance->fd); + test_compare(0, instance->cursor_active); } return TEST_SUCCESS; @@ -183,15 +188,15 @@ static test_return_t _post_runner_default(libmemcached_test_callback_fn func, li #ifdef __cplusplus -static world_runner_st defualt_libmemcached_runner= { - reinterpret_cast(_pre_runner_default), - reinterpret_cast(_runner_default), - reinterpret_cast(_post_runner_default) +static Runner defualt_libmemcached_runner= { + reinterpret_cast(_pre_runner_default), + reinterpret_cast(_runner_default), + reinterpret_cast(_post_runner_default) }; #else -static world_runner_st defualt_libmemcached_runner= { +static Runner defualt_libmemcached_runner= { (test_callback_runner_fn)_pre_runner_default, (test_callback_runner_fn)_runner_default, (test_callback_runner_fn)_post_runner_default diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index f963582e..c1bb70fe 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -63,7 +63,7 @@ #define SMALL_STRING_LEN 1024 -#include +#include #include "tests/deprecated.h" #include "tests/parser.h" #include "tests/pool.h" @@ -1880,7 +1880,7 @@ static test_return_t get_stats(memcached_st *memc) { char **stat_list= memcached_stat_get_keys(memc, memc_stat+x, &rc); test_compare(MEMCACHED_SUCCESS, rc); - for (char **ptr= stat_list; *ptr; ptr++); + for (char **ptr= stat_list; *ptr; ptr++) {}; free(stat_list); } @@ -2271,7 +2271,7 @@ static test_return_t user_supplied_bug3(memcached_st *memc) keys[x]= strdup(key); test_true(keys[x]); key_lengths[x]= key_length; - test_compare(key_length, strlen(keys[x])); + test_compare(size_t(key_length), strlen(keys[x])); } test_compare(MEMCACHED_SUCCESS, @@ -3909,32 +3909,32 @@ static test_return_t set_prefix(memcached_st *memc) /* Make sure be default none exists */ value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); - test_true(rc == MEMCACHED_FAILURE); + test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc)); /* Test a clean set */ rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key); - test_true_got(rc == MEMCACHED_SUCCESS, memcached_last_error_message(memc)); + test_compare_got(MEMCACHED_SUCCESS, rc , memcached_last_error_message(memc)); value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); test_true(value); test_memcmp(value, key, 4); - test_compare(MEMCACHED_SUCCESS, rc); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); /* Test that we can turn it off */ rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL); - test_compare(MEMCACHED_SUCCESS, rc); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); test_false(value); - test_true(rc == MEMCACHED_FAILURE); + test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc)); /* Now setup for main test */ rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key); - test_compare(MEMCACHED_SUCCESS, rc); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); value= (char *)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc); test_true(value); - test_compare(MEMCACHED_SUCCESS, rc); + test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc)); test_memcmp(value, key, 4); /* Set to Zero, and then Set to something too large */ @@ -5845,6 +5845,10 @@ static test_return_t regression_bug_655423(memcached_st *memc) test_true(clone); char payload[100]; +#ifdef __APPLE__ + return TEST_SKIPPED; +#endif + test_skip(MEMCACHED_SUCCESS, memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)); test_skip(MEMCACHED_SUCCESS, memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1)); test_skip(MEMCACHED_SUCCESS, memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1)); @@ -5854,7 +5858,7 @@ static test_return_t regression_bug_655423(memcached_st *memc) for (uint32_t x= 0; x < regression_bug_655423_COUNT; x++) { - char key[1024]; + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1]; snprintf(key, sizeof(key), "%u", x); test_compare(MEMCACHED_SUCCESS, memcached_set(clone, key, strlen(key), payload, sizeof(payload), 0, 0)); @@ -5862,7 +5866,7 @@ static test_return_t regression_bug_655423(memcached_st *memc) for (uint32_t x= 0; x < regression_bug_655423_COUNT; x++) { - char key[1024]; + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1]; snprintf(key, sizeof(key), "%u", x); size_t value_length; @@ -5886,11 +5890,13 @@ static test_return_t regression_bug_655423(memcached_st *memc) size_t *key_length= (size_t *)calloc(regression_bug_655423_COUNT, sizeof(size_t)); for (uint32_t x= 0; x < regression_bug_655423_COUNT; x++) { - char key[1024]; + char key[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1]; snprintf(key, sizeof(key), "%u", x); keys[x]= strdup(key); + test_true(keys[x]); key_length[x]= strlen(key); + test_true(key_length[x]); } memcached_return_t rc; @@ -6105,155 +6111,155 @@ static test_return_t sasl_auth_test(memcached_st *memc) /* Clean the server before beginning testing */ test_st tests[] ={ - {"util_version", 1, (test_callback_fn)util_version_test }, - {"flush", 0, (test_callback_fn)flush_test }, - {"init", 0, (test_callback_fn)init_test }, - {"allocation", 0, (test_callback_fn)allocation_test }, - {"server_list_null_test", 0, (test_callback_fn)server_list_null_test}, - {"server_unsort", 0, (test_callback_fn)server_unsort_test}, - {"server_sort", 0, (test_callback_fn)server_sort_test}, - {"server_sort2", 0, (test_callback_fn)server_sort2_test}, - {"memcached_server_remove", 0, (test_callback_fn)memcached_server_remove_test}, - {"clone_test", 0, (test_callback_fn)clone_test }, - {"connection_test", 0, (test_callback_fn)connection_test}, - {"callback_test", 0, (test_callback_fn)callback_test}, - {"userdata_test", 0, (test_callback_fn)userdata_test}, - {"error", 0, (test_callback_fn)error_test }, - {"set", 0, (test_callback_fn)set_test }, - {"set2", 0, (test_callback_fn)set_test2 }, - {"set3", 0, (test_callback_fn)set_test3 }, - {"dump", 1, (test_callback_fn)dump_test}, - {"add", 1, (test_callback_fn)add_test }, - {"memcached_fetch_result(MEMCACHED_NOTFOUND)", 1, (test_callback_fn)memcached_fetch_result_NOT_FOUND }, - {"replace", 1, (test_callback_fn)replace_test }, - {"delete", 1, (test_callback_fn)delete_test }, - {"get", 1, (test_callback_fn)get_test }, - {"get2", 0, (test_callback_fn)get_test2 }, - {"get3", 0, (test_callback_fn)get_test3 }, - {"get4", 0, (test_callback_fn)get_test4 }, - {"partial mget", 0, (test_callback_fn)get_test5 }, - {"stats_servername", 0, (test_callback_fn)stats_servername_test }, - {"increment", 0, (test_callback_fn)increment_test }, - {"increment_with_initial", 1, (test_callback_fn)increment_with_initial_test }, - {"decrement", 0, (test_callback_fn)decrement_test }, - {"decrement_with_initial", 1, (test_callback_fn)decrement_with_initial_test }, - {"increment_by_key", 0, (test_callback_fn)increment_by_key_test }, - {"increment_with_initial_by_key", 1, (test_callback_fn)increment_with_initial_by_key_test }, - {"decrement_by_key", 0, (test_callback_fn)decrement_by_key_test }, - {"decrement_with_initial_by_key", 1, (test_callback_fn)decrement_with_initial_by_key_test }, - {"quit", 0, (test_callback_fn)quit_test }, - {"mget", 1, (test_callback_fn)mget_test }, - {"mget_result", 1, (test_callback_fn)mget_result_test }, - {"mget_result_alloc", 1, (test_callback_fn)mget_result_alloc_test }, - {"mget_result_function", 1, (test_callback_fn)mget_result_function }, - {"mget_execute", 1, (test_callback_fn)mget_execute }, - {"mget_end", 0, (test_callback_fn)mget_end }, - {"get_stats", 0, (test_callback_fn)get_stats }, - {"add_host_test", 0, (test_callback_fn)add_host_test }, - {"add_host_test_1", 0, (test_callback_fn)add_host_test1 }, - {"get_stats_keys", 0, (test_callback_fn)get_stats_keys }, - {"version_string_test", 0, (test_callback_fn)version_string_test}, - {"bad_key", 1, (test_callback_fn)bad_key_test }, - {"memcached_server_cursor", 1, (test_callback_fn)memcached_server_cursor_test }, - {"read_through", 1, (test_callback_fn)read_through }, - {"delete_through", 1, (test_callback_fn)delete_through }, - {"noreply", 1, (test_callback_fn)noreply_test}, - {"analyzer", 1, (test_callback_fn)analyzer_test}, - {"connectionpool", 1, (test_callback_fn)connection_pool_test }, - {"memcached_pool_test", 1, (test_callback_fn)memcached_pool_test }, - {"ping", 1, (test_callback_fn)ping_test }, - {"test_get_last_disconnect", 1, (test_callback_fn)test_get_last_disconnect}, - {"verbosity", 1, (test_callback_fn)test_verbosity}, - {"test_server_failure", 1, (test_callback_fn)test_server_failure}, - {"cull_servers", 1, (test_callback_fn)test_cull_servers}, - {"memcached_stat_execute", 1, (test_callback_fn)memcached_stat_execute_test}, + {"util_version", 1, (test_callback_fn*)util_version_test }, + {"flush", 0, (test_callback_fn*)flush_test }, + {"init", 0, (test_callback_fn*)init_test }, + {"allocation", 0, (test_callback_fn*)allocation_test }, + {"server_list_null_test", 0, (test_callback_fn*)server_list_null_test}, + {"server_unsort", 0, (test_callback_fn*)server_unsort_test}, + {"server_sort", 0, (test_callback_fn*)server_sort_test}, + {"server_sort2", 0, (test_callback_fn*)server_sort2_test}, + {"memcached_server_remove", 0, (test_callback_fn*)memcached_server_remove_test}, + {"clone_test", 0, (test_callback_fn*)clone_test }, + {"connection_test", 0, (test_callback_fn*)connection_test}, + {"callback_test", 0, (test_callback_fn*)callback_test}, + {"userdata_test", 0, (test_callback_fn*)userdata_test}, + {"error", 0, (test_callback_fn*)error_test }, + {"set", 0, (test_callback_fn*)set_test }, + {"set2", 0, (test_callback_fn*)set_test2 }, + {"set3", 0, (test_callback_fn*)set_test3 }, + {"dump", 1, (test_callback_fn*)dump_test}, + {"add", 1, (test_callback_fn*)add_test }, + {"memcached_fetch_result(MEMCACHED_NOTFOUND)", 1, (test_callback_fn*)memcached_fetch_result_NOT_FOUND }, + {"replace", 1, (test_callback_fn*)replace_test }, + {"delete", 1, (test_callback_fn*)delete_test }, + {"get", 1, (test_callback_fn*)get_test }, + {"get2", 0, (test_callback_fn*)get_test2 }, + {"get3", 0, (test_callback_fn*)get_test3 }, + {"get4", 0, (test_callback_fn*)get_test4 }, + {"partial mget", 0, (test_callback_fn*)get_test5 }, + {"stats_servername", 0, (test_callback_fn*)stats_servername_test }, + {"increment", 0, (test_callback_fn*)increment_test }, + {"increment_with_initial", 1, (test_callback_fn*)increment_with_initial_test }, + {"decrement", 0, (test_callback_fn*)decrement_test }, + {"decrement_with_initial", 1, (test_callback_fn*)decrement_with_initial_test }, + {"increment_by_key", 0, (test_callback_fn*)increment_by_key_test }, + {"increment_with_initial_by_key", 1, (test_callback_fn*)increment_with_initial_by_key_test }, + {"decrement_by_key", 0, (test_callback_fn*)decrement_by_key_test }, + {"decrement_with_initial_by_key", 1, (test_callback_fn*)decrement_with_initial_by_key_test }, + {"quit", 0, (test_callback_fn*)quit_test }, + {"mget", 1, (test_callback_fn*)mget_test }, + {"mget_result", 1, (test_callback_fn*)mget_result_test }, + {"mget_result_alloc", 1, (test_callback_fn*)mget_result_alloc_test }, + {"mget_result_function", 1, (test_callback_fn*)mget_result_function }, + {"mget_execute", 1, (test_callback_fn*)mget_execute }, + {"mget_end", 0, (test_callback_fn*)mget_end }, + {"get_stats", 0, (test_callback_fn*)get_stats }, + {"add_host_test", 0, (test_callback_fn*)add_host_test }, + {"add_host_test_1", 0, (test_callback_fn*)add_host_test1 }, + {"get_stats_keys", 0, (test_callback_fn*)get_stats_keys }, + {"version_string_test", 0, (test_callback_fn*)version_string_test}, + {"bad_key", 1, (test_callback_fn*)bad_key_test }, + {"memcached_server_cursor", 1, (test_callback_fn*)memcached_server_cursor_test }, + {"read_through", 1, (test_callback_fn*)read_through }, + {"delete_through", 1, (test_callback_fn*)delete_through }, + {"noreply", 1, (test_callback_fn*)noreply_test}, + {"analyzer", 1, (test_callback_fn*)analyzer_test}, + {"connectionpool", 1, (test_callback_fn*)connection_pool_test }, + {"memcached_pool_test", 1, (test_callback_fn*)memcached_pool_test }, + {"ping", 1, (test_callback_fn*)ping_test }, + {"test_get_last_disconnect", 1, (test_callback_fn*)test_get_last_disconnect}, + {"verbosity", 1, (test_callback_fn*)test_verbosity}, + {"test_server_failure", 1, (test_callback_fn*)test_server_failure}, + {"cull_servers", 1, (test_callback_fn*)test_cull_servers}, + {"memcached_stat_execute", 1, (test_callback_fn*)memcached_stat_execute_test}, {0, 0, 0} }; test_st behavior_tests[] ={ - {"libmemcached_string_behavior()", 0, (test_callback_fn)libmemcached_string_behavior_test}, - {"libmemcached_string_distribution()", 0, (test_callback_fn)libmemcached_string_distribution_test}, - {"behavior_test", 0, (test_callback_fn)behavior_test}, - {"MEMCACHED_BEHAVIOR_CORK", 0, (test_callback_fn)MEMCACHED_BEHAVIOR_CORK_test}, - {"MEMCACHED_BEHAVIOR_TCP_KEEPALIVE", 0, (test_callback_fn)MEMCACHED_BEHAVIOR_TCP_KEEPALIVE_test}, - {"MEMCACHED_BEHAVIOR_TCP_KEEPIDLE", 0, (test_callback_fn)MEMCACHED_BEHAVIOR_TCP_KEEPIDLE_test}, + {"libmemcached_string_behavior()", 0, (test_callback_fn*)libmemcached_string_behavior_test}, + {"libmemcached_string_distribution()", 0, (test_callback_fn*)libmemcached_string_distribution_test}, + {"behavior_test", 0, (test_callback_fn*)behavior_test}, + {"MEMCACHED_BEHAVIOR_CORK", 0, (test_callback_fn*)MEMCACHED_BEHAVIOR_CORK_test}, + {"MEMCACHED_BEHAVIOR_TCP_KEEPALIVE", 0, (test_callback_fn*)MEMCACHED_BEHAVIOR_TCP_KEEPALIVE_test}, + {"MEMCACHED_BEHAVIOR_TCP_KEEPIDLE", 0, (test_callback_fn*)MEMCACHED_BEHAVIOR_TCP_KEEPIDLE_test}, {0, 0, 0} }; test_st basic_tests[] ={ - {"init", 1, (test_callback_fn)basic_init_test}, - {"clone", 1, (test_callback_fn)basic_clone_test}, - {"reset", 1, (test_callback_fn)basic_reset_stack_test}, - {"reset heap", 1, (test_callback_fn)basic_reset_heap_test}, - {"reset stack clone", 1, (test_callback_fn)basic_reset_stack_clone_test}, - {"reset heap clone", 1, (test_callback_fn)basic_reset_heap_clone_test}, + {"init", 1, (test_callback_fn*)basic_init_test}, + {"clone", 1, (test_callback_fn*)basic_clone_test}, + {"reset", 1, (test_callback_fn*)basic_reset_stack_test}, + {"reset heap", 1, (test_callback_fn*)basic_reset_heap_test}, + {"reset stack clone", 1, (test_callback_fn*)basic_reset_stack_clone_test}, + {"reset heap clone", 1, (test_callback_fn*)basic_reset_heap_clone_test}, {0, 0, 0} }; test_st regression_binary_vs_block[] ={ - {"block add", 1, (test_callback_fn)block_add_regression}, - {"binary add", 1, (test_callback_fn)binary_add_regression}, + {"block add", 1, (test_callback_fn*)block_add_regression}, + {"binary add", 1, (test_callback_fn*)binary_add_regression}, {0, 0, 0} }; test_st async_tests[] ={ - {"add", 1, (test_callback_fn)add_wrapper }, + {"add", 1, (test_callback_fn*)add_wrapper }, {0, 0, 0} }; test_st string_tests[] ={ - {"string static with null", 0, (test_callback_fn)string_static_null }, - {"string alloc with null", 0, (test_callback_fn)string_alloc_null }, - {"string alloc with 1K", 0, (test_callback_fn)string_alloc_with_size }, - {"string alloc with malloc failure", 0, (test_callback_fn)string_alloc_with_size_toobig }, - {"string append", 0, (test_callback_fn)string_alloc_append }, - {"string append failure (too big)", 0, (test_callback_fn)string_alloc_append_toobig }, - {"string_alloc_append_multiple", 0, (test_callback_fn)string_alloc_append_multiple }, - {0, 0, (test_callback_fn)0} + {"string static with null", 0, (test_callback_fn*)string_static_null }, + {"string alloc with null", 0, (test_callback_fn*)string_alloc_null }, + {"string alloc with 1K", 0, (test_callback_fn*)string_alloc_with_size }, + {"string alloc with malloc failure", 0, (test_callback_fn*)string_alloc_with_size_toobig }, + {"string append", 0, (test_callback_fn*)string_alloc_append }, + {"string append failure (too big)", 0, (test_callback_fn*)string_alloc_append_toobig }, + {"string_alloc_append_multiple", 0, (test_callback_fn*)string_alloc_append_multiple }, + {0, 0, (test_callback_fn*)0} }; test_st memcached_server_get_last_disconnect_tests[] ={ - {"memcached_server_get_last_disconnect()", 0, (test_callback_fn)test_multiple_get_last_disconnect}, - {0, 0, (test_callback_fn)0} + {"memcached_server_get_last_disconnect()", 0, (test_callback_fn*)test_multiple_get_last_disconnect}, + {0, 0, (test_callback_fn*)0} }; test_st result_tests[] ={ - {"result static", 0, (test_callback_fn)result_static}, - {"result alloc", 0, (test_callback_fn)result_alloc}, - {0, 0, (test_callback_fn)0} + {"result static", 0, (test_callback_fn*)result_static}, + {"result alloc", 0, (test_callback_fn*)result_alloc}, + {0, 0, (test_callback_fn*)0} }; test_st version_1_2_3[] ={ - {"append", 0, (test_callback_fn)append_test }, - {"prepend", 0, (test_callback_fn)prepend_test }, - {"cas", 0, (test_callback_fn)cas_test }, - {"cas2", 0, (test_callback_fn)cas2_test }, - {"append_binary", 0, (test_callback_fn)append_binary_test }, - {0, 0, (test_callback_fn)0} + {"append", 0, (test_callback_fn*)append_test }, + {"prepend", 0, (test_callback_fn*)prepend_test }, + {"cas", 0, (test_callback_fn*)cas_test }, + {"cas2", 0, (test_callback_fn*)cas2_test }, + {"append_binary", 0, (test_callback_fn*)append_binary_test }, + {0, 0, (test_callback_fn*)0} }; test_st haldenbrand_tests[] ={ - {"memcached_set", 0, (test_callback_fn)user_supplied_bug1 }, - {"memcached_get()", 0, (test_callback_fn)user_supplied_bug2 }, - {"memcached_mget()", 0, (test_callback_fn)user_supplied_bug3 }, - {0, 0, (test_callback_fn)0} + {"memcached_set", 0, (test_callback_fn*)user_supplied_bug1 }, + {"memcached_get()", 0, (test_callback_fn*)user_supplied_bug2 }, + {"memcached_mget()", 0, (test_callback_fn*)user_supplied_bug3 }, + {0, 0, (test_callback_fn*)0} }; test_st user_tests[] ={ - {"user_supplied_bug4", true, (test_callback_fn)user_supplied_bug4 }, - {"user_supplied_bug5", 1, (test_callback_fn)user_supplied_bug5 }, - {"user_supplied_bug6", 1, (test_callback_fn)user_supplied_bug6 }, - {"user_supplied_bug7", 1, (test_callback_fn)user_supplied_bug7 }, - {"user_supplied_bug8", 1, (test_callback_fn)user_supplied_bug8 }, - {"user_supplied_bug9", 1, (test_callback_fn)user_supplied_bug9 }, - {"user_supplied_bug10", 1, (test_callback_fn)user_supplied_bug10 }, - {"user_supplied_bug11", 1, (test_callback_fn)user_supplied_bug11 }, - {"user_supplied_bug12", 1, (test_callback_fn)user_supplied_bug12 }, - {"user_supplied_bug13", 1, (test_callback_fn)user_supplied_bug13 }, - {"user_supplied_bug14", 1, (test_callback_fn)user_supplied_bug14 }, - {"user_supplied_bug15", 1, (test_callback_fn)user_supplied_bug15 }, - {"user_supplied_bug16", 1, (test_callback_fn)user_supplied_bug16 }, + {"user_supplied_bug4", true, (test_callback_fn*)user_supplied_bug4 }, + {"user_supplied_bug5", 1, (test_callback_fn*)user_supplied_bug5 }, + {"user_supplied_bug6", 1, (test_callback_fn*)user_supplied_bug6 }, + {"user_supplied_bug7", 1, (test_callback_fn*)user_supplied_bug7 }, + {"user_supplied_bug8", 1, (test_callback_fn*)user_supplied_bug8 }, + {"user_supplied_bug9", 1, (test_callback_fn*)user_supplied_bug9 }, + {"user_supplied_bug10", 1, (test_callback_fn*)user_supplied_bug10 }, + {"user_supplied_bug11", 1, (test_callback_fn*)user_supplied_bug11 }, + {"user_supplied_bug12", 1, (test_callback_fn*)user_supplied_bug12 }, + {"user_supplied_bug13", 1, (test_callback_fn*)user_supplied_bug13 }, + {"user_supplied_bug14", 1, (test_callback_fn*)user_supplied_bug14 }, + {"user_supplied_bug15", 1, (test_callback_fn*)user_supplied_bug15 }, + {"user_supplied_bug16", 1, (test_callback_fn*)user_supplied_bug16 }, #if !defined(__sun) && !defined(__OpenBSD__) /* ** It seems to be something weird with the character sets.. @@ -6262,25 +6268,25 @@ test_st user_tests[] ={ ** to run the test in a specific locale (I tried zh_CN.UTF-8 without success, ** so just disable the code for now...). */ - {"user_supplied_bug17", 1, (test_callback_fn)user_supplied_bug17 }, + {"user_supplied_bug17", 1, (test_callback_fn*)user_supplied_bug17 }, #endif - {"user_supplied_bug18", 1, (test_callback_fn)user_supplied_bug18 }, - {"user_supplied_bug19", 1, (test_callback_fn)user_supplied_bug19 }, - {"user_supplied_bug20", 1, (test_callback_fn)user_supplied_bug20 }, - {"user_supplied_bug21", 1, (test_callback_fn)user_supplied_bug21 }, - {"wrong_failure_counter_test", 1, (test_callback_fn)wrong_failure_counter_test}, - {"wrong_failure_counter_two_test", 1, (test_callback_fn)wrong_failure_counter_two_test}, - {0, 0, (test_callback_fn)0} + {"user_supplied_bug18", 1, (test_callback_fn*)user_supplied_bug18 }, + {"user_supplied_bug19", 1, (test_callback_fn*)user_supplied_bug19 }, + {"user_supplied_bug20", 1, (test_callback_fn*)user_supplied_bug20 }, + {"user_supplied_bug21", 1, (test_callback_fn*)user_supplied_bug21 }, + {"wrong_failure_counter_test", 1, (test_callback_fn*)wrong_failure_counter_test}, + {"wrong_failure_counter_two_test", 1, (test_callback_fn*)wrong_failure_counter_two_test}, + {0, 0, (test_callback_fn*)0} }; test_st replication_tests[]= { - {"set", 1, (test_callback_fn)replication_set_test }, - {"get", 0, (test_callback_fn)replication_get_test }, - {"mget", 0, (test_callback_fn)replication_mget_test }, - {"delete", 0, (test_callback_fn)replication_delete_test }, - {"rand_mget", 0, (test_callback_fn)replication_randomize_mget_test }, - {"fail", 0, (test_callback_fn)replication_randomize_mget_fail_test }, - {0, 0, (test_callback_fn)0} + {"set", 1, (test_callback_fn*)replication_set_test }, + {"get", 0, (test_callback_fn*)replication_get_test }, + {"mget", 0, (test_callback_fn*)replication_mget_test }, + {"delete", 0, (test_callback_fn*)replication_delete_test }, + {"rand_mget", 0, (test_callback_fn*)replication_randomize_mget_test }, + {"fail", 0, (test_callback_fn*)replication_randomize_mget_fail_test }, + {0, 0, (test_callback_fn*)0} }; /* @@ -6290,143 +6296,143 @@ test_st replication_tests[]= { * http://bugs.launchpad.net/libmemcached */ test_st regression_tests[]= { - {"lp:434484", 1, (test_callback_fn)regression_bug_434484 }, - {"lp:434843", 1, (test_callback_fn)regression_bug_434843 }, - {"lp:434843-buffered", 1, (test_callback_fn)regression_bug_434843_buffered }, - {"lp:421108", 1, (test_callback_fn)regression_bug_421108 }, - {"lp:442914", 1, (test_callback_fn)regression_bug_442914 }, - {"lp:447342", 1, (test_callback_fn)regression_bug_447342 }, - {"lp:463297", 1, (test_callback_fn)regression_bug_463297 }, - {"lp:490486", 1, (test_callback_fn)regression_bug_490486 }, - {"lp:583031", 1, (test_callback_fn)regression_bug_583031 }, - {"lp:?", 1, (test_callback_fn)regression_bug_ }, - {"lp:728286", 1, (test_callback_fn)regression_bug_728286 }, - {"lp:581030", 1, (test_callback_fn)regression_bug_581030 }, - {"lp:71231153 connect()", 1, (test_callback_fn)regression_bug_71231153_connect }, - {"lp:71231153 poll()", 1, (test_callback_fn)regression_bug_71231153_poll }, - {"lp:655423", 1, (test_callback_fn)regression_bug_655423 }, - {"lp:490520", 1, (test_callback_fn)regression_bug_490520 }, - {0, 0, (test_callback_fn)0} + {"lp:434484", 1, (test_callback_fn*)regression_bug_434484 }, + {"lp:434843", 1, (test_callback_fn*)regression_bug_434843 }, + {"lp:434843-buffered", 1, (test_callback_fn*)regression_bug_434843_buffered }, + {"lp:421108", 1, (test_callback_fn*)regression_bug_421108 }, + {"lp:442914", 1, (test_callback_fn*)regression_bug_442914 }, + {"lp:447342", 1, (test_callback_fn*)regression_bug_447342 }, + {"lp:463297", 1, (test_callback_fn*)regression_bug_463297 }, + {"lp:490486", 1, (test_callback_fn*)regression_bug_490486 }, + {"lp:583031", 1, (test_callback_fn*)regression_bug_583031 }, + {"lp:?", 1, (test_callback_fn*)regression_bug_ }, + {"lp:728286", 1, (test_callback_fn*)regression_bug_728286 }, + {"lp:581030", 1, (test_callback_fn*)regression_bug_581030 }, + {"lp:71231153 connect()", 1, (test_callback_fn*)regression_bug_71231153_connect }, + {"lp:71231153 poll()", 1, (test_callback_fn*)regression_bug_71231153_poll }, + {"lp:655423", 1, (test_callback_fn*)regression_bug_655423 }, + {"lp:490520", 1, (test_callback_fn*)regression_bug_490520 }, + {0, 0, (test_callback_fn*)0} }; test_st sasl_auth_tests[]= { - {"sasl_auth", 1, (test_callback_fn)sasl_auth_test }, - {0, 0, (test_callback_fn)0} + {"sasl_auth", 1, (test_callback_fn*)sasl_auth_test }, + {0, 0, (test_callback_fn*)0} }; test_st ketama_compatibility[]= { - {"libmemcached", 1, (test_callback_fn)ketama_compatibility_libmemcached }, - {"spymemcached", 1, (test_callback_fn)ketama_compatibility_spymemcached }, - {0, 0, (test_callback_fn)0} + {"libmemcached", 1, (test_callback_fn*)ketama_compatibility_libmemcached }, + {"spymemcached", 1, (test_callback_fn*)ketama_compatibility_spymemcached }, + {0, 0, (test_callback_fn*)0} }; test_st generate_tests[] ={ - {"generate_pairs", 1, (test_callback_fn)generate_pairs }, - {"generate_data", 1, (test_callback_fn)generate_data }, - {"get_read", 0, (test_callback_fn)get_read }, - {"delete_generate", 0, (test_callback_fn)delete_generate }, - {"generate_buffer_data", 1, (test_callback_fn)generate_buffer_data }, - {"delete_buffer", 0, (test_callback_fn)delete_buffer_generate}, - {"generate_data", 1, (test_callback_fn)generate_data }, - {"mget_read", 0, (test_callback_fn)mget_read }, - {"mget_read_result", 0, (test_callback_fn)mget_read_result }, - {"memcached_fetch_result() use internal result", 0, (test_callback_fn)mget_read_internal_result }, - {"memcached_fetch_result() partial read", 0, (test_callback_fn)mget_read_partial_result }, - {"mget_read_function", 0, (test_callback_fn)mget_read_function }, - {"cleanup", 1, (test_callback_fn)cleanup_pairs }, - {"generate_large_pairs", 1, (test_callback_fn)generate_large_pairs }, - {"generate_data", 1, (test_callback_fn)generate_data }, - {"generate_buffer_data", 1, (test_callback_fn)generate_buffer_data }, - {"cleanup", 1, (test_callback_fn)cleanup_pairs }, - {0, 0, (test_callback_fn)0} + {"generate_pairs", 1, (test_callback_fn*)generate_pairs }, + {"generate_data", 1, (test_callback_fn*)generate_data }, + {"get_read", 0, (test_callback_fn*)get_read }, + {"delete_generate", 0, (test_callback_fn*)delete_generate }, + {"generate_buffer_data", 1, (test_callback_fn*)generate_buffer_data }, + {"delete_buffer", 0, (test_callback_fn*)delete_buffer_generate}, + {"generate_data", 1, (test_callback_fn*)generate_data }, + {"mget_read", 0, (test_callback_fn*)mget_read }, + {"mget_read_result", 0, (test_callback_fn*)mget_read_result }, + {"memcached_fetch_result() use internal result", 0, (test_callback_fn*)mget_read_internal_result }, + {"memcached_fetch_result() partial read", 0, (test_callback_fn*)mget_read_partial_result }, + {"mget_read_function", 0, (test_callback_fn*)mget_read_function }, + {"cleanup", 1, (test_callback_fn*)cleanup_pairs }, + {"generate_large_pairs", 1, (test_callback_fn*)generate_large_pairs }, + {"generate_data", 1, (test_callback_fn*)generate_data }, + {"generate_buffer_data", 1, (test_callback_fn*)generate_buffer_data }, + {"cleanup", 1, (test_callback_fn*)cleanup_pairs }, + {0, 0, (test_callback_fn*)0} }; test_st consistent_tests[] ={ - {"generate_pairs", 1, (test_callback_fn)generate_pairs }, - {"generate_data", 1, (test_callback_fn)generate_data }, - {"get_read", 0, (test_callback_fn)get_read_count }, - {"cleanup", 1, (test_callback_fn)cleanup_pairs }, - {0, 0, (test_callback_fn)0} + {"generate_pairs", 1, (test_callback_fn*)generate_pairs }, + {"generate_data", 1, (test_callback_fn*)generate_data }, + {"get_read", 0, (test_callback_fn*)get_read_count }, + {"cleanup", 1, (test_callback_fn*)cleanup_pairs }, + {0, 0, (test_callback_fn*)0} }; test_st consistent_weighted_tests[] ={ - {"generate_pairs", 1, (test_callback_fn)generate_pairs }, - {"generate_data", 1, (test_callback_fn)generate_data_with_stats }, - {"get_read", 0, (test_callback_fn)get_read_count }, - {"cleanup", 1, (test_callback_fn)cleanup_pairs }, - {0, 0, (test_callback_fn)0} + {"generate_pairs", 1, (test_callback_fn*)generate_pairs }, + {"generate_data", 1, (test_callback_fn*)generate_data_with_stats }, + {"get_read", 0, (test_callback_fn*)get_read_count }, + {"cleanup", 1, (test_callback_fn*)cleanup_pairs }, + {0, 0, (test_callback_fn*)0} }; test_st hsieh_availability[] ={ - {"hsieh_avaibility_test", 0, (test_callback_fn)hsieh_avaibility_test}, - {0, 0, (test_callback_fn)0} + {"hsieh_avaibility_test", 0, (test_callback_fn*)hsieh_avaibility_test}, + {0, 0, (test_callback_fn*)0} }; test_st murmur_availability[] ={ - {"murmur_avaibility_test", 0, (test_callback_fn)murmur_avaibility_test}, - {0, 0, (test_callback_fn)0} + {"murmur_avaibility_test", 0, (test_callback_fn*)murmur_avaibility_test}, + {0, 0, (test_callback_fn*)0} }; #if 0 test_st hash_sanity[] ={ - {"hash sanity", 0, (test_callback_fn)hash_sanity_test}, - {0, 0, (test_callback_fn)0} + {"hash sanity", 0, (test_callback_fn*)hash_sanity_test}, + {0, 0, (test_callback_fn*)0} }; #endif test_st ketama_auto_eject_hosts[] ={ - {"auto_eject_hosts", 1, (test_callback_fn)auto_eject_hosts }, - {"output_ketama_weighted_keys", 1, (test_callback_fn)output_ketama_weighted_keys }, - {0, 0, (test_callback_fn)0} + {"auto_eject_hosts", 1, (test_callback_fn*)auto_eject_hosts }, + {"output_ketama_weighted_keys", 1, (test_callback_fn*)output_ketama_weighted_keys }, + {0, 0, (test_callback_fn*)0} }; test_st hash_tests[] ={ - {"one_at_a_time_run", 0, (test_callback_fn)one_at_a_time_run }, - {"md5", 0, (test_callback_fn)md5_run }, - {"crc", 0, (test_callback_fn)crc_run }, - {"fnv1_64", 0, (test_callback_fn)fnv1_64_run }, - {"fnv1a_64", 0, (test_callback_fn)fnv1a_64_run }, - {"fnv1_32", 0, (test_callback_fn)fnv1_32_run }, - {"fnv1a_32", 0, (test_callback_fn)fnv1a_32_run }, - {"hsieh", 0, (test_callback_fn)hsieh_run }, - {"murmur", 0, (test_callback_fn)murmur_run }, - {"jenkis", 0, (test_callback_fn)jenkins_run }, - {"memcached_get_hashkit", 0, (test_callback_fn)memcached_get_hashkit_test }, - {0, 0, (test_callback_fn)0} + {"one_at_a_time_run", 0, (test_callback_fn*)one_at_a_time_run }, + {"md5", 0, (test_callback_fn*)md5_run }, + {"crc", 0, (test_callback_fn*)crc_run }, + {"fnv1_64", 0, (test_callback_fn*)fnv1_64_run }, + {"fnv1a_64", 0, (test_callback_fn*)fnv1a_64_run }, + {"fnv1_32", 0, (test_callback_fn*)fnv1_32_run }, + {"fnv1a_32", 0, (test_callback_fn*)fnv1a_32_run }, + {"hsieh", 0, (test_callback_fn*)hsieh_run }, + {"murmur", 0, (test_callback_fn*)murmur_run }, + {"jenkis", 0, (test_callback_fn*)jenkins_run }, + {"memcached_get_hashkit", 0, (test_callback_fn*)memcached_get_hashkit_test }, + {0, 0, (test_callback_fn*)0} }; test_st error_conditions[] ={ - {"memcached_get(MEMCACHED_ERRNO)", 0, (test_callback_fn)memcached_get_MEMCACHED_ERRNO }, - {"memcached_get(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_MEMCACHED_NOTFOUND }, - {"memcached_get_by_key(MEMCACHED_ERRNO)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_ERRNO }, - {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND }, - {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn)memcached_get_by_key_MEMCACHED_NOTFOUND }, - {"memcached_increment(MEMCACHED_NO_SERVERS)", 0, (test_callback_fn)memcached_increment_MEMCACHED_NO_SERVERS }, - {0, 0, (test_callback_fn)0} + {"memcached_get(MEMCACHED_ERRNO)", 0, (test_callback_fn*)memcached_get_MEMCACHED_ERRNO }, + {"memcached_get(MEMCACHED_NOTFOUND)", 0, (test_callback_fn*)memcached_get_MEMCACHED_NOTFOUND }, + {"memcached_get_by_key(MEMCACHED_ERRNO)", 0, (test_callback_fn*)memcached_get_by_key_MEMCACHED_ERRNO }, + {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn*)memcached_get_by_key_MEMCACHED_NOTFOUND }, + {"memcached_get_by_key(MEMCACHED_NOTFOUND)", 0, (test_callback_fn*)memcached_get_by_key_MEMCACHED_NOTFOUND }, + {"memcached_increment(MEMCACHED_NO_SERVERS)", 0, (test_callback_fn*)memcached_increment_MEMCACHED_NO_SERVERS }, + {0, 0, (test_callback_fn*)0} }; test_st parser_tests[] ={ - {"behavior", 0, (test_callback_fn)behavior_parser_test }, - {"boolean_options", 0, (test_callback_fn)parser_boolean_options_test }, - {"configure_file", 0, (test_callback_fn)memcached_create_with_options_with_filename }, - {"distribtions", 0, (test_callback_fn)parser_distribution_test }, - {"hash", 0, (test_callback_fn)parser_hash_test }, - {"libmemcached_check_configuration", 0, (test_callback_fn)libmemcached_check_configuration_test }, - {"libmemcached_check_configuration_with_filename", 0, (test_callback_fn)libmemcached_check_configuration_with_filename_test }, - {"number_options", 0, (test_callback_fn)parser_number_options_test }, - {"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 }, - {"bad server strings", 0, (test_callback_fn)servers_bad_test }, - {"server with weights", 0, (test_callback_fn)server_with_weight_test }, - {"parsing servername, port, and weight", 0, (test_callback_fn)test_hostname_port_weight }, - {0, 0, (test_callback_fn)0} + {"behavior", 0, (test_callback_fn*)behavior_parser_test }, + {"boolean_options", 0, (test_callback_fn*)parser_boolean_options_test }, + {"configure_file", 0, (test_callback_fn*)memcached_create_with_options_with_filename }, + {"distribtions", 0, (test_callback_fn*)parser_distribution_test }, + {"hash", 0, (test_callback_fn*)parser_hash_test }, + {"libmemcached_check_configuration", 0, (test_callback_fn*)libmemcached_check_configuration_test }, + {"libmemcached_check_configuration_with_filename", 0, (test_callback_fn*)libmemcached_check_configuration_with_filename_test }, + {"number_options", 0, (test_callback_fn*)parser_number_options_test }, + {"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 }, + {"bad server strings", 0, (test_callback_fn*)servers_bad_test }, + {"server with weights", 0, (test_callback_fn*)server_with_weight_test }, + {"parsing servername, port, and weight", 0, (test_callback_fn*)test_hostname_port_weight }, + {0, 0, (test_callback_fn*)0} }; test_st virtual_bucket_tests[] ={ - {"basic", 0, (test_callback_fn)virtual_back_map }, - {0, 0, (test_callback_fn)0} + {"basic", 0, (test_callback_fn*)virtual_back_map }, + {0, 0, (test_callback_fn*)0} }; collection_st collection[] ={ @@ -6437,61 +6443,61 @@ collection_st collection[] ={ {"hsieh_availability", 0, 0, hsieh_availability}, {"murmur_availability", 0, 0, murmur_availability}, {"block", 0, 0, tests}, - {"binary", (test_callback_fn)pre_binary, 0, tests}, - {"nonblock", (test_callback_fn)pre_nonblock, 0, tests}, - {"nodelay", (test_callback_fn)pre_nodelay, 0, tests}, - {"settimer", (test_callback_fn)pre_settimer, 0, tests}, - {"md5", (test_callback_fn)pre_md5, 0, tests}, - {"crc", (test_callback_fn)pre_crc, 0, tests}, - {"hsieh", (test_callback_fn)pre_hsieh, 0, tests}, - {"jenkins", (test_callback_fn)pre_jenkins, 0, tests}, - {"fnv1_64", (test_callback_fn)pre_hash_fnv1_64, 0, tests}, - {"fnv1a_64", (test_callback_fn)pre_hash_fnv1a_64, 0, tests}, - {"fnv1_32", (test_callback_fn)pre_hash_fnv1_32, 0, tests}, - {"fnv1a_32", (test_callback_fn)pre_hash_fnv1a_32, 0, tests}, - {"ketama", (test_callback_fn)pre_behavior_ketama, 0, tests}, - {"ketama_auto_eject_hosts", (test_callback_fn)pre_behavior_ketama, 0, ketama_auto_eject_hosts}, - {"unix_socket", (test_callback_fn)pre_unix_socket, 0, tests}, - {"unix_socket_nodelay", (test_callback_fn)pre_nodelay, 0, tests}, - {"poll_timeout", (test_callback_fn)poll_timeout, 0, tests}, - {"gets", (test_callback_fn)enable_cas, 0, tests}, - {"consistent_crc", (test_callback_fn)enable_consistent_crc, 0, tests}, - {"consistent_hsieh", (test_callback_fn)enable_consistent_hsieh, 0, tests}, + {"binary", (test_callback_fn*)pre_binary, 0, tests}, + {"nonblock", (test_callback_fn*)pre_nonblock, 0, tests}, + {"nodelay", (test_callback_fn*)pre_nodelay, 0, tests}, + {"settimer", (test_callback_fn*)pre_settimer, 0, tests}, + {"md5", (test_callback_fn*)pre_md5, 0, tests}, + {"crc", (test_callback_fn*)pre_crc, 0, tests}, + {"hsieh", (test_callback_fn*)pre_hsieh, 0, tests}, + {"jenkins", (test_callback_fn*)pre_jenkins, 0, tests}, + {"fnv1_64", (test_callback_fn*)pre_hash_fnv1_64, 0, tests}, + {"fnv1a_64", (test_callback_fn*)pre_hash_fnv1a_64, 0, tests}, + {"fnv1_32", (test_callback_fn*)pre_hash_fnv1_32, 0, tests}, + {"fnv1a_32", (test_callback_fn*)pre_hash_fnv1a_32, 0, tests}, + {"ketama", (test_callback_fn*)pre_behavior_ketama, 0, tests}, + {"ketama_auto_eject_hosts", (test_callback_fn*)pre_behavior_ketama, 0, ketama_auto_eject_hosts}, + {"unix_socket", (test_callback_fn*)pre_unix_socket, 0, tests}, + {"unix_socket_nodelay", (test_callback_fn*)pre_nodelay, 0, tests}, + {"poll_timeout", (test_callback_fn*)poll_timeout, 0, tests}, + {"gets", (test_callback_fn*)enable_cas, 0, tests}, + {"consistent_crc", (test_callback_fn*)enable_consistent_crc, 0, tests}, + {"consistent_hsieh", (test_callback_fn*)enable_consistent_hsieh, 0, tests}, #ifdef MEMCACHED_ENABLE_DEPRECATED - {"deprecated_memory_allocators", (test_callback_fn)deprecated_set_memory_alloc, 0, tests}, + {"deprecated_memory_allocators", (test_callback_fn*)deprecated_set_memory_alloc, 0, tests}, #endif - {"memory_allocators", (test_callback_fn)set_memory_alloc, 0, tests}, - {"prefix", (test_callback_fn)set_prefix, 0, tests}, - {"sasl_auth", (test_callback_fn)pre_sasl, 0, sasl_auth_tests }, - {"sasl", (test_callback_fn)pre_sasl, 0, tests }, - {"version_1_2_3", (test_callback_fn)check_for_1_2_3, 0, version_1_2_3}, + {"memory_allocators", (test_callback_fn*)set_memory_alloc, 0, tests}, + {"prefix", (test_callback_fn*)set_prefix, 0, tests}, + {"sasl_auth", (test_callback_fn*)pre_sasl, 0, sasl_auth_tests }, + {"sasl", (test_callback_fn*)pre_sasl, 0, tests }, + {"version_1_2_3", (test_callback_fn*)check_for_1_2_3, 0, version_1_2_3}, {"string", 0, 0, string_tests}, {"result", 0, 0, result_tests}, - {"async", (test_callback_fn)pre_nonblock, 0, async_tests}, - {"async_binary", (test_callback_fn)pre_nonblock_binary, 0, async_tests}, + {"async", (test_callback_fn*)pre_nonblock, 0, async_tests}, + {"async_binary", (test_callback_fn*)pre_nonblock_binary, 0, async_tests}, {"Cal Haldenbrand's tests", 0, 0, haldenbrand_tests}, {"user", 0, 0, user_tests}, {"generate", 0, 0, generate_tests}, - {"generate_hsieh", (test_callback_fn)pre_hsieh, 0, generate_tests}, - {"generate_ketama", (test_callback_fn)pre_behavior_ketama, 0, generate_tests}, - {"generate_hsieh_consistent", (test_callback_fn)enable_consistent_hsieh, 0, generate_tests}, - {"generate_md5", (test_callback_fn)pre_md5, 0, generate_tests}, - {"generate_murmur", (test_callback_fn)pre_murmur, 0, generate_tests}, - {"generate_jenkins", (test_callback_fn)pre_jenkins, 0, generate_tests}, - {"generate_nonblock", (test_callback_fn)pre_nonblock, 0, generate_tests}, + {"generate_hsieh", (test_callback_fn*)pre_hsieh, 0, generate_tests}, + {"generate_ketama", (test_callback_fn*)pre_behavior_ketama, 0, generate_tests}, + {"generate_hsieh_consistent", (test_callback_fn*)enable_consistent_hsieh, 0, generate_tests}, + {"generate_md5", (test_callback_fn*)pre_md5, 0, generate_tests}, + {"generate_murmur", (test_callback_fn*)pre_murmur, 0, generate_tests}, + {"generate_jenkins", (test_callback_fn*)pre_jenkins, 0, generate_tests}, + {"generate_nonblock", (test_callback_fn*)pre_nonblock, 0, generate_tests}, // Too slow - {"generate_corked", (test_callback_fn)pre_cork, 0, generate_tests}, - {"generate_corked_and_nonblock", (test_callback_fn)pre_cork_and_nonblock, 0, generate_tests}, + {"generate_corked", (test_callback_fn*)pre_cork, 0, generate_tests}, + {"generate_corked_and_nonblock", (test_callback_fn*)pre_cork_and_nonblock, 0, generate_tests}, {"consistent_not", 0, 0, consistent_tests}, - {"consistent_ketama", (test_callback_fn)pre_behavior_ketama, 0, consistent_tests}, - {"consistent_ketama_weighted", (test_callback_fn)pre_behavior_ketama_weighted, 0, consistent_weighted_tests}, + {"consistent_ketama", (test_callback_fn*)pre_behavior_ketama, 0, consistent_tests}, + {"consistent_ketama_weighted", (test_callback_fn*)pre_behavior_ketama_weighted, 0, consistent_weighted_tests}, {"ketama_compat", 0, 0, ketama_compatibility}, {"test_hashes", 0, 0, hash_tests}, - {"replication", (test_callback_fn)pre_replication, 0, replication_tests}, - {"replication_noblock", (test_callback_fn)pre_replication_noblock, 0, replication_tests}, + {"replication", (test_callback_fn*)pre_replication, 0, replication_tests}, + {"replication_noblock", (test_callback_fn*)pre_replication_noblock, 0, replication_tests}, {"regression", 0, 0, regression_tests}, {"behaviors", 0, 0, behavior_tests}, - {"regression_binary_vs_block", (test_callback_fn)key_setup, (test_callback_fn)key_teardown, regression_binary_vs_block}, + {"regression_binary_vs_block", (test_callback_fn*)key_setup, (test_callback_fn*)key_teardown, regression_binary_vs_block}, {"error_conditions", 0, 0, error_conditions}, {"parser", 0, 0, parser_tests}, {"virtual buckets", 0, 0, virtual_bucket_tests}, @@ -6501,21 +6507,21 @@ collection_st collection[] ={ #include "tests/libmemcached_world.h" -void get_world(world_st *world) +void get_world(Framework *world) { world->collections= collection; - world->create= (test_callback_create_fn)world_create; - world->destroy= (test_callback_fn)world_destroy; + world->_create= (test_callback_create_fn*)world_create; + world->_destroy= (test_callback_fn*)world_destroy; - world->test.startup= (test_callback_fn)world_test_startup; - world->test.flush= (test_callback_fn)world_flush; - world->test.pre_run= (test_callback_fn)world_pre_run; - world->test.post_run= (test_callback_fn)world_post_run; - world->test.on_error= (test_callback_error_fn)world_on_error; + world->item._startup= (test_callback_fn*)world_test_startup; + world->item._flush= (test_callback_fn*)world_flush; + world->item.set_pre((test_callback_fn*)world_pre_run); + world->item.set_post((test_callback_fn*)world_post_run); + world->_on_error= (test_callback_error_fn*)world_on_error; - world->collection.startup= (test_callback_fn)world_container_startup; - world->collection.shutdown= (test_callback_fn)world_container_shutdown; + world->collection_startup= (test_callback_fn*)world_container_startup; + world->collection_shutdown= (test_callback_fn*)world_container_shutdown; world->runner= &defualt_libmemcached_runner; } diff --git a/tests/mem_udp.c b/tests/mem_udp.c deleted file mode 100644 index 01314dbd..00000000 --- a/tests/mem_udp.c +++ /dev/null @@ -1,508 +0,0 @@ -/* libMemcached Functions Test - * Copyright (C) 2006-2009 Brian Aker - * All rights reserved. - * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. - */ - -/* - Sample test application. -*/ - -#include "config.h" - -#include "libmemcached/common.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define SERVERS_TO_CREATE 5 - - -/** - @note This should be testing to see if the server really supports the binary protocol. -*/ -static test_return_t pre_binary(memcached_st *memc) -{ - memcached_return_t rc= MEMCACHED_FAILURE; - memcached_st *memc_clone; - memcached_server_instance_st instance; - - memc_clone= memcached_clone(NULL, memc); - test_true(memc_clone); - // The memcached_version needs to be done on a clone, because the server - // will not toggle protocol on an connection. - memcached_version(memc_clone); - - instance= memcached_server_instance_by_position(memc_clone, 0); - - if (instance->major_version >= 1 && instance->minor_version > 2) - { - rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); - test_true(rc == MEMCACHED_SUCCESS); - test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1); - } - - memcached_free(memc_clone); - - return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED; -} - -static void increment_request_id(uint16_t *id) -{ - (*id)++; - if ((*id & UDP_REQUEST_ID_THREAD_MASK) != 0) - *id= 0; -} - -static uint16_t *get_udp_request_ids(memcached_st *memc) -{ - uint16_t *ids= malloc(sizeof(uint16_t) * memcached_server_count(memc)); - assert(ids != NULL); - - for (uint32_t x= 0; x < memcached_server_count(memc); x++) - { - memcached_server_instance_st instance= - memcached_server_instance_by_position(memc, x); - - ids[x]= get_udp_datagram_request_id((struct udp_datagram_header_st *) ((memcached_server_instance_st )instance)->write_buffer); - } - - return ids; -} - -static test_return_t post_udp_op_check(memcached_st *memc, uint16_t *expected_req_ids) -{ - (void)memc; - (void)expected_req_ids; -#if 0 - memcached_server_st *cur_server = memcached_server_list(memc); - uint16_t *cur_req_ids = get_udp_request_ids(memc); - - for (size_t x= 0; x < memcached_server_count(memc); x++) - { - test_true(cur_server[x].cursor_active == 0); - test_true(cur_req_ids[x] == expected_req_ids[x]); - } - free(expected_req_ids); - free(cur_req_ids); - -#endif - return TEST_SUCCESS; -} - -/* -** There is a little bit of a hack here, instead of removing -** the servers, I just set num host to 0 and them add then new udp servers -**/ -static test_return_t init_udp(memcached_st *memc) -{ - memcached_version(memc); -#if 0 - memcached_server_instance_st instance= - memcached_server_instance_by_position(memc, 0); - - /* For the time being, only support udp test for >= 1.2.6 && < 1.3 */ - if (instance->major_version != 1 || instance->minor_version != 2 - || instance->micro_version < 6) - return TEST_SKIPPED; - - uint32_t num_hosts= memcached_server_count(memc); - memcached_server_st servers[num_hosts]; - memcpy(servers, memcached_server_list(memc), sizeof(memcached_server_st) * num_hosts); - for (uint32_t x= 0; x < num_hosts; x++) - { - memcached_server_instance_st set_instance= - memcached_server_instance_by_position(memc, x); - - memcached_server_free(((memcached_server_write_instance_st)set_instance)); - } - - memc->number_of_hosts= 0; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1); - for (uint32_t x= 0; x < num_hosts; x++) - { - memcached_server_instance_st set_instance= - memcached_server_instance_by_position(memc, x); - - test_true(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS); - test_true(set_instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); - } -#endif - - return TEST_SKIPPED; -} - -static test_return_t binary_init_udp(memcached_st *memc) -{ - test_return_t test_rc; - test_rc= pre_binary(memc); - - if (test_rc != TEST_SUCCESS) - return test_rc; - - return init_udp(memc); -} - -/* Make sure that I cant add a tcp server to a udp client */ -static test_return_t add_tcp_server_udp_client_test(memcached_st *memc) -{ - (void)memc; -#if 0 - memcached_server_st server; - memcached_server_instance_st instance= - memcached_server_instance_by_position(memc, 0); - memcached_server_clone(&server, &memc->hosts[0]); - test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS); - test_true(memcached_server_add(memc, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL); -#endif - return TEST_SUCCESS; -} - -/* Make sure that I cant add a udp server to a tcp client */ -static test_return_t add_udp_server_tcp_client_test(memcached_st *memc) -{ - (void)memc; -#if 0 - memcached_server_st server; - memcached_server_instance_st instance= - memcached_server_instance_by_position(memc, 0); - memcached_server_clone(&server, &memc->hosts[0]); - test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS); - - memcached_st tcp_client; - memcached_create(&tcp_client); - test_true(memcached_server_add_udp(&tcp_client, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL); -#endif - - return TEST_SUCCESS; -} - -static test_return_t set_udp_behavior_test(memcached_st *memc) -{ - - memcached_quit(memc); - memc->number_of_hosts= 0; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution); - test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1) == MEMCACHED_SUCCESS); - test_true(memc->flags.use_udp); - test_true(memc->flags.no_reply); - - test_true(memcached_server_count(memc) == 0); - - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,0); - test_true(! (memc->flags.use_udp)); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY,0); - test_true(! (memc->flags.no_reply)); - - return TEST_SUCCESS; -} - -static test_return_t udp_set_test(memcached_st *memc) -{ - unsigned int num_iters= 1025; //request id rolls over at 1024 - - for (size_t x= 0; x < num_iters;x++) - { - memcached_return_t rc; - const char *key= "foo"; - const char *value= "when we sanitize"; - uint16_t *expected_ids= get_udp_request_ids(memc); - unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); - memcached_server_instance_st instance= - memcached_server_instance_by_position(memc, server_key); - size_t init_offset= instance->write_buffer_offset; - - rc= memcached_set(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); - /** NB, the check below assumes that if new write_ptr is less than - * the original write_ptr that we have flushed. For large payloads, this - * maybe an invalid assumption, but for the small payload we have it is OK - */ - if (rc == MEMCACHED_SUCCESS || - instance->write_buffer_offset < init_offset) - increment_request_id(&expected_ids[server_key]); - - if (rc == MEMCACHED_SUCCESS) - { - test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); - } - else - { - test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH); - test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH); - } - test_true(post_udp_op_check(memc, expected_ids) == TEST_SUCCESS); - } - return TEST_SUCCESS; -} - -static test_return_t udp_buffered_set_test(memcached_st *memc) -{ - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); - return udp_set_test(memc); -} - -static test_return_t udp_set_too_big_test(memcached_st *memc) -{ - memcached_return_t rc; - const char *key= "bar"; - char value[MAX_UDP_DATAGRAM_LENGTH]; - uint16_t *expected_ids= get_udp_request_ids(memc); - rc= memcached_set(memc, key, strlen(key), - value, MAX_UDP_DATAGRAM_LENGTH, - (time_t)0, (uint32_t)0); - test_true(rc == MEMCACHED_WRITE_FAILURE); - - return post_udp_op_check(memc,expected_ids); -} - -static test_return_t udp_delete_test(memcached_st *memc) -{ - unsigned int num_iters= 1025; //request id rolls over at 1024 - - for (size_t x= 0; x < num_iters;x++) - { - memcached_return_t rc; - const char *key= "foo"; - uint16_t *expected_ids=get_udp_request_ids(memc); - unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); - memcached_server_instance_st instance= - memcached_server_instance_by_position(memc, server_key); - size_t init_offset= instance->write_buffer_offset; - - rc= memcached_delete(memc, key, strlen(key), 0); - test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); - - if (rc == MEMCACHED_SUCCESS || instance->write_buffer_offset < init_offset) - increment_request_id(&expected_ids[server_key]); - if (rc == MEMCACHED_SUCCESS) - { - test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); - } - else - { - test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH); - test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH); - } - test_true(post_udp_op_check(memc,expected_ids) == TEST_SUCCESS); - } - return TEST_SUCCESS; -} - -static test_return_t udp_buffered_delete_test(memcached_st *memc) -{ - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); - return udp_delete_test(memc); -} - -static test_return_t udp_verbosity_test(memcached_st *memc) -{ - memcached_return_t rc; - uint16_t *expected_ids= get_udp_request_ids(memc); - - for (size_t x= 0; x < memcached_server_count(memc); x++) - { - increment_request_id(&expected_ids[x]); - } - - rc= memcached_verbosity(memc,3); - test_true(rc == MEMCACHED_SUCCESS); - return post_udp_op_check(memc,expected_ids); -} - -static test_return_t udp_quit_test(memcached_st *memc) -{ - uint16_t *expected_ids= get_udp_request_ids(memc); - memcached_quit(memc); - return post_udp_op_check(memc, expected_ids); -} - -static test_return_t udp_flush_test(memcached_st *memc) -{ - memcached_return_t rc; - uint16_t *expected_ids= get_udp_request_ids(memc); - - for (size_t x= 0; x < memcached_server_count(memc); x++) - { - increment_request_id(&expected_ids[x]); - } - - rc= memcached_flush(memc,0); - test_true(rc == MEMCACHED_SUCCESS); - return post_udp_op_check(memc,expected_ids); -} - -static test_return_t udp_incr_test(memcached_st *memc) -{ - memcached_return_t rc; - const char *key= "incr"; - const char *value= "1"; - rc= memcached_set(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); - - test_true(rc == MEMCACHED_SUCCESS); - uint16_t *expected_ids= get_udp_request_ids(memc); - unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); - increment_request_id(&expected_ids[server_key]); - uint64_t newvalue; - rc= memcached_increment(memc, key, strlen(key), 1, &newvalue); - test_true(rc == MEMCACHED_SUCCESS); - return post_udp_op_check(memc, expected_ids); -} - -static test_return_t udp_decr_test(memcached_st *memc) -{ - memcached_return_t rc; - const char *key= "decr"; - const char *value= "1"; - rc= memcached_set(memc, key, strlen(key), - value, strlen(value), - (time_t)0, (uint32_t)0); - - test_true(rc == MEMCACHED_SUCCESS); - uint16_t *expected_ids= get_udp_request_ids(memc); - unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); - increment_request_id(&expected_ids[server_key]); - uint64_t newvalue; - rc= memcached_decrement(memc, key, strlen(key), 1, &newvalue); - test_true(rc == MEMCACHED_SUCCESS); - return post_udp_op_check(memc, expected_ids); -} - - -static test_return_t udp_stat_test(memcached_st *memc) -{ - memcached_stat_st * rv= NULL; - memcached_return_t rc; - char args[]= ""; - uint16_t *expected_ids = get_udp_request_ids(memc); - rv = memcached_stat(memc, args, &rc); - free(rv); - test_true(rc == MEMCACHED_NOT_SUPPORTED); - return post_udp_op_check(memc, expected_ids); -} - -static test_return_t udp_version_test(memcached_st *memc) -{ - memcached_return_t rc; - uint16_t *expected_ids = get_udp_request_ids(memc); - rc = memcached_version(memc); - test_true(rc == MEMCACHED_NOT_SUPPORTED); - return post_udp_op_check(memc, expected_ids); -} - -static test_return_t udp_get_test(memcached_st *memc) -{ - memcached_return_t rc; - const char *key= "foo"; - size_t vlen; - uint16_t *expected_ids = get_udp_request_ids(memc); - char *val= memcached_get(memc, key, strlen(key), &vlen, (uint32_t)0, &rc); - test_true(rc == MEMCACHED_NOT_SUPPORTED); - test_true(val == NULL); - return post_udp_op_check(memc, expected_ids); -} - -static test_return_t udp_mixed_io_test(memcached_st *memc) -{ - test_st current_op; - test_st mixed_io_ops [] ={ - {"udp_set_test", 0, - (test_callback_fn)udp_set_test}, - {"udp_set_too_big_test", 0, - (test_callback_fn)udp_set_too_big_test}, - {"udp_delete_test", 0, - (test_callback_fn)udp_delete_test}, - {"udp_verbosity_test", 0, - (test_callback_fn)udp_verbosity_test}, - {"udp_quit_test", 0, - (test_callback_fn)udp_quit_test}, - {"udp_flush_test", 0, - (test_callback_fn)udp_flush_test}, - {"udp_incr_test", 0, - (test_callback_fn)udp_incr_test}, - {"udp_decr_test", 0, - (test_callback_fn)udp_decr_test}, - {"udp_version_test", 0, - (test_callback_fn)udp_version_test} - }; - - for (size_t x= 0; x < 500; x++) - { - current_op= mixed_io_ops[random() % 9]; - test_true(current_op.test_fn(memc) == TEST_SUCCESS); - } - return TEST_SUCCESS; -} - -test_st udp_setup_server_tests[] ={ - {"set_udp_behavior_test", 0, (test_callback_fn)set_udp_behavior_test}, - {"add_tcp_server_udp_client_test", 0, (test_callback_fn)add_tcp_server_udp_client_test}, - {"add_udp_server_tcp_client_test", 0, (test_callback_fn)add_udp_server_tcp_client_test}, - {0, 0, 0} -}; - -test_st upd_io_tests[] ={ - {"udp_set_test", 0, (test_callback_fn)udp_set_test}, - {"udp_buffered_set_test", 0, (test_callback_fn)udp_buffered_set_test}, - {"udp_set_too_big_test", 0, (test_callback_fn)udp_set_too_big_test}, - {"udp_delete_test", 0, (test_callback_fn)udp_delete_test}, - {"udp_buffered_delete_test", 0, (test_callback_fn)udp_buffered_delete_test}, - {"udp_verbosity_test", 0, (test_callback_fn)udp_verbosity_test}, - {"udp_quit_test", 0, (test_callback_fn)udp_quit_test}, - {"udp_flush_test", 0, (test_callback_fn)udp_flush_test}, - {"udp_incr_test", 0, (test_callback_fn)udp_incr_test}, - {"udp_decr_test", 0, (test_callback_fn)udp_decr_test}, - {"udp_stat_test", 0, (test_callback_fn)udp_stat_test}, - {"udp_version_test", 0, (test_callback_fn)udp_version_test}, - {"udp_get_test", 0, (test_callback_fn)udp_get_test}, - {"udp_mixed_io_test", 0, (test_callback_fn)udp_mixed_io_test}, - {0, 0, 0} -}; - -collection_st collection[] ={ - {"udp_setup", (test_callback_fn)init_udp, 0, udp_setup_server_tests}, - {"udp_io", (test_callback_fn)init_udp, 0, upd_io_tests}, - {"udp_binary_io", (test_callback_fn)binary_init_udp, 0, upd_io_tests}, - {0, 0, 0, 0} -}; - -#define SERVERS_TO_CREATE 5 - -#include "libmemcached_world.h" - -void get_world(world_st *world) -{ - world->collections= collection; - - world->create= (test_callback_create_fn)world_create; - world->destroy= (test_callback_fn)world_destroy; - - world->test.startup= (test_callback_fn)world_test_startup; - world->test.flush= (test_callback_fn)world_flush; - world->test.pre_run= (test_callback_fn)world_pre_run; - world->test.post_run= (test_callback_fn)world_post_run; - world->test.on_error= (test_callback_error_fn)world_on_error; - - world->collection.startup= (test_callback_fn)world_container_startup; - world->collection.shutdown= (test_callback_fn)world_container_shutdown; - - world->runner= &defualt_libmemcached_runner; -} diff --git a/tests/mem_udp.cc b/tests/mem_udp.cc new file mode 100644 index 00000000..8153e8ef --- /dev/null +++ b/tests/mem_udp.cc @@ -0,0 +1,511 @@ +/* libMemcached Functions Test + * Copyright (C) 2006-2009 Brian Aker + * All rights reserved. + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + */ + +/* + Sample test application. +*/ + +#include "config.h" + +#include "libmemcached/common.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SERVERS_TO_CREATE 5 + +#ifndef __INTEL_COMPILER +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + +/** + @note This should be testing to see if the server really supports the binary protocol. +*/ +static test_return_t pre_binary(memcached_st *memc) +{ + memcached_return_t rc= MEMCACHED_FAILURE; + memcached_st *memc_clone; + memcached_server_instance_st instance; + + memc_clone= memcached_clone(NULL, memc); + test_true(memc_clone); + // The memcached_version needs to be done on a clone, because the server + // will not toggle protocol on an connection. + memcached_version(memc_clone); + + instance= memcached_server_instance_by_position(memc_clone, 0); + + if (instance->major_version >= 1 && instance->minor_version > 2) + { + rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); + test_true(rc == MEMCACHED_SUCCESS); + test_true(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1); + } + + memcached_free(memc_clone); + + return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED; +} + +static void increment_request_id(uint16_t *id) +{ + (*id)++; + if ((*id & UDP_REQUEST_ID_THREAD_MASK) != 0) + *id= 0; +} + +static uint16_t *get_udp_request_ids(memcached_st *memc) +{ + uint16_t *ids= (uint16_t*)malloc(sizeof(uint16_t) * memcached_server_count(memc)); + assert(ids); + + for (uint32_t x= 0; x < memcached_server_count(memc); x++) + { + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, x); + + ids[x]= get_udp_datagram_request_id((struct udp_datagram_header_st *) ((memcached_server_instance_st )instance)->write_buffer); + } + + return ids; +} + +static test_return_t post_udp_op_check(memcached_st *memc, uint16_t *expected_req_ids) +{ + (void)memc; + (void)expected_req_ids; +#if 0 + memcached_server_st *cur_server = memcached_server_list(memc); + uint16_t *cur_req_ids = get_udp_request_ids(memc); + + for (size_t x= 0; x < memcached_server_count(memc); x++) + { + test_true(cur_server[x].cursor_active == 0); + test_true(cur_req_ids[x] == expected_req_ids[x]); + } + free(expected_req_ids); + free(cur_req_ids); + +#endif + return TEST_SUCCESS; +} + +/* +** There is a little bit of a hack here, instead of removing +** the servers, I just set num host to 0 and them add then new udp servers +**/ +static test_return_t init_udp(memcached_st *memc) +{ + memcached_version(memc); +#if 0 + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, 0); + + /* For the time being, only support udp test for >= 1.2.6 && < 1.3 */ + if (instance->major_version != 1 || instance->minor_version != 2 + || instance->micro_version < 6) + return TEST_SKIPPED; + + uint32_t num_hosts= memcached_server_count(memc); + memcached_server_st servers[num_hosts]; + memcpy(servers, memcached_server_list(memc), sizeof(memcached_server_st) * num_hosts); + for (uint32_t x= 0; x < num_hosts; x++) + { + memcached_server_instance_st set_instance= + memcached_server_instance_by_position(memc, x); + + memcached_server_free(((memcached_server_write_instance_st)set_instance)); + } + + memc->number_of_hosts= 0; + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1); + for (uint32_t x= 0; x < num_hosts; x++) + { + memcached_server_instance_st set_instance= + memcached_server_instance_by_position(memc, x); + + test_true(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS); + test_true(set_instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); + } +#endif + + return TEST_SKIPPED; +} + +static test_return_t binary_init_udp(memcached_st *memc) +{ + test_return_t test_rc; + test_rc= pre_binary(memc); + + if (test_rc != TEST_SUCCESS) + return test_rc; + + return init_udp(memc); +} + +/* Make sure that I cant add a tcp server to a udp client */ +static test_return_t add_tcp_server_udp_client_test(memcached_st *memc) +{ + (void)memc; +#if 0 + memcached_server_st server; + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, 0); + memcached_server_clone(&server, &memc->hosts[0]); + test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS); + test_true(memcached_server_add(memc, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL); +#endif + return TEST_SUCCESS; +} + +/* Make sure that I cant add a udp server to a tcp client */ +static test_return_t add_udp_server_tcp_client_test(memcached_st *memc) +{ + (void)memc; +#if 0 + memcached_server_st server; + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, 0); + memcached_server_clone(&server, &memc->hosts[0]); + test_true(memcached_server_remove(&(memc->hosts[0])) == MEMCACHED_SUCCESS); + + memcached_st tcp_client; + memcached_create(&tcp_client); + test_true(memcached_server_add_udp(&tcp_client, server.hostname, server.port) == MEMCACHED_INVALID_HOST_PROTOCOL); +#endif + + return TEST_SUCCESS; +} + +static test_return_t set_udp_behavior_test(memcached_st *memc) +{ + + memcached_quit(memc); + memc->number_of_hosts= 0; + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution); + test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1) == MEMCACHED_SUCCESS); + test_true(memc->flags.use_udp); + test_true(memc->flags.no_reply); + + test_true(memcached_server_count(memc) == 0); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP,0); + test_true(! (memc->flags.use_udp)); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY,0); + test_true(! (memc->flags.no_reply)); + + return TEST_SUCCESS; +} + +static test_return_t udp_set_test(memcached_st *memc) +{ + unsigned int num_iters= 1025; //request id rolls over at 1024 + + for (size_t x= 0; x < num_iters;x++) + { + memcached_return_t rc; + const char *key= "foo"; + const char *value= "when we sanitize"; + uint16_t *expected_ids= get_udp_request_ids(memc); + unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, server_key); + size_t init_offset= instance->write_buffer_offset; + + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); + /** NB, the check below assumes that if new write_ptr is less than + * the original write_ptr that we have flushed. For large payloads, this + * maybe an invalid assumption, but for the small payload we have it is OK + */ + if (rc == MEMCACHED_SUCCESS || + instance->write_buffer_offset < init_offset) + increment_request_id(&expected_ids[server_key]); + + if (rc == MEMCACHED_SUCCESS) + { + test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); + } + else + { + test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH); + test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH); + } + test_true(post_udp_op_check(memc, expected_ids) == TEST_SUCCESS); + } + return TEST_SUCCESS; +} + +static test_return_t udp_buffered_set_test(memcached_st *memc) +{ + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); + return udp_set_test(memc); +} + +static test_return_t udp_set_too_big_test(memcached_st *memc) +{ + memcached_return_t rc; + const char *key= "bar"; + char value[MAX_UDP_DATAGRAM_LENGTH]; + uint16_t *expected_ids= get_udp_request_ids(memc); + rc= memcached_set(memc, key, strlen(key), + value, MAX_UDP_DATAGRAM_LENGTH, + (time_t)0, (uint32_t)0); + test_true(rc == MEMCACHED_WRITE_FAILURE); + + return post_udp_op_check(memc,expected_ids); +} + +static test_return_t udp_delete_test(memcached_st *memc) +{ + unsigned int num_iters= 1025; //request id rolls over at 1024 + + for (size_t x= 0; x < num_iters;x++) + { + memcached_return_t rc; + const char *key= "foo"; + uint16_t *expected_ids=get_udp_request_ids(memc); + unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); + memcached_server_instance_st instance= + memcached_server_instance_by_position(memc, server_key); + size_t init_offset= instance->write_buffer_offset; + + rc= memcached_delete(memc, key, strlen(key), 0); + test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); + + if (rc == MEMCACHED_SUCCESS || instance->write_buffer_offset < init_offset) + increment_request_id(&expected_ids[server_key]); + if (rc == MEMCACHED_SUCCESS) + { + test_true(instance->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH); + } + else + { + test_true(instance->write_buffer_offset != UDP_DATAGRAM_HEADER_LENGTH); + test_true(instance->write_buffer_offset <= MAX_UDP_DATAGRAM_LENGTH); + } + test_true(post_udp_op_check(memc,expected_ids) == TEST_SUCCESS); + } + return TEST_SUCCESS; +} + +static test_return_t udp_buffered_delete_test(memcached_st *memc) +{ + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); + return udp_delete_test(memc); +} + +static test_return_t udp_verbosity_test(memcached_st *memc) +{ + memcached_return_t rc; + uint16_t *expected_ids= get_udp_request_ids(memc); + + for (size_t x= 0; x < memcached_server_count(memc); x++) + { + increment_request_id(&expected_ids[x]); + } + + rc= memcached_verbosity(memc,3); + test_true(rc == MEMCACHED_SUCCESS); + return post_udp_op_check(memc,expected_ids); +} + +static test_return_t udp_quit_test(memcached_st *memc) +{ + uint16_t *expected_ids= get_udp_request_ids(memc); + memcached_quit(memc); + return post_udp_op_check(memc, expected_ids); +} + +static test_return_t udp_flush_test(memcached_st *memc) +{ + memcached_return_t rc; + uint16_t *expected_ids= get_udp_request_ids(memc); + + for (size_t x= 0; x < memcached_server_count(memc); x++) + { + increment_request_id(&expected_ids[x]); + } + + rc= memcached_flush(memc,0); + test_true(rc == MEMCACHED_SUCCESS); + return post_udp_op_check(memc,expected_ids); +} + +static test_return_t udp_incr_test(memcached_st *memc) +{ + memcached_return_t rc; + const char *key= "incr"; + const char *value= "1"; + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + + test_true(rc == MEMCACHED_SUCCESS); + uint16_t *expected_ids= get_udp_request_ids(memc); + unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); + increment_request_id(&expected_ids[server_key]); + uint64_t newvalue; + rc= memcached_increment(memc, key, strlen(key), 1, &newvalue); + test_true(rc == MEMCACHED_SUCCESS); + return post_udp_op_check(memc, expected_ids); +} + +static test_return_t udp_decr_test(memcached_st *memc) +{ + memcached_return_t rc; + const char *key= "decr"; + const char *value= "1"; + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)0, (uint32_t)0); + + test_true(rc == MEMCACHED_SUCCESS); + uint16_t *expected_ids= get_udp_request_ids(memc); + unsigned int server_key= memcached_generate_hash(memc, key, strlen(key)); + increment_request_id(&expected_ids[server_key]); + uint64_t newvalue; + rc= memcached_decrement(memc, key, strlen(key), 1, &newvalue); + test_true(rc == MEMCACHED_SUCCESS); + return post_udp_op_check(memc, expected_ids); +} + + +static test_return_t udp_stat_test(memcached_st *memc) +{ + memcached_stat_st * rv= NULL; + memcached_return_t rc; + char args[]= ""; + uint16_t *expected_ids = get_udp_request_ids(memc); + rv = memcached_stat(memc, args, &rc); + free(rv); + test_true(rc == MEMCACHED_NOT_SUPPORTED); + return post_udp_op_check(memc, expected_ids); +} + +static test_return_t udp_version_test(memcached_st *memc) +{ + memcached_return_t rc; + uint16_t *expected_ids = get_udp_request_ids(memc); + rc = memcached_version(memc); + test_true(rc == MEMCACHED_NOT_SUPPORTED); + return post_udp_op_check(memc, expected_ids); +} + +static test_return_t udp_get_test(memcached_st *memc) +{ + memcached_return_t rc; + const char *key= "foo"; + size_t vlen; + uint16_t *expected_ids = get_udp_request_ids(memc); + char *val= memcached_get(memc, key, strlen(key), &vlen, (uint32_t)0, &rc); + test_true(rc == MEMCACHED_NOT_SUPPORTED); + test_true(val == NULL); + return post_udp_op_check(memc, expected_ids); +} + +static test_return_t udp_mixed_io_test(memcached_st *memc) +{ + test_st current_op; + test_st mixed_io_ops [] ={ + {"udp_set_test", 0, + (test_callback_fn*)udp_set_test}, + {"udp_set_too_big_test", 0, + (test_callback_fn*)udp_set_too_big_test}, + {"udp_delete_test", 0, + (test_callback_fn*)udp_delete_test}, + {"udp_verbosity_test", 0, + (test_callback_fn*)udp_verbosity_test}, + {"udp_quit_test", 0, + (test_callback_fn*)udp_quit_test}, + {"udp_flush_test", 0, + (test_callback_fn*)udp_flush_test}, + {"udp_incr_test", 0, + (test_callback_fn*)udp_incr_test}, + {"udp_decr_test", 0, + (test_callback_fn*)udp_decr_test}, + {"udp_version_test", 0, + (test_callback_fn*)udp_version_test} + }; + + for (size_t x= 0; x < 500; x++) + { + current_op= mixed_io_ops[random() % 9]; + test_true(current_op.test_fn(memc) == TEST_SUCCESS); + } + return TEST_SUCCESS; +} + +test_st udp_setup_server_tests[] ={ + {"set_udp_behavior_test", 0, (test_callback_fn*)set_udp_behavior_test}, + {"add_tcp_server_udp_client_test", 0, (test_callback_fn*)add_tcp_server_udp_client_test}, + {"add_udp_server_tcp_client_test", 0, (test_callback_fn*)add_udp_server_tcp_client_test}, + {0, 0, 0} +}; + +test_st upd_io_tests[] ={ + {"udp_set_test", 0, (test_callback_fn*)udp_set_test}, + {"udp_buffered_set_test", 0, (test_callback_fn*)udp_buffered_set_test}, + {"udp_set_too_big_test", 0, (test_callback_fn*)udp_set_too_big_test}, + {"udp_delete_test", 0, (test_callback_fn*)udp_delete_test}, + {"udp_buffered_delete_test", 0, (test_callback_fn*)udp_buffered_delete_test}, + {"udp_verbosity_test", 0, (test_callback_fn*)udp_verbosity_test}, + {"udp_quit_test", 0, (test_callback_fn*)udp_quit_test}, + {"udp_flush_test", 0, (test_callback_fn*)udp_flush_test}, + {"udp_incr_test", 0, (test_callback_fn*)udp_incr_test}, + {"udp_decr_test", 0, (test_callback_fn*)udp_decr_test}, + {"udp_stat_test", 0, (test_callback_fn*)udp_stat_test}, + {"udp_version_test", 0, (test_callback_fn*)udp_version_test}, + {"udp_get_test", 0, (test_callback_fn*)udp_get_test}, + {"udp_mixed_io_test", 0, (test_callback_fn*)udp_mixed_io_test}, + {0, 0, 0} +}; + +collection_st collection[] ={ + {"udp_setup", (test_callback_fn*)init_udp, 0, udp_setup_server_tests}, + {"udp_io", (test_callback_fn*)init_udp, 0, upd_io_tests}, + {"udp_binary_io", (test_callback_fn*)binary_init_udp, 0, upd_io_tests}, + {0, 0, 0, 0} +}; + +#define SERVERS_TO_CREATE 5 + +#include "libmemcached_world.h" + +void get_world(Framework *world) +{ + world->collections= collection; + + world->_create= (test_callback_create_fn*)world_create; + world->_destroy= (test_callback_fn*)world_destroy; + + world->item._startup= (test_callback_fn*)world_test_startup; + world->item._flush= (test_callback_fn*)world_flush; + world->item.set_pre((test_callback_fn*)world_pre_run); + world->item.set_post((test_callback_fn*)world_post_run); + world->_on_error= (test_callback_error_fn*)world_on_error; + + world->collection_startup= (test_callback_fn*)world_container_startup; + world->collection_shutdown= (test_callback_fn*)world_container_shutdown; + + world->runner= &defualt_libmemcached_runner; +} diff --git a/tests/parser.cc b/tests/parser.cc index bb2de83f..ad602048 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -43,13 +43,15 @@ #include #include +#include + #define BUILDING_LIBMEMCACHED // !NEVER use common.h, always use memcached.h in your own apps #include #include -#include "tests/parser.h" -#include "tests/print.h" +#include +#include enum scanner_type_t { @@ -334,7 +336,7 @@ test_return_t memcached_create_with_options_with_filename(memcached_st*) return TEST_SKIPPED; memcached_st *memc_ptr; - memc_ptr= memcached(STRING_WITH_LEN("--CONFIGURE-FILE=\"support/example.cnf\"")); + memc_ptr= memcached(test_literal_param("--CONFIGURE-FILE=\"support/example.cnf\"")); test_true_got(memc_ptr, "memcached() failed"); test_strcmp(SUPPORT_EXAMPLE_CNF, memcached_array_string(memc_ptr->configure.filename)); memcached_free(memc_ptr); @@ -350,13 +352,13 @@ test_return_t libmemcached_check_configuration_with_filename_test(memcached_st*) memcached_return_t rc; char buffer[BUFSIZ]; - rc= libmemcached_check_configuration(STRING_WITH_LEN("--CONFIGURE-FILE=\"support/example.cnf\""), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--CONFIGURE-FILE=\"support/example.cnf\""), buffer, sizeof(buffer)); test_true_got(rc == MEMCACHED_SUCCESS, (rc == MEMCACHED_ERRNO) ? strerror(errno) : memcached_strerror(NULL, rc)); - rc= libmemcached_check_configuration(STRING_WITH_LEN("--CONFIGURE-FILE=support/example.cnf"), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--CONFIGURE-FILE=support/example.cnf"), buffer, sizeof(buffer)); test_false_with(rc == MEMCACHED_SUCCESS, memcached_strerror(NULL, rc)); - rc= libmemcached_check_configuration(STRING_WITH_LEN("--CONFIGURE-FILE=\"bad-path/example.cnf\""), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--CONFIGURE-FILE=\"bad-path/example.cnf\""), buffer, sizeof(buffer)); test_true_got(rc == MEMCACHED_ERRNO, memcached_strerror(NULL, rc)); return TEST_SUCCESS; @@ -367,10 +369,10 @@ test_return_t libmemcached_check_configuration_test(memcached_st*) memcached_return_t rc; char buffer[BUFSIZ]; - rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost"), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--server=localhost"), buffer, sizeof(buffer)); test_true_got(rc == MEMCACHED_SUCCESS, buffer); - rc= libmemcached_check_configuration(STRING_WITH_LEN("--dude=localhost"), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--dude=localhost"), buffer, sizeof(buffer)); test_false_with(rc == MEMCACHED_SUCCESS, buffer); test_true(rc == MEMCACHED_PARSE_ERROR); @@ -380,11 +382,11 @@ test_return_t libmemcached_check_configuration_test(memcached_st*) test_return_t memcached_create_with_options_test(memcached_st*) { memcached_st *memc_ptr; - memc_ptr= memcached(STRING_WITH_LEN("--server=localhost")); + memc_ptr= memcached(test_literal_param("--server=localhost")); test_true_got(memc_ptr, memcached_last_error_message(memc_ptr)); memcached_free(memc_ptr); - memc_ptr= memcached(STRING_WITH_LEN("--dude=localhost")); + memc_ptr= memcached(test_literal_param("--dude=localhost")); test_false_with(memc_ptr, memcached_last_error_message(memc_ptr)); return TEST_SUCCESS; @@ -397,7 +399,7 @@ test_return_t test_include_keyword(memcached_st*) char buffer[BUFSIZ]; memcached_return_t rc; - rc= libmemcached_check_configuration(STRING_WITH_LEN("INCLUDE \"support/example.cnf\""), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("INCLUDE \"support/example.cnf\""), buffer, sizeof(buffer)); test_true_got(rc == MEMCACHED_SUCCESS, buffer); return TEST_SUCCESS; @@ -407,7 +409,7 @@ test_return_t test_end_keyword(memcached_st*) { char buffer[BUFSIZ]; memcached_return_t rc; - rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost END bad keywords"), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--server=localhost END bad keywords"), buffer, sizeof(buffer)); test_true_got(rc == MEMCACHED_SUCCESS, buffer); return TEST_SUCCESS; @@ -417,7 +419,7 @@ test_return_t test_reset_keyword(memcached_st*) { char buffer[BUFSIZ]; memcached_return_t rc; - rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost reset --server=bad.com"), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--server=localhost reset --server=bad.com"), buffer, sizeof(buffer)); test_true_got(rc == MEMCACHED_SUCCESS, buffer); return TEST_SUCCESS; @@ -427,7 +429,7 @@ test_return_t test_error_keyword(memcached_st*) { char buffer[BUFSIZ]; memcached_return_t rc; - rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost ERROR --server=bad.com"), buffer, sizeof(buffer)); + rc= libmemcached_check_configuration(test_literal_param("--server=localhost ERROR --server=bad.com"), buffer, sizeof(buffer)); test_true_got(rc != MEMCACHED_SUCCESS, buffer); return TEST_SUCCESS; diff --git a/tests/parser.h b/tests/parser.h index 15d57a64..dac1a691 100644 --- a/tests/parser.h +++ b/tests/parser.h @@ -37,8 +37,6 @@ #pragma once -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/tests/plus.cpp b/tests/plus.cpp index 59ebf555..f67fcf27 100644 --- a/tests/plus.cpp +++ b/tests/plus.cpp @@ -14,7 +14,7 @@ #include -#include +#include #include #include @@ -199,15 +199,15 @@ test_return_t basic_behavior(memcached_st *original) test_st tests[] ={ { "basic", 0, - reinterpret_cast(basic_test) }, + reinterpret_cast(basic_test) }, { "basic_master_key", 0, - reinterpret_cast(basic_master_key_test) }, + reinterpret_cast(basic_master_key_test) }, { "increment_test", 0, - reinterpret_cast(increment_test) }, + reinterpret_cast(increment_test) }, { "mget", 1, - reinterpret_cast(mget_test) }, + reinterpret_cast(mget_test) }, { "basic_behavior", 0, - reinterpret_cast(basic_behavior) }, + reinterpret_cast(basic_behavior) }, {0, 0, 0} }; @@ -220,21 +220,21 @@ collection_st collection[] ={ #include "libmemcached_world.h" -void get_world(world_st *world) +void get_world(Framework *world) { world->collections= collection; - world->create= reinterpret_cast(world_create); - world->destroy= reinterpret_cast(world_destroy); + world->_create= reinterpret_cast(world_create); + world->_destroy= reinterpret_cast(world_destroy); - world->test.startup= reinterpret_cast(world_test_startup); - world->test.flush= reinterpret_cast(world_flush); - world->test.pre_run= reinterpret_cast(world_pre_run); - world->test.post_run= reinterpret_cast(world_post_run); - world->test.on_error= reinterpret_cast(world_on_error); + world->item._startup= reinterpret_cast(world_test_startup); + world->item._flush= reinterpret_cast(world_flush); + world->item.set_pre(reinterpret_cast(world_pre_run)); + world->item.set_post(reinterpret_cast(world_post_run)); + world->_on_error= reinterpret_cast(world_on_error); - world->collection.startup= reinterpret_cast(world_container_startup); - world->collection.shutdown= reinterpret_cast(world_container_shutdown); + world->collection_startup= reinterpret_cast(world_container_startup); + world->collection_shutdown= reinterpret_cast(world_container_shutdown); world->runner= &defualt_libmemcached_runner; } diff --git a/tests/pool.cc b/tests/pool.cc index ed5016f0..9e1d94f7 100644 --- a/tests/pool.cc +++ b/tests/pool.cc @@ -37,10 +37,12 @@ #include +#include + #include #include #include -#include +#include #include #include diff --git a/tests/pool.h b/tests/pool.h index 45bb14da..ff4d47c7 100644 --- a/tests/pool.h +++ b/tests/pool.h @@ -37,8 +37,6 @@ #pragma once -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/tests/print.cc b/tests/print.cc index 570ab0f0..b3c8d066 100644 --- a/tests/print.cc +++ b/tests/print.cc @@ -40,7 +40,7 @@ #include #include -#include +#include #include "tests/print.h" diff --git a/tests/replication.cc b/tests/replication.cc index 92d68066..3e4476c5 100644 --- a/tests/replication.cc +++ b/tests/replication.cc @@ -37,7 +37,7 @@ #include -#include +#include #include "libmemcached/common.h" #include diff --git a/tests/start.c b/tests/start.c deleted file mode 100644 index 1f5d43e2..00000000 --- a/tests/start.c +++ /dev/null @@ -1,29 +0,0 @@ -/* LibMemcached - * Copyright (C) 2006-2009 Brian Aker - * All rights reserved. - * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. - * - * Summary: - * - */ - -#include "config.h" - -#include -#include -#include - -int main(void) -{ - server_startup_st construct; - - memset(&construct, 0, sizeof(server_startup_st)); - - construct.count= 4; - - server_startup(&construct); - - return EXIT_SUCCESS; -} diff --git a/tests/start.cc b/tests/start.cc new file mode 100644 index 00000000..1f5d43e2 --- /dev/null +++ b/tests/start.cc @@ -0,0 +1,29 @@ +/* LibMemcached + * Copyright (C) 2006-2009 Brian Aker + * All rights reserved. + * + * Use and distribution licensed under the BSD license. See + * the COPYING file in the parent directory for full text. + * + * Summary: + * + */ + +#include "config.h" + +#include +#include +#include + +int main(void) +{ + server_startup_st construct; + + memset(&construct, 0, sizeof(server_startup_st)); + + construct.count= 4; + + server_startup(&construct); + + return EXIT_SUCCESS; +} diff --git a/tests/string.cc b/tests/string.cc index 5c6175f8..4048d91c 100644 --- a/tests/string.cc +++ b/tests/string.cc @@ -38,6 +38,9 @@ #define BUILDING_LIBMEMCACHED #include + +#include + #include #include diff --git a/tests/string.h b/tests/string.h index eebd0c11..12f06109 100644 --- a/tests/string.h +++ b/tests/string.h @@ -37,8 +37,6 @@ #pragma once -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/tests/virtual_buckets.cc b/tests/virtual_buckets.cc index 308fa1d8..1714600e 100644 --- a/tests/virtual_buckets.cc +++ b/tests/virtual_buckets.cc @@ -37,6 +37,7 @@ #include +#include #include #include diff --git a/tests/virtual_buckets.h b/tests/virtual_buckets.h index 054ec492..dee47694 100644 --- a/tests/virtual_buckets.h +++ b/tests/virtual_buckets.h @@ -37,8 +37,6 @@ #pragma once -#include - struct memcached_st; #ifdef __cplusplus