Merge lp:~avsej/libmemcached/touch-command into lp:~tangent-org/libmemcached/trunk

Proposed by Sergey Avseyev
Status: Superseded
Proposed branch: lp:~avsej/libmemcached/touch-command
Merge into: lp:~tangent-org/libmemcached/trunk
Diff against target: 99078 lines (+95976/-0) (has conflicts)
611 files modified
.bzrignore (+100/-0)
.hgignore (+87/-0)
.quickly (+5/-0)
AUTHORS (+11/-0)
COPYING (+33/-0)
ChangeLog (+393/-0)
Makefile.am (+111/-0)
NEWS (+1/-0)
README (+43/-0)
README.FIRST (+31/-0)
README.win32 (+25/-0)
THANKS (+14/-0)
TODO (+11/-0)
clients/client_options.h (+45/-0)
clients/execute.cc (+131/-0)
clients/execute.h (+30/-0)
clients/generator.cc (+96/-0)
clients/generator.h (+36/-0)
clients/include.am (+116/-0)
clients/memaslap.c (+908/-0)
clients/memcapable.cc (+2094/-0)
clients/memcat.cc (+242/-0)
clients/memcp.cc (+317/-0)
clients/memdump.cc (+183/-0)
clients/memerror.cc (+102/-0)
clients/memflush.cc (+154/-0)
clients/memparse.cc (+68/-0)
clients/memrm.cc (+177/-0)
clients/memslap.cc (+495/-0)
clients/memstat.cc (+349/-0)
clients/ms_atomic.h (+69/-0)
clients/ms_conn.c (+3413/-0)
clients/ms_conn.h (+241/-0)
clients/ms_memslap.h (+132/-0)
clients/ms_setting.c (+1068/-0)
clients/ms_setting.h (+181/-0)
clients/ms_sigsegv.c (+126/-0)
clients/ms_sigsegv.h (+34/-0)
clients/ms_stats.c (+307/-0)
clients/ms_stats.h (+69/-0)
clients/ms_task.c (+1114/-0)
clients/ms_task.h (+94/-0)
clients/ms_thread.c (+351/-0)
clients/ms_thread.h (+78/-0)
clients/utilities.cc (+229/-0)
clients/utilities.h (+64/-0)
config/autorun.sh (+126/-0)
config/config.rpath (+666/-0)
config/lcov.am (+42/-0)
config/pandora-plugin (+752/-0)
config/uncrustify.cfg (+1112/-0)
configure.ac (+186/-0)
docs/client_errors/MEMCACHED_AUTH_CONTINUE.rst (+5/-0)
docs/client_errors/MEMCACHED_AUTH_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_AUTH_PROBLEM.rst (+5/-0)
docs/client_errors/MEMCACHED_BAD_KEY_PROVIDED.rst (+5/-0)
docs/client_errors/MEMCACHED_BUFFERED.rst (+5/-0)
docs/client_errors/MEMCACHED_CLIENT_ERROR.rst (+5/-0)
docs/client_errors/MEMCACHED_CONNECTION_BIND_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_CONNECTION_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_DATA_DOES_NOT_EXIST.rst (+5/-0)
docs/client_errors/MEMCACHED_DATA_EXISTS.rst (+5/-0)
docs/client_errors/MEMCACHED_DELETED.rst (+5/-0)
docs/client_errors/MEMCACHED_DEPRECATED.rst (+5/-0)
docs/client_errors/MEMCACHED_E2BIG.rst (+5/-0)
docs/client_errors/MEMCACHED_END.rst (+5/-0)
docs/client_errors/MEMCACHED_ERRNO.rst (+5/-0)
docs/client_errors/MEMCACHED_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_FAIL_UNIX_SOCKET.rst (+5/-0)
docs/client_errors/MEMCACHED_FETCH_NOTFINISHED.rst (+5/-0)
docs/client_errors/MEMCACHED_HOST_LOOKUP_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_INVALID_ARGUMENTS.rst (+5/-0)
docs/client_errors/MEMCACHED_INVALID_HOST_PROTOCOL.rst (+5/-0)
docs/client_errors/MEMCACHED_ITEM.rst (+5/-0)
docs/client_errors/MEMCACHED_KEY_TOO_BIG.rst (+5/-0)
docs/client_errors/MEMCACHED_MAXIMUM_RETURN.rst (+5/-0)
docs/client_errors/MEMCACHED_MEMORY_ALLOCATION_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_NOTFOUND.rst (+5/-0)
docs/client_errors/MEMCACHED_NOTSTORED.rst (+5/-0)
docs/client_errors/MEMCACHED_NOT_SUPPORTED.rst (+5/-0)
docs/client_errors/MEMCACHED_NO_KEY_PROVIDED.rst (+5/-0)
docs/client_errors/MEMCACHED_NO_SERVERS.rst (+5/-0)
docs/client_errors/MEMCACHED_PARSE_ERROR.rst (+5/-0)
docs/client_errors/MEMCACHED_PARSE_USER_ERROR.rst (+5/-0)
docs/client_errors/MEMCACHED_PARTIAL_READ.rst (+5/-0)
docs/client_errors/MEMCACHED_PROTOCOL_ERROR.rst (+5/-0)
docs/client_errors/MEMCACHED_READ_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_SERVER_ERROR.rst (+5/-0)
docs/client_errors/MEMCACHED_SERVER_MARKED_DEAD.rst (+5/-0)
docs/client_errors/MEMCACHED_SOME_ERRORS.rst (+5/-0)
docs/client_errors/MEMCACHED_STAT.rst (+5/-0)
docs/client_errors/MEMCACHED_STORED.rst (+5/-0)
docs/client_errors/MEMCACHED_SUCCESS.rst (+5/-0)
docs/client_errors/MEMCACHED_TIMEOUT.rst (+5/-0)
docs/client_errors/MEMCACHED_UNKNOWN_READ_FAILURE.rst (+5/-0)
docs/client_errors/MEMCACHED_UNKNOWN_STAT_KEY.rst (+5/-0)
docs/client_errors/MEMCACHED_VALUE.rst (+5/-0)
docs/client_errors/MEMCACHED_WRITE_FAILURE.rst (+5/-0)
docs/conf.py.in (+355/-0)
docs/error_messages.rst (+55/-0)
docs/hashkit_create.rst (+65/-0)
docs/hashkit_functions.rst (+76/-0)
docs/hashkit_value.rst (+58/-0)
docs/include.am (+240/-0)
docs/index.rst (+131/-0)
docs/libhashkit.rst (+35/-0)
docs/libmemcached.rst (+185/-0)
docs/libmemcached/memcached_return_t.rst (+133/-0)
docs/libmemcached_configuration.rst (+225/-0)
docs/libmemcached_examples.rst (+144/-0)
docs/libmemcachedutil.rst (+57/-0)
docs/man/hashkit_clone.3 (+92/-0)
docs/man/hashkit_crc32.3 (+105/-0)
docs/man/hashkit_create.3 (+92/-0)
docs/man/hashkit_fnv1_32.3 (+105/-0)
docs/man/hashkit_fnv1_64.3 (+105/-0)
docs/man/hashkit_fnv1a_32.3 (+105/-0)
docs/man/hashkit_fnv1a_64.3 (+105/-0)
docs/man/hashkit_free.3 (+92/-0)
docs/man/hashkit_functions.3 (+105/-0)
docs/man/hashkit_hsieh.3 (+105/-0)
docs/man/hashkit_is_allocated.3 (+92/-0)
docs/man/hashkit_jenkins.3 (+105/-0)
docs/man/hashkit_md5.3 (+105/-0)
docs/man/hashkit_murmur.3 (+105/-0)
docs/man/hashkit_value.3 (+66/-0)
docs/man/libhashkit.3 (+57/-0)
docs/man/libmemcached.3 (+215/-0)
docs/man/libmemcached_check_configuration.3 (+293/-0)
docs/man/libmemcached_configuration.3 (+293/-0)
docs/man/libmemcached_examples.3 (+144/-0)
docs/man/libmemcachedutil.3 (+68/-0)
docs/man/memaslap.1 (+1220/-0)
docs/man/memcached.3 (+293/-0)
docs/man/memcached_add.3 (+121/-0)
docs/man/memcached_add_by_key.3 (+121/-0)
docs/man/memcached_analyze.3 (+77/-0)
docs/man/memcached_append.3 (+111/-0)
docs/man/memcached_append_by_key.3 (+111/-0)
docs/man/memcached_auto.3 (+124/-0)
docs/man/memcached_behavior.3 (+329/-0)
docs/man/memcached_behavior_get.3 (+329/-0)
docs/man/memcached_behavior_set.3 (+329/-0)
docs/man/memcached_callback.3 (+174/-0)
docs/man/memcached_callback_get.3 (+174/-0)
docs/man/memcached_callback_set.3 (+174/-0)
docs/man/memcached_cas.3 (+91/-0)
docs/man/memcached_cas_by_key.3 (+91/-0)
docs/man/memcached_clone.3 (+104/-0)
docs/man/memcached_create.3 (+104/-0)
docs/man/memcached_decrement.3 (+124/-0)
docs/man/memcached_decrement_with_initial.3 (+124/-0)
docs/man/memcached_delete.3 (+84/-0)
docs/man/memcached_delete_by_key.3 (+84/-0)
docs/man/memcached_destroy_sasl_auth_data.3 (+94/-0)
docs/man/memcached_dump.3 (+78/-0)
docs/man/memcached_fetch.3 (+168/-0)
docs/man/memcached_fetch_execute.3 (+168/-0)
docs/man/memcached_fetch_result.3 (+168/-0)
docs/man/memcached_flush.3 (+73/-0)
docs/man/memcached_flush_buffers.3 (+72/-0)
docs/man/memcached_free.3 (+104/-0)
docs/man/memcached_generate_hash.3 (+85/-0)
docs/man/memcached_generate_hash_value.3 (+85/-0)
docs/man/memcached_get.3 (+168/-0)
docs/man/memcached_get_by_key.3 (+168/-0)
docs/man/memcached_get_memory_allocators.3 (+112/-0)
docs/man/memcached_get_sasl_callbacks.3 (+94/-0)
docs/man/memcached_get_user_data.3 (+76/-0)
docs/man/memcached_increment.3 (+124/-0)
docs/man/memcached_increment_with_initial.3 (+124/-0)
docs/man/memcached_lib_version.3 (+76/-0)
docs/man/memcached_memory_allocators.3 (+112/-0)
docs/man/memcached_mget.3 (+168/-0)
docs/man/memcached_mget_by_key.3 (+168/-0)
docs/man/memcached_mget_execute.3 (+168/-0)
docs/man/memcached_mget_execute_by_key.3 (+168/-0)
docs/man/memcached_pool.3 (+134/-0)
docs/man/memcached_pool_behavior_get.3 (+134/-0)
docs/man/memcached_pool_behavior_set.3 (+134/-0)
docs/man/memcached_pool_create.3 (+134/-0)
docs/man/memcached_pool_destroy.3 (+134/-0)
docs/man/memcached_pool_pop.3 (+134/-0)
docs/man/memcached_pool_push.3 (+134/-0)
docs/man/memcached_pool_st.3 (+134/-0)
docs/man/memcached_prepend.3 (+111/-0)
docs/man/memcached_prepend_by_key.3 (+111/-0)
docs/man/memcached_quit.3 (+73/-0)
docs/man/memcached_replace.3 (+121/-0)
docs/man/memcached_replace_by_key.3 (+121/-0)
docs/man/memcached_result_cas.3 (+154/-0)
docs/man/memcached_result_create.3 (+154/-0)
docs/man/memcached_result_flags.3 (+154/-0)
docs/man/memcached_result_free.3 (+154/-0)
docs/man/memcached_result_key_length.3 (+154/-0)
docs/man/memcached_result_key_value.3 (+154/-0)
docs/man/memcached_result_length.3 (+154/-0)
docs/man/memcached_result_st.3 (+154/-0)
docs/man/memcached_result_value.3 (+154/-0)
docs/man/memcached_return_t.3 (+261/-0)
docs/man/memcached_sasl.3 (+94/-0)
docs/man/memcached_sasl_set_auth_data.3 (+94/-0)
docs/man/memcached_server_add.3 (+135/-0)
docs/man/memcached_server_add_unix_socket.3 (+135/-0)
docs/man/memcached_server_count.3 (+135/-0)
docs/man/memcached_server_cursor.3 (+135/-0)
docs/man/memcached_server_list.3 (+135/-0)
docs/man/memcached_server_list_append.3 (+106/-0)
docs/man/memcached_server_list_count.3 (+106/-0)
docs/man/memcached_server_list_free.3 (+106/-0)
docs/man/memcached_server_push.3 (+135/-0)
docs/man/memcached_server_st.3 (+135/-0)
docs/man/memcached_servers.3 (+135/-0)
docs/man/memcached_servers_parse.3 (+106/-0)
docs/man/memcached_servers_reset.3 (+104/-0)
docs/man/memcached_set.3 (+121/-0)
docs/man/memcached_set_by_key.3 (+121/-0)
docs/man/memcached_set_memory_allocators.3 (+112/-0)
docs/man/memcached_set_memory_allocators_context.3 (+112/-0)
docs/man/memcached_set_sasl_callbacks.3 (+94/-0)
docs/man/memcached_set_user_data.3 (+76/-0)
docs/man/memcached_stat.3 (+103/-0)
docs/man/memcached_stat_execute.3 (+103/-0)
docs/man/memcached_stat_get_keys.3 (+103/-0)
docs/man/memcached_stat_get_value.3 (+103/-0)
docs/man/memcached_stat_servername.3 (+103/-0)
docs/man/memcached_stats.3 (+103/-0)
docs/man/memcached_strerror.3 (+67/-0)
docs/man/memcached_user_data.3 (+76/-0)
docs/man/memcached_verbosity.3 (+68/-0)
docs/man/memcached_version.3 (+76/-0)
docs/man/memcapable.1 (+93/-0)
docs/man/memcat.1 (+81/-0)
docs/man/memcp.1 (+88/-0)
docs/man/memdump.1 (+70/-0)
docs/man/memerror.1 (+69/-0)
docs/man/memflush.1 (+83/-0)
docs/man/memrm.1 (+82/-0)
docs/man/memslap.1 (+79/-0)
docs/man/memstat.1 (+80/-0)
docs/memaslap.rst (+1248/-0)
docs/memcached_analyze.rst (+67/-0)
docs/memcached_append.rst (+97/-0)
docs/memcached_auto.rst (+97/-0)
docs/memcached_behavior.rst (+294/-0)
docs/memcached_callback.rst (+162/-0)
docs/memcached_cas.rst (+78/-0)
docs/memcached_create.rst (+84/-0)
docs/memcached_delete.rst (+73/-0)
docs/memcached_dump.rst (+72/-0)
docs/memcached_flush.rst (+65/-0)
docs/memcached_flush_buffers.rst (+65/-0)
docs/memcached_generate_hash_value.rst (+77/-0)
docs/memcached_get.rst (+140/-0)
docs/memcached_memory_allocators.rst (+93/-0)
docs/memcached_pool.rst (+111/-0)
docs/memcached_quit.rst (+63/-0)
docs/memcached_result_st.rst (+117/-0)
docs/memcached_sasl.rst (+82/-0)
docs/memcached_server_st.rst (+83/-0)
docs/memcached_servers.rst (+102/-0)
docs/memcached_set.rst (+101/-0)
docs/memcached_stats.rst (+89/-0)
docs/memcached_strerror.rst (+57/-0)
docs/memcached_user_data.rst (+73/-0)
docs/memcached_verbosity.rst (+56/-0)
docs/memcached_version.rst (+63/-0)
docs/memcapable.rst (+83/-0)
docs/memcat.rst (+73/-0)
docs/memcp.rst (+75/-0)
docs/memdump.rst (+58/-0)
docs/memerror.rst (+58/-0)
docs/memflush.rst (+67/-0)
docs/memrm.rst (+71/-0)
docs/memslap.rst (+64/-0)
docs/memstat.rst (+61/-0)
docs/tap.rst (+7/-0)
example/include.am (+24/-0)
example/interface_v0.c (+594/-0)
example/interface_v1.c (+411/-0)
example/memcached_light.c (+474/-0)
example/memcached_light.h (+7/-0)
example/storage.c (+172/-0)
example/storage.h (+27/-0)
example/storage_innodb.c (+535/-0)
libhashkit/algorithm.cc (+69/-0)
libhashkit/algorithm.h (+96/-0)
libhashkit/behavior.cc (+9/-0)
libhashkit/behavior.h (+26/-0)
libhashkit/common.h (+33/-0)
libhashkit/configure.h.in (+19/-0)
libhashkit/crc32.cc (+86/-0)
libhashkit/digest.cc (+60/-0)
libhashkit/digest.h (+30/-0)
libhashkit/fnv.cc (+75/-0)
libhashkit/function.cc (+156/-0)
libhashkit/function.h (+44/-0)
libhashkit/hashkit.cc (+100/-0)
libhashkit/hashkit.h (+95/-0)
libhashkit/hashkit.hpp (+97/-0)
libhashkit/hsieh.cc (+70/-0)
libhashkit/include.am (+69/-0)
libhashkit/jenkins.cc (+214/-0)
libhashkit/ketama.cc (+164/-0)
libhashkit/md5.cc (+367/-0)
libhashkit/murmur.cc (+77/-0)
libhashkit/one_at_a_time.cc (+34/-0)
libhashkit/str_algorithm.cc (+57/-0)
libhashkit/str_algorithm.h (+48/-0)
libhashkit/strerror.cc (+25/-0)
libhashkit/strerror.h (+23/-0)
libhashkit/types.h (+89/-0)
libhashkit/visibility.h (+48/-0)
libmemcached/allocators.cc (+119/-0)
libmemcached/allocators.h (+87/-0)
libmemcached/analyze.cc (+110/-0)
libmemcached/analyze.h (+66/-0)
libmemcached/array.c (+128/-0)
libmemcached/array.h (+75/-0)
libmemcached/auto.cc (+383/-0)
libmemcached/auto.h (+111/-0)
libmemcached/basic_string.h (+55/-0)
libmemcached/behavior.cc (+589/-0)
libmemcached/behavior.h (+86/-0)
libmemcached/byteorder.cc (+90/-0)
libmemcached/byteorder.h (+52/-0)
libmemcached/callback.cc (+160/-0)
libmemcached/callback.h (+61/-0)
libmemcached/common.h (+182/-0)
libmemcached/configure.h.in (+52/-0)
libmemcached/connect.cc (+634/-0)
libmemcached/constants.h (+166/-0)
libmemcached/delete.cc (+266/-0)
libmemcached/delete.h (+57/-0)
libmemcached/do.cc (+100/-0)
libmemcached/do.hpp (+49/-0)
libmemcached/dump.cc (+107/-0)
libmemcached/dump.h (+51/-0)
libmemcached/error.cc (+419/-0)
libmemcached/error.h (+61/-0)
libmemcached/error.hpp (+87/-0)
libmemcached/exception.hpp (+63/-0)
libmemcached/fetch.cc (+264/-0)
libmemcached/fetch.h (+53/-0)
libmemcached/flush.cc (+149/-0)
libmemcached/flush.h (+49/-0)
libmemcached/flush_buffers.cc (+66/-0)
libmemcached/flush_buffers.h (+49/-0)
libmemcached/get.cc (+698/-0)
libmemcached/get.h (+110/-0)
libmemcached/hash.cc (+178/-0)
libmemcached/hash.h (+68/-0)
libmemcached/hosts.cc (+513/-0)
libmemcached/include.am (+182/-0)
libmemcached/initialize_query.cc (+70/-0)
libmemcached/initialize_query.h (+51/-0)
libmemcached/internal.h (+46/-0)
libmemcached/io.cc (+925/-0)
libmemcached/io.h (+119/-0)
libmemcached/is.h (+48/-0)
libmemcached/key.cc (+23/-0)
libmemcached/libmemcached_probes.d (+30/-0)
libmemcached/libmemcached_probes.h (+118/-0)
libmemcached/memcached.cc (+435/-0)
libmemcached/memcached.h (+213/-0)
libmemcached/memcached.hpp (+789/-0)
libmemcached/memcached/README.txt (+7/-0)
libmemcached/memcached/protocol_binary.h (+726/-0)
libmemcached/memcached/vbucket.h (+26/-0)
libmemcached/memcached_util.h (+44/-0)
libmemcached/memory.h (+79/-0)
libmemcached/options.cc (+184/-0)
libmemcached/options.h (+71/-0)
libmemcached/options/context.h (+151/-0)
libmemcached/options/include.am (+19/-0)
libmemcached/options/parser.cc (+2322/-0)
libmemcached/options/parser.h (+122/-0)
libmemcached/options/scanner.cc (+3203/-0)
libmemcached/options/scanner.h (+479/-0)
libmemcached/options/server.h (+60/-0)
libmemcached/options/symbol.h (+57/-0)
libmemcached/parse.cc (+110/-0)
libmemcached/parse.h (+23/-0)
libmemcached/platform.h (+56/-0)
libmemcached/prefix_key.cc (+65/-0)
libmemcached/prefix_key.h (+49/-0)
libmemcached/protocol/ascii_handler.c (+963/-0)
libmemcached/protocol/ascii_handler.h (+40/-0)
libmemcached/protocol/binary_handler.c (+1121/-0)
libmemcached/protocol/binary_handler.h (+47/-0)
libmemcached/protocol/cache.c (+149/-0)
libmemcached/protocol/cache.h (+116/-0)
libmemcached/protocol/callback.h (+418/-0)
libmemcached/protocol/common.h (+163/-0)
libmemcached/protocol/include.am (+26/-0)
libmemcached/protocol/pedantic.c (+202/-0)
libmemcached/protocol/protocol_handler.c (+365/-0)
libmemcached/protocol_handler.h (+215/-0)
libmemcached/purge.cc (+90/-0)
libmemcached/quit.cc (+139/-0)
libmemcached/quit.h (+55/-0)
libmemcached/response.cc (+634/-0)
libmemcached/response.h (+57/-0)
libmemcached/result.cc (+173/-0)
libmemcached/result.h (+100/-0)
libmemcached/return.h (+98/-0)
libmemcached/sasl.c (+408/-0)
libmemcached/sasl.h (+86/-0)
libmemcached/server.cc (+351/-0)
libmemcached/server.h (+169/-0)
libmemcached/server_list.cc (+83/-0)
libmemcached/server_list.h (+77/-0)
libmemcached/stats.cc (+623/-0)
libmemcached/stats.h (+96/-0)
libmemcached/storage.cc (+567/-0)
libmemcached/storage.h (+133/-0)
libmemcached/strerror.cc (+189/-0)
libmemcached/strerror.h (+50/-0)
libmemcached/string.cc (+253/-0)
libmemcached/string.h (+121/-0)
libmemcached/touch.cc (+106/-0)
libmemcached/touch.h (+59/-0)
libmemcached/types.h (+117/-0)
libmemcached/util.h (+40/-0)
libmemcached/util/flush.cc (+61/-0)
libmemcached/util/flush.h (+50/-0)
libmemcached/util/include.am (+34/-0)
libmemcached/util/ping.cc (+62/-0)
libmemcached/util/ping.h (+49/-0)
libmemcached/util/pool.cc (+392/-0)
libmemcached/util/pool.h (+78/-0)
libmemcached/util/version.cc (+87/-0)
libmemcached/util/version.h (+53/-0)
libmemcached/verbosity.cc (+97/-0)
libmemcached/verbosity.h (+50/-0)
libmemcached/version.cc (+214/-0)
libmemcached/version.h (+52/-0)
libmemcached/virtual_bucket.c (+118/-0)
libmemcached/virtual_bucket.h (+59/-0)
libmemcached/visibility.h (+51/-0)
libmemcached/watchpoint.h (+110/-0)
libtest/failed.cc (+75/-0)
libtest/failed.h (+53/-0)
libtest/include.am (+40/-0)
libtest/server.c (+355/-0)
libtest/server.h (+43/-0)
libtest/test.c (+399/-0)
libtest/test.h (+323/-0)
libtest/visibility.h (+69/-0)
m4/ac_cxx_compile_stdcxx_0x.m4 (+103/-0)
m4/ac_cxx_header_stdcxx_98.m4 (+83/-0)
m4/acx_pthread.m4 (+271/-0)
m4/byteorder.m4 (+19/-0)
m4/deprecated.m4 (+17/-0)
m4/eagain.m4 (+28/-0)
m4/enable_utillib.m4 (+16/-0)
m4/gettext.m4 (+379/-0)
m4/hsieh.m4 (+18/-0)
m4/iconv.m4 (+214/-0)
m4/lib-ld.m4 (+110/-0)
m4/lib-link.m4 (+767/-0)
m4/lib-prefix.m4 (+221/-0)
m4/memaslap.m4 (+9/-0)
m4/memcached.m4 (+31/-0)
m4/murmur.m4 (+18/-0)
m4/pandora_64bit.m4 (+60/-0)
m4/pandora_bison.m4 (+33/-0)
m4/pandora_canonical.m4 (+418/-0)
m4/pandora_check_compiler_version.m4 (+37/-0)
m4/pandora_check_cxx_standard.m4 (+23/-0)
m4/pandora_cinttypes.m4 (+39/-0)
m4/pandora_clock_gettime.m4 (+15/-0)
m4/pandora_compile_stdcxx_0x.m4 (+103/-0)
m4/pandora_cstdint.m4 (+38/-0)
m4/pandora_cxx_demangle.m4 (+27/-0)
m4/pandora_enable_dtrace.m4 (+60/-0)
m4/pandora_ensure_gcc_version.m4 (+62/-0)
m4/pandora_extensions.m4 (+16/-0)
m4/pandora_fdatasync.m4 (+25/-0)
m4/pandora_flex.m4 (+33/-0)
m4/pandora_have_better_malloc.m4 (+66/-0)
m4/pandora_have_boost.m4 (+93/-0)
m4/pandora_have_gcc_atomics.m4 (+37/-0)
m4/pandora_have_innodb.m4 (+41/-0)
m4/pandora_have_libaio.m4 (+56/-0)
m4/pandora_have_libavahi.m4 (+41/-0)
m4/pandora_have_libbdb.m4 (+40/-0)
m4/pandora_have_libboost_date_time.m4 (+46/-0)
m4/pandora_have_libboost_filesystem.m4 (+47/-0)
m4/pandora_have_libboost_iostreams.m4 (+49/-0)
m4/pandora_have_libboost_options.m4 (+47/-0)
m4/pandora_have_libboost_regex.m4 (+54/-0)
m4/pandora_have_libboost_test.m4 (+45/-0)
m4/pandora_have_libboost_thread.m4 (+54/-0)
m4/pandora_have_libcassandra.m4 (+44/-0)
m4/pandora_have_libcurl.m4 (+62/-0)
m4/pandora_have_libdl.m4 (+51/-0)
m4/pandora_have_libdrizzle.m4 (+61/-0)
m4/pandora_have_libevent.m4 (+66/-0)
m4/pandora_have_libgearman.m4 (+41/-0)
m4/pandora_have_libgtest.m4 (+47/-0)
m4/pandora_have_libhaildb.m4 (+43/-0)
m4/pandora_have_libhashkit.m4 (+42/-0)
m4/pandora_have_libinnodb.m4 (+64/-0)
m4/pandora_have_libldap.m4 (+73/-0)
m4/pandora_have_libmemcached.m4 (+106/-0)
m4/pandora_have_libmysqlclient.m4 (+146/-0)
m4/pandora_have_libndbclient.m4 (+80/-0)
m4/pandora_have_libpcre.m4 (+73/-0)
m4/pandora_have_libpq.m4 (+46/-0)
m4/pandora_have_libpqxx.m4 (+44/-0)
m4/pandora_have_libsqlite3.m4 (+42/-0)
m4/pandora_have_libtokyocabinet.m4 (+54/-0)
m4/pandora_have_libuuid.m4 (+55/-0)
m4/pandora_have_libvbucket.m4 (+40/-0)
m4/pandora_have_libxml2.m4 (+52/-0)
m4/pandora_have_libz.m4 (+51/-0)
m4/pandora_have_protobuf.m4 (+82/-0)
m4/pandora_have_sasl.m4 (+133/-0)
m4/pandora_have_thrift.m4 (+45/-0)
m4/pandora_header_assert.m4 (+23/-0)
m4/pandora_header_stdcxx_98.m4 (+83/-0)
m4/pandora_intltool.m4 (+225/-0)
m4/pandora_libtool.m4 (+25/-0)
m4/pandora_optimize.m4 (+75/-0)
m4/pandora_platform.m4 (+117/-0)
m4/pandora_plugins.m4 (+62/-0)
m4/pandora_print_callstack.m4 (+61/-0)
m4/pandora_pthread.m4 (+258/-0)
m4/pandora_python3_devel.m4 (+236/-0)
m4/pandora_run_cpplint.m4 (+8/-0)
m4/pandora_sasl.m4 (+133/-0)
m4/pandora_shared_ptr.m4 (+59/-0)
m4/pandora_stack_direction.m4 (+39/-0)
m4/pandora_stl_hash.m4 (+94/-0)
m4/pandora_swig.m4 (+39/-0)
m4/pandora_use_pipe.m4 (+36/-0)
m4/pandora_vc_build.m4 (+168/-0)
m4/pandora_version.m4 (+11/-0)
m4/pandora_visibility.m4 (+75/-0)
m4/pandora_warnings.m4 (+447/-0)
m4/pandora_with_gettext.m4 (+44/-0)
m4/pandora_with_lua.m4 (+55/-0)
m4/pandora_with_memcached.m4 (+41/-0)
m4/pandora_with_perl.m4 (+81/-0)
m4/pandora_with_php.m4 (+56/-0)
m4/pandora_with_python.m4 (+37/-0)
m4/pandora_with_python3.m4 (+44/-0)
m4/pandora_with_r.m4 (+33/-0)
m4/pandora_with_ruby.m4 (+79/-0)
m4/pandora_with_valgrind.m4 (+17/-0)
m4/pkg.m4 (+157/-0)
m4/po.m4 (+449/-0)
m4/progtest.m4 (+92/-0)
m4/protocol_binary.m4 (+36/-0)
m4/setsockopt.m4 (+73/-0)
m4/socket_send_flags.m4 (+66/-0)
poll/include.am (+8/-0)
poll/poll.c (+77/-0)
poll/poll.h (+45/-0)
support/example.cnf (+10/-0)
support/include.am (+11/-0)
support/libmemcached-fc.spec.in (+105/-0)
support/libmemcached.pc.in (+10/-0)
support/libmemcached.spec.in (+281/-0)
support/set_benchmark.sh (+5/-0)
tests/atomsmasher.c (+296/-0)
tests/basic.cc (+132/-0)
tests/basic.h (+66/-0)
tests/cpp_example.cc (+194/-0)
tests/deprecated.cc (+73/-0)
tests/deprecated.h (+49/-0)
tests/error_conditions.cc (+63/-0)
tests/error_conditions.h (+50/-0)
tests/hash_plus.cc (+217/-0)
tests/hash_results.h (+127/-0)
tests/hashkit_functions.c (+602/-0)
tests/include.am (+342/-0)
tests/ketama_test_cases.h (+121/-0)
tests/ketama_test_cases_spy.h (+118/-0)
tests/libmemcached_world.h (+200/-0)
tests/mem_functions.cc (+6581/-0)
tests/mem_udp.c (+508/-0)
tests/output_plus.res (+5/-0)
tests/parser.cc (+599/-0)
tests/parser.h (+111/-0)
tests/plus.cpp (+240/-0)
tests/pool.cc (+78/-0)
tests/pool.h (+51/-0)
tests/print.cc (+59/-0)
tests/print.h (+51/-0)
tests/r/memcat.res (+19/-0)
tests/r/memcp.res (+27/-0)
tests/r/memrm.res (+19/-0)
tests/r/memslap.res (+33/-0)
tests/r/memstat.res (+33/-0)
tests/replication.cc (+334/-0)
tests/replication.h (+64/-0)
tests/start.c (+29/-0)
tests/string.cc (+168/-0)
tests/string.h (+69/-0)
tests/t/memcat.test (+4/-0)
tests/t/memcp.test (+3/-0)
tests/t/memrm.test (+3/-0)
tests/t/memslap.test (+5/-0)
tests/t/memstat.test (+3/-0)
tests/virtual_buckets.cc (+143/-0)
tests/virtual_buckets.h (+53/-0)
win32/include.am (+11/-0)
win32/wrappers.h (+55/-0)
Conflict adding file .bzrignore.  Moved existing file to .bzrignore.moved.
Conflict adding file .hgignore.  Moved existing file to .hgignore.moved.
Conflict adding file .quickly.  Moved existing file to .quickly.moved.
Conflict adding file AUTHORS.  Moved existing file to AUTHORS.moved.
Conflict adding file COPYING.  Moved existing file to COPYING.moved.
Conflict adding file ChangeLog.  Moved existing file to ChangeLog.moved.
Conflict adding file Makefile.am.  Moved existing file to Makefile.am.moved.
Conflict adding file NEWS.  Moved existing file to NEWS.moved.
Conflict adding file README.FIRST.  Moved existing file to README.FIRST.moved.
Conflict adding file README.  Moved existing file to README.moved.
Conflict adding file README.win32.  Moved existing file to README.win32.moved.
Conflict adding file THANKS.  Moved existing file to THANKS.moved.
Conflict adding file TODO.  Moved existing file to TODO.moved.
Conflict adding file clients.  Moved existing file to clients.moved.
Conflict adding file config.  Moved existing file to config.moved.
Conflict adding file configure.ac.  Moved existing file to configure.ac.moved.
Conflict adding file docs.  Moved existing file to docs.moved.
Conflict adding file example.  Moved existing file to example.moved.
Conflict adding file libhashkit.  Moved existing file to libhashkit.moved.
Conflict adding file libmemcached.  Moved existing file to libmemcached.moved.
Conflict adding file libtest.  Moved existing file to libtest.moved.
Conflict adding file m4.  Moved existing file to m4.moved.
Conflict adding file poll.  Moved existing file to poll.moved.
Conflict adding file support.  Moved existing file to support.moved.
Conflict adding file tests.  Moved existing file to tests.moved.
Conflict adding file win32.  Moved existing file to win32.moved.
To merge this branch: bzr merge lp:~avsej/libmemcached/touch-command
Reviewer Review Type Date Requested Status
Libmemcached-developers Pending
Review via email: mp+65623@code.launchpad.net

Commit message

Implemented TOUCH command

Description of the change

Hi guys

I implemented TOUCH command with tests which is implemented in membase/memcached server fork. Tests are skipping on original memcached and passing on membase's.

Kind regards,
Sergey Avseyev

To post a comment you must log in.
Revision history for this message
Brian Aker (brianaker) wrote :
Download full text (15.2 KiB)

Is there way to test if a server is membase or not?

Sent from my C64

On Jun 23, 2011, at 12:17 AM, Sergey Avseyev <email address hidden> wrote:

> Sergey Avseyev has proposed merging lp:~avsej/libmemcached/touch-command into lp:libmemcached.
>
> Requested reviews:
> Libmemcached-developers (libmemcached-developers)
>
> For more details, see:
> https://code.launchpad.net/~avsej/libmemcached/touch-command/+merge/65623
>
> Hi guys
>
> I implemented TOUCH command with tests which is implemented in membase/memcached server fork. Tests are skipping on original memcached and passing on membase's.
>
>
> Kind regards,
> Sergey Avseyev
> --
> The attached diff has been truncated due to its size.
> https://code.launchpad.net/~avsej/libmemcached/touch-command/+merge/65623
> Your team Libmemcached-developers is requested to review the proposed merge of lp:~avsej/libmemcached/touch-command into lp:libmemcached.
> === added file '.bzrignore' --- .bzrignore 1970-01-01 00:00:00 +0000 +++ .bzrignore 2011-06-23 07:17:28 +0000 @@ -0,0 +1,100 @@ +*.BASE +*.OTHER +*.exe +*.lo +*.output +*.pop +*.rpm +*/*.l[oa] +*/*/*.l[oa] +*/*/.deps +*/*/.dirstamp +*/*/.libs +*/.deps +*/.dirstamp +*/.libs +*/Makefile +*/Makefile.in +*TAGS +.deps +INSTALL +Makefile +Makefile.in +TAGS +aclocal.m4 +autom4te.cache +clients/memaslap +clients/memcapable +clients/memcat +clients/memcp +clients/memdump +clients/memerror +clients/memflush +clients/memparse +clients/memrm +clients/memslap +clients/memstat +config.h +config.h.in +config.log +config.status +config/compile +config/config.guess +config/config.sub +config/depcomp +config/install-sh +config/ltmain.sh +config/missing +config/pandora_vc_revinfo +config/plugin.ac +config/top.h +configure +docs/*.[13] +docs/*.html +docs/conf.py +docs/conf.py +docs/doctest/ +docs/doctrees/ +docs/html/ +docs/linkcheck/ +example/memcached_light +libhashkit/configure.h +libmemcached-*.tar.gz +libmemcached-0.30-1.src.rpm +libmemcached-0.30-1.x86_64.rpm +libmemcached-0.31-1.src.rpm +libmemcached-0.31-1.x86_64.rpm +libmemcached-0.37-1.src.rpm +libmemcached-0.37-1.x86_64.rpm +libmemcached-?.??/ +libmemcached/configure.h +libmemcached/dtrace_probes.h +libmemcached/generated_probes.h +libmemcached/memcached_configure.h +libtool +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 +patch +patch2 +stamp-h1 +support/Makefile +support/Makefile.in +support/libmemcached-fc.spec +support/libmemcached.pc +support/libmemcached.spec +tags +tests/atomsmasher +tests/hash_plus +tests/hashplus +tests/memplus +tests/output.cmp +tests/startservers +tests/testapp +tests/testhashkit +tests/testplus +tests/testudp +tests/var/ +unittests/unittests === renamed file '.bzrignore' => '.bzrignore.moved' === added file '.hgignore' --- .hgignore 1970-01-01 00:00:00 +0000 +++ .hgignore 2011-06-23 07:17:28 +0000 @@ -0,0 +1,87 @@ +# Exact paths to config junk +^INSTALL$ +^aclocal.m4$ +^configure$ +^config/(config.guess|config.sub|depcomp|install-sh|ltmain.sh|missing)$ +^config.(log|status)$ +^libtool$ +^autom4te.cache$ +^libmemcached/(libmemcached_config.h(.in)?|stamp-h1)$ +^libmemcached/libmemcached_config.h.in$ +^stamp-h1$ +^lib/libmemcachedPlus.la$ +^tests/...

lp:~avsej/libmemcached/touch-command updated
946. By Brian Aker

Merge in trunk. Updates to manual/update to latest libtest.

947. By Brian Aker

Update build bits.

948. By Brian Aker

Merge of trunk.

949. By Brian Aker

Merge in conditional fix

950. By Sergey Avseyev

Fix binary increment/decrement commands with prefix

951. By Sergey Avseyev

Implement TOUCH command

Unmerged revisions

951. By Sergey Avseyev

Implement TOUCH command

950. By Sergey Avseyev

Fix binary increment/decrement commands with prefix

949. By Brian Aker

Merge in conditional fix

948. By Brian Aker

Merge of trunk.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2011-06-23 07:17:28 +0000
4@@ -0,0 +1,100 @@
5+*.BASE
6+*.OTHER
7+*.exe
8+*.lo
9+*.output
10+*.pop
11+*.rpm
12+*/*.l[oa]
13+*/*/*.l[oa]
14+*/*/.deps
15+*/*/.dirstamp
16+*/*/.libs
17+*/.deps
18+*/.dirstamp
19+*/.libs
20+*/Makefile
21+*/Makefile.in
22+*TAGS
23+.deps
24+INSTALL
25+Makefile
26+Makefile.in
27+TAGS
28+aclocal.m4
29+autom4te.cache
30+clients/memaslap
31+clients/memcapable
32+clients/memcat
33+clients/memcp
34+clients/memdump
35+clients/memerror
36+clients/memflush
37+clients/memparse
38+clients/memrm
39+clients/memslap
40+clients/memstat
41+config.h
42+config.h.in
43+config.log
44+config.status
45+config/compile
46+config/config.guess
47+config/config.sub
48+config/depcomp
49+config/install-sh
50+config/ltmain.sh
51+config/missing
52+config/pandora_vc_revinfo
53+config/plugin.ac
54+config/top.h
55+configure
56+docs/*.[13]
57+docs/*.html
58+docs/conf.py
59+docs/conf.py
60+docs/doctest/
61+docs/doctrees/
62+docs/html/
63+docs/linkcheck/
64+example/memcached_light
65+libhashkit/configure.h
66+libmemcached-*.tar.gz
67+libmemcached-0.30-1.src.rpm
68+libmemcached-0.30-1.x86_64.rpm
69+libmemcached-0.31-1.src.rpm
70+libmemcached-0.31-1.x86_64.rpm
71+libmemcached-0.37-1.src.rpm
72+libmemcached-0.37-1.x86_64.rpm
73+libmemcached-?.??/
74+libmemcached/configure.h
75+libmemcached/dtrace_probes.h
76+libmemcached/generated_probes.h
77+libmemcached/memcached_configure.h
78+libtool
79+libtool.m4
80+ltoptions.m4
81+ltsugar.m4
82+ltversion.m4
83+lt~obsolete.m4
84+patch
85+patch2
86+stamp-h1
87+support/Makefile
88+support/Makefile.in
89+support/libmemcached-fc.spec
90+support/libmemcached.pc
91+support/libmemcached.spec
92+tags
93+tests/atomsmasher
94+tests/hash_plus
95+tests/hashplus
96+tests/memplus
97+tests/output.cmp
98+tests/startservers
99+tests/testapp
100+tests/testhashkit
101+tests/testplus
102+tests/testudp
103+tests/var/
104+unittests/unittests
105
106=== renamed file '.bzrignore' => '.bzrignore.moved'
107=== added file '.hgignore'
108--- .hgignore 1970-01-01 00:00:00 +0000
109+++ .hgignore 2011-06-23 07:17:28 +0000
110@@ -0,0 +1,87 @@
111+# Exact paths to config junk
112+^INSTALL$
113+^aclocal.m4$
114+^configure$
115+^config/(config.guess|config.sub|depcomp|install-sh|ltmain.sh|missing)$
116+^config.(log|status)$
117+^libtool$
118+^autom4te.cache$
119+^libmemcached/(libmemcached_config.h(.in)?|stamp-h1)$
120+^libmemcached/libmemcached_config.h.in$
121+^stamp-h1$
122+^lib/libmemcachedPlus.la$
123+^tests/testplus$
124+
125+# Don't bother with TAGS files
126+TAGS
127+clients/TAGS
128+clients/memdump
129+libmemcached/TAGS
130+libmemcachedutil/TAGS
131+tests/TAGS
132+
133+
134+
135+# Build artifacts
136+^libmemcached/libmemcached.la$
137+^libmemcachedutil/libmemcachedutil.la$
138+^clients/mem(cat|cp|flush|rm|slap|stat|error)$
139+^tests/testapp$
140+.(deps|libs)/*$
141+.cmp$
142+autom4te.cache/*$
143+.(gz|cmp|tar|rpm|srpm)$
144+support/libmemcached.pc$
145+support/libmemcached.spec$
146+support/libmemcached-fc.spec$
147+docs/pod2htmd.tmp
148+docs/pod2htmi.tmp
149+libmemcached/memcachedplus.loT
150+tests/atomsmasher
151+tests/startservers
152+tests/stopservers
153+tests/udptest
154+^libmemcached/dtrace_probes.h$
155+^tests/core$
156+
157+Makefile(.in)?$
158+.(deps|libs)$
159+\.l?o$
160+
161+# Generated man files
162+\.1$
163+\.3$
164+
165+# Merged files
166+\.orig$
167+
168+#HTML files
169+docs/libmemcached/default.css
170+docs/libmemcached/memcached.html
171+docs/libmemcached/memcached_auto.html
172+docs/libmemcached/memcached_behavior.html
173+docs/libmemcached/memcached_callback.html
174+docs/libmemcached/memcached_create.html
175+docs/libmemcached/memcached_delete.html
176+docs/libmemcached/memcached_examples.html
177+docs/libmemcached/memcached_flush.html
178+docs/libmemcached/memcached_get.html
179+docs/libmemcached/memcached_quit.html
180+docs/libmemcached/memcached_result_st.html
181+docs/libmemcached/memcached_server_st.html
182+docs/libmemcached/memcached_servers.html
183+docs/libmemcached/memcached_set.html
184+docs/libmemcached/memcached_stats.html
185+docs/libmemcached/memcached_strerror.html
186+docs/libmemcached/memcached_verbosity.html
187+docs/libmemcached/memcached_version.html
188+docs/libmemcached/memcat.html
189+docs/libmemcached/memcp.html
190+docs/libmemcached/memerror.html
191+docs/libmemcached/memflush.html
192+docs/libmemcached/memrm.html
193+docs/libmemcached/memslap.html
194+docs/libmemcached/memstat.html
195+
196+# Backup files created by emacs
197+.*~$
198
199=== renamed file '.hgignore' => '.hgignore.moved'
200=== added file '.quickly'
201--- .quickly 1970-01-01 00:00:00 +0000
202+++ .quickly 2011-06-23 07:17:28 +0000
203@@ -0,0 +1,5 @@
204+project = libmemcached
205+version = 0.4.2
206+template = pandora-build
207+project-type = library
208+pandora-version = 0.175
209
210=== renamed file '.quickly' => '.quickly.moved'
211=== added file 'AUTHORS'
212--- AUTHORS 1970-01-01 00:00:00 +0000
213+++ AUTHORS 2011-06-23 07:17:28 +0000
214@@ -0,0 +1,11 @@
215+Brian Aker, brian@tangent.org -- Client Library, Tools
216+Mark Atwood, -- Tools, Docs
217+Patrick Galbraith, -- C++ Interface
218+Padraig O'Sullivan, -- C++ Interface (current one)
219+Tim Bunce, -- Docs
220+Trond Norbye, trond.norbye@gmail.com -- Binary protocol, Misc
221+Yin Chen, -- Ketama Work
222+Toru Maesaka, dev@torum.net -- Stats analysis
223+Eric Lambert, -- UDP work
224+Monty Taylor, -- Build Releated (Pandora)
225+Mingqiang Zhuang, Schooner Information Technology, Inc. -- Rewrite of memslap
226
227=== renamed file 'AUTHORS' => 'AUTHORS.moved'
228=== added file 'COPYING'
229--- COPYING 1970-01-01 00:00:00 +0000
230+++ COPYING 2011-06-23 07:17:28 +0000
231@@ -0,0 +1,33 @@
232+Software License Agreement (BSD License)
233+
234+Copyright (c) 2011, Data Differential (http://datadifferential.com/)
235+Copyright (c) 2007-2010, TangentOrg (Brian Aker)
236+All rights reserved.
237+
238+Redistribution and use in source and binary forms, with or without
239+modification, are permitted provided that the following conditions are
240+met:
241+
242+ * Redistributions of source code must retain the above copyright
243+notice, this list of conditions and the following disclaimer.
244+
245+ * Redistributions in binary form must reproduce the above
246+copyright notice, this list of conditions and the following disclaimer
247+in the documentation and/or other materials provided with the
248+distribution.
249+
250+ * Neither the name of TangentOrg nor the names of its
251+contributors may be used to endorse or promote products derived from
252+this software without specific prior written permission.
253+
254+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
255+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
256+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
257+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
258+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
259+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
260+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
261+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
263+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265
266=== renamed file 'COPYING' => 'COPYING.moved'
267=== added file 'ChangeLog'
268--- ChangeLog 1970-01-01 00:00:00 +0000
269+++ ChangeLog 2011-06-23 07:17:28 +0000
270@@ -0,0 +1,393 @@
271+0.50
272+
273+ * Updates to C++ interface
274+ * Custom free allocators need to now check for value before calling free.
275+
276+ * memcached_fetch_result() now uses the internal result when available (about 25 to 50% faster).
277+
278+0.49 Thu Apr 14 08:43:37 PDT 2011
279+ * Fix calls to auto methods so that if value is not passed in nothing bad happens.
280+ * New parser calls for generating memcached_st objects.
281+ * New error system.
282+ * New flow control for messages means faster get/set calls.
283+ * Added new documentation system.
284+ * A behavior change has been now made that if you specify a weight for any
285+ server, we enable the weight flag and do weight balancing.
286+ * 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.
287+ * Added MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS to simplify the setting of AUTO REJECT for servers.
288+
289+0.48 Tue Mar 15 23:05:18 PDT 2011
290+ * Fix memory leak in server parse.
291+ * Move test framework out to be its own library (easier to work with Gearman).
292+
293+
294+0.47 Wed Feb 23 18:46:48 PST 2011
295+ * Additional fixes for OpenBSD.
296+ * Bug fix 677609, 456080.
297+ * SIGPIPE fix for Linux send().
298+ * memcapable can now test ascii or binary based on flags.
299+ * Additional build fixes for SASL.
300+
301+
302+0.46 Mon Feb 14 10:28:01 PST 2011
303+ * Fixes a number of corner case bugs.
304+ * Fixes related to OpenBSD.
305+ * Better testing for protocol version.
306+ * Removes special case infinite wait on blocking setup.
307+
308+0.45 Tue Feb 8 16:02:06 PST 2011
309+ * Add support for systemtap
310+
311+0.44 Wed Sep 22 21:57:57 PDT 2010
312+ * Windows bug fixes.
313+ * Hudson port support in test harness.
314+ * Improved portability of test hanrness.
315+ * SASL fixes.
316+
317+0.43 Wed Jul 28 16:29:47 PDT 2010
318+ * Added --args to memstat so that a greater range of values can be returned.
319+ * Prelimanary support for Windows.
320+ * memcached_stat_execute() merged.
321+
322+0.42 Tue Jul 6 12:29:50 PDT 2010
323+ * Mistake in libtool caused issue with library version
324+
325+0.41 Wed Jun 30 13:15:19 PDT 2010
326+ * Added --file for memcat.
327+ * Added limemcached_ping() to libmemcached_util
328+ * Bugfix for some cases where connect would have issues with timeout.
329+ * Wrong value for errno given as error on an IO failure inside of poll.
330+ * Bug fix for issue where multiple interfaces with bad DNS were not being caught.
331+
332+0.40 Thu Apr 22 19:01:25 PDT 2010
333+ * Placed retry logic in for busted resolvers
334+ * Add an ignore for SIGPIPE to solve OSX issues.
335+ * A couple of fixed for memcached_light server.
336+ * Updated to debug mode to track io_wait
337+
338+0.39 Tue Apr 6 12:35:13 PDT 2010
339+ * Add support for prefix keys to binary protocol.
340+ * Remove the undocumented call memcached_server_remove().
341+ * The undocumented call memcached_server_by_key() now returns const.
342+ * memcached_server_error_reset() has been deprecated.
343+ * memcached_server_list() has been deprecated. Use memcached_server_cursor() to walk the servers found in a memcached_st() structure.
344+ * memcached_verbosity() can now be run concurrently with other operations.
345+ * SASL support.
346+ * Fixes memory leak found in EJECT HOSTS.
347+
348+0.38 Wed Feb 10 09:40:33 PST 2010
349+ * C++ interface for libhashkit.
350+ * Modified memcached_set_memory_allocators() so that it requires a context pointer.
351+ * memcached_clone() now runs 5 times faster.
352+ * Functions used for callbacks are now given const memcached_st.
353+ * Added MEMCACHED_BEHAVIOR_CORK.
354+ * memslap now creates a configuration file at ~/.memslap.cnf
355+ * memcached_purge() now calls any callbacks registered during get execution.
356+ * Many fixes to memslap.
357+ * Updates for memcapable.
358+ * Compile fixes for OpenBSD.
359+ * Fix for possible recursive decent on IO failure.
360+
361+0.37 Mon Jan 11 16:29:57 PST 2010
362+ * Fixed build for libhashkit.
363+ * Fixed install path regression.
364+ * Modified RPM to strict check install.
365+ * Added documentation for memcached_server_cursor();
366+ * Added memcached_servers_reset().
367+ * Modified memcached_st to remove dead cursor_server member.
368+
369+0.36 Wed Jan 6 18:23:50 PST 2010
370+ * Merged in new memslap utility.
371+ * All of constants.h has been updated to match style (all old identifiers continue to work).
372+ * Added first pass for libhashkit.
373+ * Updated test Framework/extended tests.
374+ * Random read support during replication added.
375+ * Modified use_sort so that the option can be applied to any distribution type.
376+ * We removed the MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE added in 0.35. Instead use memcached_behavior_set_distribution().
377+
378+0.35 Mon Nov 9 11:18:33 PST 2009
379+ * Added support for by_key operations for inc/dec methods.
380+ * Added mget test to memslap.
381+ * Support for compatible ketama for SpyMemcached
382+ * Update C++ interface.
383+ * Fix for memcp
384+
385+0.34 Tue Oct 13 08:39:51 PDT 2009
386+ * Added support for setting behavior flags on a connection pool.
387+ * Don't increment server_failure_counter on normal disconnects.
388+ * Added prototype for a callback based protocol parser (server side) with examples so that you could let your own application speak the memcached protocol
389+ * Updated memcapable to test ASCII protocol.
390+ * Changed behavior so that server can be removed at first sign of failure.
391+ * Added memcached_server_get_last_disconnect() call
392+
393+0.33 Wed Sep 23 10:11:58 PDT 2009
394+ * Added memcapable to test servers for binary compatibility.
395+ * Updated C++ interface. Added basic support for C++ exceptions. Added multiple constructors the memcached client object. The C++ interface now takes parameters which are C++ types (such as std::string).
396+ * Several bug fixes for binary protocol support.
397+ * Fixed crashing issue with dumping from memcachd server (server internals were changed without documenting change).
398+
399+0.32 Tue Sep 15 15:49:09 PDT 2009
400+ * Change of behavior where linger is only modified for no-block and then it is set to zero.
401+ * Added Twitter's memcached_server_error() functions.
402+ * Fix for OSX compiles in development builds.
403+ * Updated C++ interface.
404+ * Updated memcached_mget and memcached_mget_by_key to take a size_t as a parameter instead of an unsigned int for number_of_keys.
405+
406+0.31 Fri Jul 10 09:02:50 PDT 2009
407+ * Added support or HA via replication.
408+ * malloc() removed for server key usage.
409+ * Update build system.
410+ * Added support for memcached_set_memory_allocators().
411+ * Fixed bug in configure.ac for have_htoll.
412+
413+0.30 Sun May 31 17:31:52 PDT 2009
414+ * Added memcachd_dump command (and framework for memdump tool).
415+ * Realigned all structures to remove padding (and line up important bits for 64bit caches.
416+ * Remove some of sprintf() in storage calls().
417+ * Removed printf() in stat call for unknown stat member.
418+ * memcached_generate_hash() function added.
419+ * Added tests to make sure all hash functions are stable.
420+
421+0.29 Tue May 19 08:26:48 PDT 2009
422+ * Fixed malloc usage to calloc for spots where we need zero filled memory.
423+ * All code warnings now treated as errors.
424+ * Fixes for debian packaging.
425+ * Added new pooling mechanism.
426+ * MEMCACHED_BEHAVIOR_NO_BLOCK no longer also sets MEMCACHED_BEHAVIOR_BUFFER_REQUESTS.
427+ * Updated generic rpm.
428+
429+0.28 Tue Apr 14 18:56:28 PDT 2009
430+ * Fixed bug in init sructure (reapplied)
431+ * Fixed bug in get/set by key (nikkhils@gmail.com)
432+
433+0.27 Sun Mar 29 22:33:01 PDT 2009
434+ * Added new UDP fire-forget mode.
435+ * Reworked performance for mget() to better make use of async protocol
436+ * Cleaned up execution of fetch (just one set of code now)
437+ * Fixed Jenkin's for big endian hosts.
438+ * Updates for memstat to determine network latency.
439+ * Updates for binary protocol.
440+ * Many updates to documentation.
441+
442+0.26 Thu Jan 29 13:05:50 PST 2009
443+ * Fix for decrement on hash key
444+ * Fixed assert that was catching bad memset() call in host_reset()
445+ * Fix purge issue for blocked IO which has been stacked.
446+
447+0.25 Fri Nov 28 09:59:35 PST 2008
448+ * Jenkins HASH added.
449+ * Update of Murmur hash code
450+ * Support explicit weights (Robey Pointer, Evan Weaver)
451+ * Bugfix for ketama continuum (Robey Pointer)
452+ * New behavior MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY (Robey Pointer)
453+ * Don't ever call stats for weighting servers, because it is unstable.
454+
455+0.24 Tue Sep 16 02:59:03 PDT 2008 (never released)
456+ * Cleanup compile warnings.
457+ * Fix issues in partitioning by keys.
458+ * Fixed "fail case" to make sure when calling memcached_clone() no memcached_st is over written.
459+ * New memcached_server_by_key() method for finding a server from a key.
460+ * memcached_server_free() was added for freeing server structures.
461+
462+
463+0.23 Sun Sep 7 08:13:59 PDT 2008
464+ * Added strings.h header for Solaris 9
465+ * Solaris 64bit fix.
466+ * Support for weighted Ketama from Yin Chen.
467+ * Fix for Chinese
468+ * Fix for 0 length key to trigger bad key.
469+ * Added behaviors MEMCACHED_BEHAVIOR_SND_TIMEOUT, MEMCACHED_BEHAVIOR_RCV_TIMEOUT
470+ * Support for Binary Protocol added
471+
472+0.22 Mon Jul 14 09:24:11 PDT 2008
473+ * Fix where master key was no being checked for "bad key"
474+ * Fixed bugs in stats output (thread output was wrong)
475+ * Clarified MEMCACHED_BAD_KEY_PROVIDED is return for bad prefix key.
476+ * Found a bug in Flags return (Jacek Ostrowski)
477+ * Fixed issue with compiling on Visual Studio
478+
479+0.21 Fri May 23 18:34:09 PDT 2008
480+ * Change of char * to const char * for all key based functions.
481+ * New MEMCACHED_CALLBACK_PREFIX_KEY added. You can now create domains for values.
482+ * Fixed bug introducd in last version on memcp
483+ * Fix for death of file io to call shutdown()
484+
485+0.20 Mon May 5 08:34:26 PDT 2008
486+ * New consistent distribution tests.
487+ * Found a memory leak when a server constantly fails.
488+ * Fix in watchpoint macro
489+ * Changed default timeout to 1 second for poll timeouts
490+ * Wheel uses less memory/dynamic allocation for size (no longer limited to 512 hosts by default.
491+ * memslap memory leak fix
492+ * Added Ketama distribution
493+ * Fix assert.h compile problem on CentOS
494+
495+0.19 Wed Apr 9 09:30:53 PDT 2008
496+ * Documentation fix in libmemcached.
497+ * Fixed bug where sort was always occuring on hosts
498+ * Logic fix in branch prediction (thanks Jay!)
499+ * Read through cached support.
500+ * Fixed for cas by key operation.
501+ * Fix for memcached_server_st list structures to have correct count.
502+ * Added callback MEMCACHED_CALLBACK_DELETE_TRIGGER
503+ * Removed function call in favor of macro (aka cut out some instructions)
504+
505+
506+0.18 Sun Mar 16 21:57:55 PDT 2008
507+ * Fix plus tests for non-zero value objects and flags.
508+ * MEMCACHED_HASH_MURMUR added for murmur algorithm provided.
509+ * MEMCACHED_BEHAVIOR_RETRY_TIMEOUT added to keep connecting from looping on timeout.
510+ * gcc branch prediction optimizations
511+ * Refactored entire tree to make include files cleaner
512+ * Fixed leaked socket.
513+
514+0.17 Wed Feb 27 03:33:29 PST 2008
515+ * MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT added for connect timeout in non-block mode.
516+ * Incompatible change in memcached_behavior_set() api. We now use a uint64_t, instead of a pointer.
517+ * Fix for storage of values for zero.
518+ * memcached_server_cursor() function added to API for cycling through servers.
519+
520+0.16 Mon Feb 18 00:30:25 PST 2008
521+ * Work on the UDP protocol
522+ * Added get_by_key, set_by_key tests for C++ API
523+ * Fix for limit_maxbytes to be 64bit in stats
524+ * Added Atom Smasher test (scale baby, scale!)
525+ * Servers are now sorted, meaning that servers are now ordered so that clients with the same lists, will have same distribution. (Idea from Ross McFarland). MEMCACHED_BEHAVIOR_SORT_HOSTS was added to enable this support.
526+ * Added MEMCACHED_BAD_KEY_PROVIDED error for auto, set, and get operations. MEMCACHED_BEHAVIOR_VERIFY_KEY was added to enable this feature.
527+ * More error messages on command line tools.
528+ * Fixed bugs in memcached_cas() operator.
529+ * Fix to loop through interfaces
530+
531+0.15 Tue Jan 29 14:55:44 PST 2008
532+ * More work on the C++ API.
533+ * Bug fixes around block corner cases.
534+ * Slight performance increase in both read() and write().
535+
536+0.14 Tue Jan 22 06:21:49 PST 2008
537+ * For for bug found by Evan Weaver where increment() was not returning propper error of value was not found.
538+ * Fix for bad null pointer on flag by Toru Maesaka.
539+ * Refactor of all IO to just pass in the active server
540+ * Problem configuring (PKG_CHECK_MODULES) fixed by removal of "rpath" in support/libmemcached.pc.in (Thanks to Ross McFarland).
541+ * Added memcached_callback_get()/set()
542+ * First prototype of C++ interface
543+ * Updated docs for uint16_t changes in previous release
544+
545+0.13 Sun Jan 13 06:51:50 PST 2008
546+ * MEMCACHED_BEHAVIOR_USER_DATA added to store user pointer.
547+ * Fix for failure to connect to invalidate socket.
548+ * Patch from Marc Rossi to add --hash option for memcp, memrm, and memcat.
549+ * Kevin's patch for fixing EOF issues during a read.
550+ * Toru Maesaka patch for stats mismatch
551+ * Fix for when CRC return 0
552+ * Fixed uint16_t issues around flags. Turns out the documentation on the protocol was wrong.
553+ * Lingering socket fixes for FreeBSD.
554+ * Patches from Kevin Dalley for FreeBSD 4.0
555+ * Added multi delete functions.
556+ * All get key returns have C style null termination
557+ * If memcached_server_list_append is passed NULLs instead of pointers it returns NULL.
558+ * Added memcached_fetch_execute() method
559+ * Found a bug where memcached_fetch() was not null terminating the result value.
560+ * memcached_behavior() now has the ability to set "buffering" so that data is not automatically flushed.
561+ * Behavior change, buffered commands now return MEMCACHED_BUFFERED
562+
563+0.12 Tue Dec 11 15:20:55 PST 2007
564+ * Updates for consistent hashing
565+ * IPV6 support
566+ * Static allocation for hostname (performance)
567+ * Fixed bug where in non-block mode all data might not have been sent on close().
568+ * Refactor of memcached_get() to use common code.
569+ * Change in value fetch, MEMCACHED_END is now returned when keys are no longer in the pipe.
570+ * Fixed bug where key could be out of range of characters
571+ * Added _by_key() methods to allow partitioning of values to particular servers.
572+ * MEMCACHED_DEFAILT_TIMEOUT is now set to a non -1 value.
573+ * Performance improvements in get operations.
574+
575+0.11 Mon Nov 26 01:05:52 PST 2007
576+ * Added option to memcache_behavior_set() so that poll() can be timed out.
577+ * Fixed memory leak in case of using memcached_fetch_result() where no value was returned.
578+ * Bug fixed in memcached_connect() which would cause servers that did not need to be enabled to be enabled (performance issue).
579+ * Rewrote bounds checking code for get calls.
580+ * "make test" now starts its own memcached servers.
581+ * Added Hseih hash (MEMCACHED_HASH_HSIEH), which is showing about 7% performance over standard hash.
582+
583+0.10 Tue Nov 20 23:22:31 PST 2007
584+ * Added append binary test.
585+ * Added MEMCACHED_BEHAVIOR_CACHE_LOOKUPS behavior so that you can save on multiple DNS lookups.
586+ * Added CAS support, though this is optional and must be enabled during runtime.
587+ * Added the utility memerror to create human readable error strings from memcached errors (aka convert ints to strings)
588+ * Fixed type in MEMCACHED_HOST_LOOKUP_FAILURE
589+ * Fixed bug where hostname might not be null terminated
590+ * Moved to using gethostbyname_r() on Linux to solve thread safety issue
591+ * Added -rpath support for pkg-config
592+ * Documentation fix for hash setting using memcached_behavior_set()
593+
594+0.9 Thu Nov 15 07:44:00 PST 2007
595+ * fix for when no servers are definied.
596+ * different buffers are now kept for different connections to speed up async efforts
597+ * Modified increment/decrement functions to return uint64_t values
598+ * Fixed bug in cases where zero length keys were provided
599+ * Thread cleanup issue in memslap
600+ * No hostname lookup on reconnect
601+ * Fix for flag settings (was doing hex by accident!)
602+ * Support for 1.2.4 server additions "prepend" and "append" added.
603+ * Added memcached_version()... not sure if I will make this public or not.
604+
605+0.8 Mon Nov 5 10:40:41 PST 2007
606+ * Adding support for CRC hash method
607+ * Adding support for UNIX sockets
608+ * Added additional HASHing methods of FNV1_64,FNV1A_64, FNV1_32, FNV1A_32
609+ * Added pkgconfig support (PKG_CHECK_MODULES)
610+ * Fixed conflict with defined type in MySQL
611+ * Added memcached_result_st structure and functions to manipulate it.
612+
613+0.7 Tue Oct 30 09:24:05 PDT 2007
614+ * Poved to poll() from select()
615+ * Fixes in internal string class for allocation of large numbers of strings.
616+ * memcached_mget() function now sends keys as it parses them instead of building strings as it goes.
617+ * Propper flush now for making sure we get all IO sent even when in non-block mode.
618+ * Added --enable-debug rule for configure
619+ * All asserts() removed (hey this is going into production!)
620+
621+
622+0.6 Wed Oct 17 08:41:35 PDT 2007
623+ * get value returns are now null terminated (request by Cal Heldenbrand)
624+ * Fixed connections for more hosts then two.
625+ * Rewrite of the read/write IO systems to handle different sorts of host failures.
626+ * Added man pages for all functions and tools
627+ * Raised buffer size for readinng/writing to 16K
628+ * You can now optionally set the socket size for recv/send via memached_behavior_set/get.
629+
630+0.5 Tue Oct 9 00:22:25 PDT 2007
631+ * Ruby maintainer mentioned TCP_NODELAY patch he had added. Added this to C
632+ library as well. (Eric Hodel drbrain@segment7.net)
633+ * Added support script for set_benchmark
634+ * Updated memslap to allow testing of TCP_NODELAY
635+ * Updated memslap to support --flush (aka dump memcache servers before testing)
636+ * Fixed bug in multiple hosts not being activated
637+ * Added environmental variable MEMCACHED_SERVERS which can be used to set the servers list.
638+ * fixed memcached_stat method (and now memstat works)
639+ * server connect now happens on demand.
640+ * Help for all command line applications
641+
642+0.4 Wed Oct 3 10:28:50 PDT 2007
643+ * Added buffered IO to write calls for keys
644+ * Added buffered IO for reads
645+ * memstat was broken (bad if/else on connect)
646+ * New non-blocking IO (not default yet). Mucho faster
647+ * Refactor of test system.
648+ * memslap crash solved
649+
650+0.3 Mon Oct 1 06:37:52 PDT 2007
651+ * Jeff Fisher <guppy@techmonkeys.org> provided a spec file
652+ * Added "make rpm" around dist file
653+ * Added support for Solaris
654+ * Added support for DTrace
655+ * Fixed read to be recv and write to be send
656+ * Bug fix where memstat would core if no server was found
657+ * Added memslap tool (load generator)
658+ * Numerous bug fixes in library
659+ * Added calls to library for creating host lists (see text cases to understand how to use this).
660+
661+0.2 Thu Sep 27 03:46:57 PDT 2007
662+ * First public version
663+
664
665=== renamed file 'ChangeLog' => 'ChangeLog.moved'
666=== added file 'Makefile.am'
667--- Makefile.am 1970-01-01 00:00:00 +0000
668+++ Makefile.am 2011-06-23 07:17:28 +0000
669@@ -0,0 +1,111 @@
670+ACLOCAL_AMFLAGS = -I m4
671+
672+# includes append to these:
673+SUFFIXES =
674+PHONY =
675+TESTS =
676+CLEANFILES =
677+DISTCLEANFILES =
678+bin_PROGRAMS =
679+noinst_HEADERS =
680+lib_LTLIBRARIES =
681+man_MANS =
682+noinst_LTLIBRARIES =
683+noinst_PROGRAMS =
684+include_HEADERS =
685+nobase_include_HEADERS =
686+check_PROGRAMS =
687+EXTRA_HEADERS =
688+BUILT_SOURCES=
689+EXTRA_DIST= \
690+ ${srcdir}/m4/pandora_*.m4 \
691+ .quickly \
692+ README.FIRST \
693+ README.win32 \
694+ config/autorun.sh \
695+ config/pandora-plugin \
696+ config/uncrustify.cfg \
697+ m4/ac_cxx_header_stdcxx_98.m4 \
698+ m4/acx_pthread.m4 \
699+ m4/gettext.m4 \
700+ m4/iconv.m4 \
701+ m4/pkg.m4 \
702+ m4/po.m4 \
703+ m4/progtest.m4
704+
705+include libtest/include.am
706+include libmemcached/include.am
707+include libmemcached/protocol/include.am
708+include libmemcached/util/include.am
709+include clients/include.am
710+include libhashkit/include.am
711+include tests/include.am
712+include example/include.am
713+include support/include.am
714+include poll/include.am
715+include win32/include.am
716+include docs/include.am
717+
718+docs: html man
719+
720+TESTS += ${check_PROGRAMS}
721+
722+EXTRA_DIST+= ${man_MANS}
723+
724+fedora:
725+ @rm -f ~/rpmbuild/RPMS/x86_64/libmemcached-$(VERSION)*.rpm
726+ @rm -f ~/rpmbuild/SRPMS/libmemcached-$(VERSION)*.rpm
727+ @cp libmemcached-$(VERSION).tar.gz ~/rpmbuild/SOURCES/
728+ @rpmbuild -ba support/libmemcached.spec
729+ @cp ~/rpmbuild/RPMS/x86_64/libmemcached-$(VERSION)*.rpm .
730+ @cp ~/rpmbuild/SRPMS/libmemcached-$(VERSION)*.rpm .
731+
732+generic:
733+ @rm -f ~/rpmbuild/RPMS/x86_64/libmemcached-$(VERSION)*.rpm
734+ @rm -f ~/rpmbuild/SRPMS/libmemcached-$(VERSION)*.rpm
735+ @cp libmemcached-$(VERSION).tar.gz ~/rpmbuild/SOURCES/
736+ @rpmbuild -ba support/libmemcached.spec
737+ @cp ~/rpmbuild/RPMS/x86_64/libmemcached-$(VERSION)*.rpm .
738+ @cp ~/rpmbuild/RPMS/x86_64/libmemcached-devel-$(VERSION)*.rpm .
739+ @cp ~/rpmbuild/RPMS/x86_64/libmemcached-debuginfo-$(VERSION)*.rpm .
740+ @cp ~/rpmbuild/SRPMS/libmemcached-$(VERSION)*.rpm .
741+
742+rpm: man distcheck generic
743+
744+release: rpm
745+ @rpm --addsign libmemcached-$(VERSION)*.rpm .
746+ @rpm --checksig libmemcached-$(VERSION)*.rpm .
747+ @rpm --addsign libmemcached-devel-$(VERSION)*.rpm .
748+ @rpm --checksig libmemcached-devel-$(VERSION)*.rpm .
749+ @rpm --addsign libmemcached-debuginfo-$(VERSION)*.rpm .
750+ @rpm --checksig libmemcached-debuginfo-$(VERSION)*.rpm .
751+
752+merge-clean:
753+ @find ./ | $(GREP) \.gcda | xargs rm -f
754+ @find ./ | $(GREP) \.gcno | xargs rm -f
755+ @find ./ | $(GREP) \.gz | xargs rm -f
756+ @find ./ | $(GREP) \.orig | xargs rm -f
757+ @find ./ | $(GREP) \.rej | xargs rm -f
758+ @find ./ | $(GREP) \.rpm | xargs rm -f
759+ @find ./ | $(GREP) \~$$ | xargs rm -f
760+ @echo "Files that need to be either removed or checked in:"
761+ @bzr unknowns
762+
763+clean-local:
764+ -rm -rf docs/_build docs/doctrees
765+
766+lcov: lcov-clean check
767+ @echo
768+ @echo " ------------------------------------------------------"
769+ @echo "Make sure ./configure was run with '--enable-coverage'"
770+ @echo "------------------------------------------------------"
771+ @echo
772+ @cd libmemcached && lcov --capture --directory . --base-directory .. --output-file lcov.out
773+ @genhtml -o lcov --function-coverage -t libmemcached libmemcached/lcov.out
774+
775+lcov-clean: clean
776+ @rm -rf lcov */lcov.out
777+ @find . -name '*.gcno' | xargs rm -f
778+ @find . -name '*.gcda' | xargs rm -f
779+
780+DISTCLEANFILES+= config/top.h
781
782=== renamed file 'Makefile.am' => 'Makefile.am.moved'
783=== added file 'NEWS'
784--- NEWS 1970-01-01 00:00:00 +0000
785+++ NEWS 2011-06-23 07:17:28 +0000
786@@ -0,0 +1,1 @@
787+See Changelog
788
789=== renamed file 'NEWS' => 'NEWS.moved'
790=== added file 'README'
791--- README 1970-01-01 00:00:00 +0000
792+++ README 2011-06-23 07:17:28 +0000
793@@ -0,0 +1,43 @@
794+Hi!
795+
796+So what is this? It is a library in C for connecting to memcached servers
797+(http://danga.com/memcached/). It is also a collection of utilities designed
798+to work with memcached.
799+
800+memcat - Copy the value of a key to standard output
801+memflush - Flush the contents of your servers.
802+memrm - Remove a key(s) from the server.
803+memstat - Dump the stats of your servers to standard output
804+memslap - Load generation utility (benchmark!)
805+
806+The library is in production in many locations (upwards to 1000+ nodes).
807+
808+The project has information here: http://libmemcached.org/
809+
810+Documentation can be found here: http://docs.libmemcached.org/
811+
812+Want to contribute? If you write more then three good patches, then I will
813+just ask you to commit directly to the tree. I am happy to have additional
814+people work on this project. Please checkout README.FIRST.
815+
816+You will need a C99 compiler in order to compile this library. Currently we
817+actively support Linux, MacOSX, FreeBSD, and Solaris. A Windows port is
818+currently not supported, but one is listed on the homepage that is supported
819+by someone in the community.
820+
821+If you are looking for answers to your questions please check out the
822+mailing list at:
823+http://lists.libmemcached.org/
824+
825+Subscription information for the libmemcached mailing list can be found there.
826+
827+Please report bugs here:
828+https://bugs.launchpad.net/libmemcached/
829+
830+You can purchase support from:
831+http://datadifferential.com/
832+
833+
834+Cheers,
835+ -Brian Aker
836+ Seattle, WA.
837
838=== added file 'README.FIRST'
839--- README.FIRST 1970-01-01 00:00:00 +0000
840+++ README.FIRST 2011-06-23 07:17:28 +0000
841@@ -0,0 +1,31 @@
842+Hi!
843+
844+If you are getting this code from http://launchpad.net/libmemcached then
845+continue reading. Otherwise these directions are not for you (well maybe...).
846+
847+To obtain code from http://bazaar.launchpad.net/libmemcached you will need to
848+issue the following command:
849+
850+bzr branch lp:libmemcached
851+
852+Once the tree is cloned you will need to build the "configure" script. You
853+can do this by running the script:
854+
855+./config/autorun.sh
856+
857+It will set up all of the files you need to build libmemcached. At that
858+point it is just the typical "./configure; make; make test; make install"
859+
860+For a tarball release do a "make dist" and for an RPM type "make rpm".
861+
862+For patches, we prefer you push a branch to launchpad and then submit that
863+branch to be merged. For more information, see:
864+
865+https://help.launchpad.net/Code/UploadingABranch
866+https://help.launchpad.net/Code/Review
867+
868+Thanks and keep hacking!
869+
870+Cheers,
871+ -Brian
872+ Seattle, WA.
873
874=== renamed file 'README.FIRST' => 'README.FIRST.moved'
875=== renamed file 'README' => 'README.moved'
876=== added file 'README.win32'
877--- README.win32 1970-01-01 00:00:00 +0000
878+++ README.win32 2011-06-23 07:17:28 +0000
879@@ -0,0 +1,25 @@
880+Hi,
881+
882+So you want to know how to build libmemcached on Windows? In order to
883+have a single build environment you need to install mingw to get a
884+"unix environment" to run the configure script.
885+
886+An easy way to get started is to install the msysgit fullinstall
887+package from: http://code.google.com/p/msysgit/downloads/list
888+
889+msysgit does not contain the "autotools" needed to generate a
890+configure script, so you need to generate that on another box (this
891+should not be a problem if you're trying to build from a tar archive).
892+
893+msysgit does not contain the tools to build the documentation, so you
894+need to add --without-docs to configure.
895+
896+I'm normally building libmemcached with:
897+
898+Ex:
899+$ ./configure --without-docs --with-memcached=../memcached/memcached.exe
900+$ make all install
901+
902+Happy hacking,
903+
904+Trond Norbye
905
906=== renamed file 'README.win32' => 'README.win32.moved'
907=== added file 'THANKS'
908--- THANKS 1970-01-01 00:00:00 +0000
909+++ THANKS 2011-06-23 07:17:28 +0000
910@@ -0,0 +1,14 @@
911+(This is not complete, please send email if I have missed someone.)
912+Eirik A. Nygaard - IO Patch
913+Cal Heldenbrand - Awesome feedback on performance
914+Dustin Sallings - Insight into protocol
915+Tobias Luetke - Performance Feedback
916+Andre Cruz - Help with getting the CRC Hash function to match other connectors
917+Brian Pontz - Hsieh hash
918+Tim Bunce - Perl Driver work and feedback on API
919+Kevin Dalley - Bug Fixes
920+Patrick Galbraith - work on C++ interface
921+Ross McFarland - Idea for sorting servers.
922+Marcelo Fernandez - TCP/IP timeout pieces
923+Yin Chen - Ketama support/weighted support
924+Monty Taylor - Debian Packages, Cleanup work for configure
925
926=== renamed file 'THANKS' => 'THANKS.moved'
927=== added file 'TODO'
928--- TODO 1970-01-01 00:00:00 +0000
929+++ TODO 2011-06-23 07:17:28 +0000
930@@ -0,0 +1,11 @@
931+- Write a shell application (?)
932+- Fix version in command line tools
933+- Write (more) test cases for all command line tools (!!!)
934+- Write some sort of "default" options bit for tools
935+- More examples using libraries
936+- Doxygen?
937+- implement more connection/hash algo
938+- implement compression
939+- Revisit get() code (look for performance enhancements)
940+- Add support for managing servers for clusters.
941+- Build embedded version
942
943=== renamed file 'TODO' => 'TODO.moved'
944=== added directory 'clients'
945=== renamed directory 'clients' => 'clients.moved'
946=== added file 'clients/client_options.h'
947--- clients/client_options.h 1970-01-01 00:00:00 +0000
948+++ clients/client_options.h 2011-06-23 07:17:28 +0000
949@@ -0,0 +1,45 @@
950+/* LibMemcached
951+ * Copyright (C) 2006-2009 Brian Aker
952+ * All rights reserved.
953+ *
954+ * Use and distribution licensed under the BSD license. See
955+ * the COPYING file in the parent directory for full text.
956+ *
957+ * Summary:
958+ *
959+ */
960+
961+#ifndef __CLIENT_OPTIONS_H__
962+#define __CLIENT_OPTIONS_H__
963+
964+typedef struct memcached_help_text_st memcached_help_text_st;
965+
966+typedef enum {
967+ OPT_SERVERS= 's',
968+ OPT_VERSION= 'V',
969+ OPT_HELP= 'h',
970+ OPT_VERBOSE= 'v',
971+ OPT_DEBUG= 'd',
972+ OPT_ANALYZE= 'a',
973+ OPT_FLAG= 257,
974+ OPT_EXPIRE,
975+ OPT_SET,
976+ OPT_REPLACE,
977+ OPT_ADD,
978+ OPT_SLAP_EXECUTE_NUMBER,
979+ OPT_SLAP_INITIAL_LOAD,
980+ OPT_SLAP_TEST,
981+ OPT_SLAP_CONCURRENCY,
982+ OPT_SLAP_NON_BLOCK,
983+ OPT_SLAP_TCP_NODELAY,
984+ OPT_FLUSH,
985+ OPT_HASH,
986+ OPT_BINARY,
987+ OPT_UDP,
988+ OPT_USERNAME,
989+ OPT_PASSWD,
990+ OPT_STAT_ARGS,
991+ OPT_FILE= 'f'
992+} memcached_options;
993+
994+#endif /* CLIENT_OPTIONS */
995
996=== added file 'clients/execute.cc'
997--- clients/execute.cc 1970-01-01 00:00:00 +0000
998+++ clients/execute.cc 2011-06-23 07:17:28 +0000
999@@ -0,0 +1,131 @@
1000+/* LibMemcached
1001+ * Copyright (C) 2006-2009 Brian Aker
1002+ * All rights reserved.
1003+ *
1004+ * Use and distribution licensed under the BSD license. See
1005+ * the COPYING file in the parent directory for full text.
1006+ *
1007+ * Summary:
1008+ *
1009+ */
1010+
1011+/*
1012+ Execute a memcached_set() a set of pairs.
1013+ Return the number of rows set.
1014+*/
1015+
1016+#include "config.h"
1017+#include "execute.h"
1018+
1019+unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
1020+{
1021+ memcached_return_t rc;
1022+ unsigned int x;
1023+ unsigned int pairs_sent;
1024+
1025+ for (x= 0, pairs_sent= 0; x < number_of; x++)
1026+ {
1027+ rc= memcached_set(memc, pairs[x].key, pairs[x].key_length,
1028+ pairs[x].value, pairs[x].value_length,
1029+ 0, 0);
1030+ if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED)
1031+ fprintf(stderr, "Failured on insert of %.*s\n",
1032+ (unsigned int)pairs[x].key_length, pairs[x].key);
1033+ else
1034+ pairs_sent++;
1035+ }
1036+
1037+ return pairs_sent;
1038+}
1039+
1040+/*
1041+ Execute a memcached_get() on a set of pairs.
1042+ Return the number of rows retrieved.
1043+*/
1044+unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
1045+{
1046+ memcached_return_t rc;
1047+ unsigned int x;
1048+ unsigned int retrieved;
1049+
1050+
1051+ for (retrieved= 0,x= 0; x < number_of; x++)
1052+ {
1053+ char *value;
1054+ size_t value_length;
1055+ uint32_t flags;
1056+ unsigned int fetch_key;
1057+
1058+ fetch_key= (unsigned int)((unsigned int)random() % number_of);
1059+
1060+ value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
1061+ &value_length, &flags, &rc);
1062+
1063+ if (rc != MEMCACHED_SUCCESS)
1064+ fprintf(stderr, "Failured on read of %.*s\n",
1065+ (unsigned int)pairs[fetch_key].key_length, pairs[fetch_key].key);
1066+ else
1067+ retrieved++;
1068+
1069+ free(value);
1070+ }
1071+
1072+ return retrieved;
1073+}
1074+
1075+/**
1076+ * Callback function to count the number of results
1077+ */
1078+static memcached_return_t callback_counter(const memcached_st *ptr,
1079+ memcached_result_st *result,
1080+ void *context)
1081+{
1082+ (void)ptr;
1083+ (void)result;
1084+ unsigned int *counter= (unsigned int *)context;
1085+ *counter= *counter + 1;
1086+
1087+ return MEMCACHED_SUCCESS;
1088+}
1089+
1090+/**
1091+ * Try to run a large mget to get all of the keys
1092+ * @param memc memcached handle
1093+ * @param keys the keys to get
1094+ * @param key_length the length of the keys
1095+ * @param number_of the number of keys to try to get
1096+ * @return the number of keys received
1097+ */
1098+unsigned int execute_mget(memcached_st *memc,
1099+ const char * const *keys,
1100+ size_t *key_length,
1101+ unsigned int number_of)
1102+{
1103+ unsigned int retrieved= 0;
1104+ memcached_execute_fn callbacks[]= { callback_counter };
1105+ memcached_return_t rc;
1106+ rc= memcached_mget_execute(memc, keys, key_length,
1107+ (size_t)number_of, callbacks, &retrieved, 1);
1108+
1109+ if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOTFOUND ||
1110+ rc == MEMCACHED_BUFFERED || rc == MEMCACHED_END)
1111+ {
1112+ rc= memcached_fetch_execute(memc, callbacks, (void *)&retrieved, 1);
1113+ if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_END)
1114+ {
1115+ fprintf(stderr, "Failed to execute mget: %s\n",
1116+ memcached_strerror(memc, rc));
1117+ memcached_quit(memc);
1118+ return 0;
1119+ }
1120+ }
1121+ else
1122+ {
1123+ fprintf(stderr, "Failed to execute mget: %s\n",
1124+ memcached_strerror(memc, rc));
1125+ memcached_quit(memc);
1126+ return 0;
1127+ }
1128+
1129+ return retrieved;
1130+}
1131
1132=== added file 'clients/execute.h'
1133--- clients/execute.h 1970-01-01 00:00:00 +0000
1134+++ clients/execute.h 2011-06-23 07:17:28 +0000
1135@@ -0,0 +1,30 @@
1136+/* LibMemcached
1137+ * Copyright (C) 2006-2009 Brian Aker
1138+ * All rights reserved.
1139+ *
1140+ * Use and distribution licensed under the BSD license. See
1141+ * the COPYING file in the parent directory for full text.
1142+ *
1143+ * Summary:
1144+ *
1145+ */
1146+
1147+#pragma once
1148+
1149+#include <stdio.h>
1150+
1151+#include "libmemcached/memcached.h"
1152+#include "clients/generator.h"
1153+
1154+#ifdef __cplusplus
1155+extern "C" {
1156+#endif
1157+
1158+unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of);
1159+unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int number_of);
1160+unsigned int execute_mget(memcached_st *memc, const char * const *keys, size_t *key_length,
1161+ unsigned int number_of);
1162+
1163+#ifdef __cplusplus
1164+} // extern "C"
1165+#endif
1166
1167=== added file 'clients/generator.cc'
1168--- clients/generator.cc 1970-01-01 00:00:00 +0000
1169+++ clients/generator.cc 2011-06-23 07:17:28 +0000
1170@@ -0,0 +1,96 @@
1171+/* LibMemcached
1172+ * Copyright (C) 2006-2009 Brian Aker
1173+ * All rights reserved.
1174+ *
1175+ * Use and distribution licensed under the BSD license. See
1176+ * the COPYING file in the parent directory for full text.
1177+ *
1178+ * Summary:
1179+ *
1180+ */
1181+
1182+#include "config.h"
1183+
1184+#include <stdio.h>
1185+#include <stdlib.h>
1186+#include <stdint.h>
1187+#include <string.h>
1188+
1189+#include "generator.h"
1190+
1191+/* Use this for string generation */
1192+static const char ALPHANUMERICS[]=
1193+ "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
1194+
1195+#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
1196+
1197+static size_t get_alpha_num(void)
1198+{
1199+ return (size_t)random() % ALPHANUMERICS_SIZE;
1200+}
1201+
1202+static void get_random_string(char *buffer, size_t size)
1203+{
1204+ char *buffer_ptr= buffer;
1205+
1206+ while (--size)
1207+ *buffer_ptr++= ALPHANUMERICS[get_alpha_num()];
1208+ *buffer_ptr++= ALPHANUMERICS[get_alpha_num()];
1209+}
1210+
1211+void pairs_free(pairs_st *pairs)
1212+{
1213+ uint32_t x;
1214+
1215+ if (! pairs)
1216+ return;
1217+
1218+ /* We free until we hit the null pair we stores during creation */
1219+ for (x= 0; pairs[x].key; x++)
1220+ {
1221+ free(pairs[x].key);
1222+ if (pairs[x].value)
1223+ free(pairs[x].value);
1224+ }
1225+
1226+ free(pairs);
1227+}
1228+
1229+pairs_st *pairs_generate(uint64_t number_of, size_t value_length)
1230+{
1231+ unsigned int x;
1232+ pairs_st *pairs;
1233+
1234+ pairs= (pairs_st*)calloc((size_t)number_of + 1, sizeof(pairs_st));
1235+
1236+ if (!pairs)
1237+ goto error;
1238+
1239+ for (x= 0; x < number_of; x++)
1240+ {
1241+ pairs[x].key= (char *)calloc(100, sizeof(char));
1242+ if (!pairs[x].key)
1243+ goto error;
1244+ get_random_string(pairs[x].key, 100);
1245+ pairs[x].key_length= 100;
1246+
1247+ if (value_length)
1248+ {
1249+ pairs[x].value= (char *)calloc(value_length, sizeof(char));
1250+ if (!pairs[x].value)
1251+ goto error;
1252+ get_random_string(pairs[x].value, value_length);
1253+ pairs[x].value_length= value_length;
1254+ }
1255+ else
1256+ {
1257+ pairs[x].value= NULL;
1258+ pairs[x].value_length= 0;
1259+ }
1260+ }
1261+
1262+ return pairs;
1263+error:
1264+ fprintf(stderr, "Memory Allocation failure in pairs_generate.\n");
1265+ exit(0);
1266+}
1267
1268=== added file 'clients/generator.h'
1269--- clients/generator.h 1970-01-01 00:00:00 +0000
1270+++ clients/generator.h 2011-06-23 07:17:28 +0000
1271@@ -0,0 +1,36 @@
1272+/* LibMemcached
1273+ * Copyright (C) 2006-2009 Brian Aker
1274+ * All rights reserved.
1275+ *
1276+ * Use and distribution licensed under the BSD license. See
1277+ * the COPYING file in the parent directory for full text.
1278+ *
1279+ * Summary:
1280+ *
1281+ */
1282+
1283+/*
1284+ Code to generate data to be pushed into memcached
1285+*/
1286+
1287+#pragma once
1288+
1289+typedef struct pairs_st pairs_st;
1290+
1291+struct pairs_st {
1292+ char *key;
1293+ size_t key_length;
1294+ char *value;
1295+ size_t value_length;
1296+};
1297+
1298+#ifdef __cplusplus
1299+extern "C" {
1300+#endif
1301+
1302+pairs_st *pairs_generate(uint64_t number_of, size_t value_length);
1303+void pairs_free(pairs_st *pairs);
1304+
1305+#ifdef __cplusplus
1306+} // extern "C"
1307+#endif
1308
1309=== added file 'clients/include.am'
1310--- clients/include.am 1970-01-01 00:00:00 +0000
1311+++ clients/include.am 2011-06-23 07:17:28 +0000
1312@@ -0,0 +1,116 @@
1313+# vim:ft=automake
1314+# included from Top Level Makefile.am
1315+# All paths should be given relative to the root
1316+
1317+CLIENTS_LDADDS= \
1318+ $(LIBM) \
1319+ clients/libutilities.la \
1320+ libmemcached/libmemcached.la
1321+
1322+if HAVE_SASL
1323+CLIENTS_LDADDS+= $(LIBSASL)
1324+endif
1325+
1326+bin_PROGRAMS+= \
1327+ clients/memcapable \
1328+ clients/memcat \
1329+ clients/memcp \
1330+ clients/memdump \
1331+ clients/memerror \
1332+ clients/memflush \
1333+ clients/memparse \
1334+ clients/memrm \
1335+ clients/memslap \
1336+ clients/memstat
1337+
1338+if BUILD_MEMASLAP
1339+if HAVE_LIBEVENT
1340+if !BUILD_WIN32_WRAPPERS
1341+ bin_PROGRAMS+= clients/memaslap
1342+endif
1343+endif
1344+endif
1345+
1346+noinst_HEADERS+= \
1347+ clients/client_options.h \
1348+ clients/execute.h \
1349+ clients/generator.h \
1350+ clients/ms_atomic.h \
1351+ clients/ms_conn.h \
1352+ clients/ms_memslap.h \
1353+ clients/ms_setting.h \
1354+ clients/ms_sigsegv.h \
1355+ clients/ms_stats.h \
1356+ clients/ms_task.h \
1357+ clients/ms_thread.h \
1358+ clients/utilities.h
1359+
1360+noinst_LTLIBRARIES+= clients/libutilities.la
1361+clients_libutilities_la_SOURCES= clients/utilities.cc
1362+
1363+clients_memcat_SOURCES= clients/memcat.cc
1364+clients_memcat_LDADD= $(CLIENTS_LDADDS)
1365+
1366+clients_memparse_SOURCES= clients/memparse.cc
1367+clients_memparse_LDADD= $(CLIENTS_LDADDS)
1368+
1369+clients_memcp_SOURCES= clients/memcp.cc
1370+clients_memcp_LDADD= $(CLIENTS_LDADDS)
1371+
1372+clients_memdump_SOURCES= clients/memdump.cc
1373+clients_memdump_LDADD= $(CLIENTS_LDADDS)
1374+
1375+clients_memstat_SOURCES= clients/memstat.cc
1376+clients_memstat_LDADD= $(CLIENTS_LDADDS)
1377+
1378+clients_memrm_SOURCES= clients/memrm.cc
1379+clients_memrm_LDADD= $(CLIENTS_LDADDS)
1380+
1381+clients_memflush_SOURCES= clients/memflush.cc
1382+clients_memflush_LDADD= $(CLIENTS_LDADDS)
1383+
1384+clients_memerror_SOURCES= clients/memerror.cc
1385+clients_memerror_LDADD= $(CLIENTS_LDADDS)
1386+
1387+clients_memslap_SOURCES = clients/memslap.cc
1388+clients_memslap_SOURCES+= clients/generator.cc clients/execute.cc
1389+clients_memslap_LDADD = $(PTHREAD_LIBS) $(CLIENTS_LDADDS)
1390+
1391+clients_memaslap_SOURCES= \
1392+ clients/memaslap.c \
1393+ clients/ms_conn.c \
1394+ clients/ms_setting.c \
1395+ clients/ms_sigsegv.c \
1396+ clients/ms_stats.c \
1397+ clients/ms_task.c \
1398+ clients/ms_thread.c
1399+clients_memaslap_SOURCES+= clients/generator.cc clients/execute.cc
1400+clients_memaslap_LDADD= $(LTLIBEVENT) $(CLIENTS_LDADDS)
1401+
1402+clients_memcapable_SOURCES= \
1403+ clients/memcapable.cc \
1404+ libmemcached/byteorder.cc
1405+clients_memcapable_LDADD= $(CLIENTS_LDADDS)
1406+
1407+test-start-server:
1408+ clients/memflush --servers=localhost
1409+ clients/memcp --servers=localhost /etc/services
1410+ clients/memcat --servers=localhost /etc/services
1411+ clients/memrm --servers=localhost /etc/services
1412+ clients/memstat --servers=localhost
1413+ clients/memslap --servers=localhost
1414+ clients/memslap --servers=localhost --concurrency=10
1415+ clients/memslap --servers=localhost --concurrency=10 --initial-load=1000
1416+ clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10
1417+ clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=get
1418+ clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set
1419+ clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set --non-blocking
1420+
1421+client-valgrind:
1422+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost
1423+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10
1424+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000
1425+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10
1426+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=get
1427+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set
1428+ libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes clients/memslap --servers=localhost --concurrency=10 --initial-load=1000 --execute-number=10 --test=set --non-blocking
1429
1430=== added file 'clients/memaslap.c'
1431--- clients/memaslap.c 1970-01-01 00:00:00 +0000
1432+++ clients/memaslap.c 2011-06-23 07:17:28 +0000
1433@@ -0,0 +1,908 @@
1434+/*
1435+ * memslap
1436+ *
1437+ * (c) Copyright 2009, Schooner Information Technology, Inc.
1438+ * All rights reserved.
1439+ * http://www.schoonerinfotech.com/
1440+ *
1441+ * Use and distribution licensed under the BSD license. See
1442+ * the COPYING file for full text.
1443+ *
1444+ * Authors:
1445+ * Brian Aker
1446+ * Mingqiang Zhuang <mingqiangzhuang@hengtiansoft.com>
1447+ *
1448+ */
1449+#include "config.h"
1450+
1451+#include <stdlib.h>
1452+#include <getopt.h>
1453+#include <limits.h>
1454+#if TIME_WITH_SYS_TIME
1455+# include <sys/time.h>
1456+# include <time.h>
1457+#else
1458+# if HAVE_SYS_TIME_H
1459+# include <sys/time.h>
1460+# else
1461+# include <time.h>
1462+# endif
1463+#endif
1464+
1465+
1466+#include "ms_sigsegv.h"
1467+#include "ms_setting.h"
1468+#include "ms_thread.h"
1469+
1470+#define PROGRAM_NAME "memslap"
1471+#define PROGRAM_DESCRIPTION \
1472+ "Generates workload against memcached servers."
1473+
1474+#ifdef __sun
1475+ /* For some odd reason the option struct on solaris defines the argument
1476+ * as char* and not const char*
1477+ */
1478+#define OPTIONSTRING char*
1479+#else
1480+#define OPTIONSTRING const char*
1481+#endif
1482+
1483+/* options */
1484+static struct option long_options[]=
1485+{
1486+ { (OPTIONSTRING)"servers", required_argument, NULL,
1487+ OPT_SERVERS },
1488+ { (OPTIONSTRING)"threads", required_argument, NULL,
1489+ OPT_THREAD_NUMBER },
1490+ { (OPTIONSTRING)"concurrency", required_argument, NULL,
1491+ OPT_CONCURRENCY },
1492+ { (OPTIONSTRING)"conn_sock", required_argument, NULL,
1493+ OPT_SOCK_PER_CONN },
1494+ { (OPTIONSTRING)"execute_number", required_argument, NULL,
1495+ OPT_EXECUTE_NUMBER },
1496+ { (OPTIONSTRING)"time", required_argument, NULL,
1497+ OPT_TIME },
1498+ { (OPTIONSTRING)"cfg_cmd", required_argument, NULL,
1499+ OPT_CONFIG_CMD },
1500+ { (OPTIONSTRING)"win_size", required_argument, NULL,
1501+ OPT_WINDOW_SIZE },
1502+ { (OPTIONSTRING)"fixed_size", required_argument, NULL,
1503+ OPT_FIXED_LTH },
1504+ { (OPTIONSTRING)"verify", required_argument, NULL,
1505+ OPT_VERIFY },
1506+ { (OPTIONSTRING)"division", required_argument, NULL,
1507+ OPT_GETS_DIVISION },
1508+ { (OPTIONSTRING)"stat_freq", required_argument, NULL,
1509+ OPT_STAT_FREQ },
1510+ { (OPTIONSTRING)"exp_verify", required_argument, NULL,
1511+ OPT_EXPIRE },
1512+ { (OPTIONSTRING)"overwrite", required_argument, NULL,
1513+ OPT_OVERWRITE },
1514+ { (OPTIONSTRING)"reconnect", no_argument, NULL,
1515+ OPT_RECONNECT },
1516+ { (OPTIONSTRING)"udp", no_argument, NULL,
1517+ OPT_UDP },
1518+ { (OPTIONSTRING)"facebook", no_argument, NULL,
1519+ OPT_FACEBOOK_TEST },
1520+ { (OPTIONSTRING)"binary", no_argument, NULL,
1521+ OPT_BINARY_PROTOCOL },
1522+ { (OPTIONSTRING)"tps", required_argument, NULL,
1523+ OPT_TPS },
1524+ { (OPTIONSTRING)"rep_write", required_argument, NULL,
1525+ OPT_REP_WRITE_SRV },
1526+ { (OPTIONSTRING)"verbose", no_argument, NULL,
1527+ OPT_VERBOSE },
1528+ { (OPTIONSTRING)"help", no_argument, NULL,
1529+ OPT_HELP },
1530+ { (OPTIONSTRING)"version", no_argument, NULL,
1531+ OPT_VERSION },
1532+ { 0, 0, 0, 0 },
1533+};
1534+
1535+/* Prototypes */
1536+static void ms_sync_lock_init(void);
1537+static void ms_sync_lock_destroy(void);
1538+static void ms_global_struct_init(void);
1539+static void ms_global_struct_destroy(void);
1540+static void ms_version_command(const char *command_name);
1541+static const char *ms_lookup_help(ms_options_t option);
1542+static int64_t ms_parse_time(void);
1543+static int64_t ms_parse_size(void);
1544+static void ms_options_parse(int argc, char *argv[]);
1545+static int ms_check_para(void);
1546+static void ms_statistic_init(void);
1547+static void ms_stats_init(void);
1548+static void ms_print_statistics(int in_time);
1549+static void ms_print_memslap_stats(struct timeval *start_time,
1550+ struct timeval *end_time);
1551+static void ms_monitor_slap_mode(void);
1552+void ms_help_command(const char *command_name, const char *description);
1553+
1554+
1555+/* initialize the global locks */
1556+static void ms_sync_lock_init()
1557+{
1558+ ms_global.init_lock.count= 0;
1559+ pthread_mutex_init(&ms_global.init_lock.lock, NULL);
1560+ pthread_cond_init(&ms_global.init_lock.cond, NULL);
1561+
1562+ ms_global.warmup_lock.count = 0;
1563+ pthread_mutex_init(&ms_global.warmup_lock.lock, NULL);
1564+ pthread_cond_init(&ms_global.warmup_lock.cond, NULL);
1565+
1566+ ms_global.run_lock.count= 0;
1567+ pthread_mutex_init(&ms_global.run_lock.lock, NULL);
1568+ pthread_cond_init(&ms_global.run_lock.cond, NULL);
1569+
1570+ pthread_mutex_init(&ms_global.quit_mutex, NULL);
1571+ pthread_mutex_init(&ms_global.seq_mutex, NULL);
1572+} /* ms_sync_lock_init */
1573+
1574+
1575+/* destroy the global locks */
1576+static void ms_sync_lock_destroy()
1577+{
1578+ pthread_mutex_destroy(&ms_global.init_lock.lock);
1579+ pthread_cond_destroy(&ms_global.init_lock.cond);
1580+
1581+ pthread_mutex_destroy(&ms_global.warmup_lock.lock);
1582+ pthread_cond_destroy(&ms_global.warmup_lock.cond);
1583+
1584+ pthread_mutex_destroy(&ms_global.run_lock.lock);
1585+ pthread_cond_destroy(&ms_global.run_lock.cond);
1586+
1587+ pthread_mutex_destroy(&ms_global.quit_mutex);
1588+ pthread_mutex_destroy(&ms_global.seq_mutex);
1589+
1590+ if (ms_setting.stat_freq > 0)
1591+ {
1592+ pthread_mutex_destroy(&ms_statistic.stat_mutex);
1593+ }
1594+} /* ms_sync_lock_destroy */
1595+
1596+
1597+/* initialize the global structure */
1598+static void ms_global_struct_init()
1599+{
1600+ ms_sync_lock_init();
1601+ ms_global.finish_warmup= false;
1602+ ms_global.time_out= false;
1603+}
1604+
1605+
1606+/* destroy the global structure */
1607+static void ms_global_struct_destroy()
1608+{
1609+ ms_sync_lock_destroy();
1610+}
1611+
1612+
1613+/**
1614+ * output the version information
1615+ *
1616+ * @param command_name, the string of this process
1617+ */
1618+static void ms_version_command(const char *command_name)
1619+{
1620+ printf("%s v%u.%u\n", command_name, 1U, 0U);
1621+ exit(0);
1622+}
1623+
1624+
1625+/**
1626+ * get the description of the option
1627+ *
1628+ * @param option, option of command line
1629+ *
1630+ * @return char*, description of the command option
1631+ */
1632+static const char *ms_lookup_help(ms_options_t option)
1633+{
1634+ switch (option)
1635+ {
1636+ case OPT_SERVERS:
1637+ return
1638+ "List one or more servers to connect. Servers count must be less than\n"
1639+ " threads count. e.g.: --servers=localhost:1234,localhost:11211";
1640+
1641+ case OPT_VERSION:
1642+ return "Display the version of the application and then exit.";
1643+
1644+ case OPT_HELP:
1645+ return "Display this message and then exit.";
1646+
1647+ case OPT_EXECUTE_NUMBER:
1648+ return "Number of operations(get and set) to execute for the\n"
1649+ " given test. Default 1000000.";
1650+
1651+ case OPT_THREAD_NUMBER:
1652+ return
1653+ "Number of threads to startup, better equal to CPU numbers. Default 8.";
1654+
1655+ case OPT_CONCURRENCY:
1656+ return "Number of concurrency to simulate with load. Default 128.";
1657+
1658+ case OPT_FIXED_LTH:
1659+ return "Fixed length of value.";
1660+
1661+ case OPT_VERIFY:
1662+ return "The proportion of date verification, e.g.: --verify=0.01";
1663+
1664+ case OPT_GETS_DIVISION:
1665+ return "Number of keys to multi-get once. Default 1, means single get.";
1666+
1667+ case OPT_TIME:
1668+ return
1669+ "How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n"
1670+ " d-days e.g.: --time=2h.";
1671+
1672+ case OPT_CONFIG_CMD:
1673+ return
1674+ "Load the configure file to get command,key and value distribution list.";
1675+
1676+ case OPT_WINDOW_SIZE:
1677+ return
1678+ "Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n"
1679+ " Default 10k.";
1680+
1681+ case OPT_UDP:
1682+ return
1683+ "UDP support, default memslap uses TCP, TCP port and UDP port of\n"
1684+ " server must be same.";
1685+
1686+ case OPT_EXPIRE:
1687+ return
1688+ "The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n"
1689+ " Default no object with expire time";
1690+
1691+ case OPT_OVERWRITE:
1692+ return
1693+ "The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n"
1694+ " Default never overwrite object.";
1695+
1696+ case OPT_STAT_FREQ:
1697+ return
1698+ "Frequency of dumping statistic information. suffix: s-seconds,\n"
1699+ " m-minutes, e.g.: --resp_freq=10s.";
1700+
1701+ case OPT_SOCK_PER_CONN:
1702+ return "Number of TCP socks per concurrency. Default 1.";
1703+
1704+ case OPT_RECONNECT:
1705+ return
1706+ "Reconnect support, when connection is closed it will be reconnected.";
1707+
1708+ case OPT_VERBOSE:
1709+ return
1710+ "Whether it outputs detailed information when verification fails.";
1711+
1712+ case OPT_FACEBOOK_TEST:
1713+ return
1714+ "Whether it enables facebook test feature, set with TCP and multi-get with UDP.";
1715+
1716+ case OPT_BINARY_PROTOCOL:
1717+ return
1718+ "Whether it enables binary protocol. Default with ASCII protocol.";
1719+
1720+ case OPT_TPS:
1721+ return "Expected throughput, suffix: K, e.g.: --tps=10k.";
1722+
1723+ case OPT_REP_WRITE_SRV:
1724+ return "The first nth servers can write data, e.g.: --rep_write=2.";
1725+
1726+ default:
1727+ return "Forgot to document this option :)";
1728+ } /* switch */
1729+} /* ms_lookup_help */
1730+
1731+
1732+/**
1733+ * output the help information
1734+ *
1735+ * @param command_name, the string of this process
1736+ * @param description, description of this process
1737+ * @param long_options, global options array
1738+ */
1739+void ms_help_command(const char *command_name, const char *description)
1740+{
1741+ char *help_message= NULL;
1742+
1743+ printf("%s v%u.%u\n", command_name, 1U, 0U);
1744+ printf(" %s\n\n", description);
1745+ printf(
1746+ "Usage:\n"
1747+ " memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n"
1748+ "Options:\n");
1749+
1750+ for (int x= 0; long_options[x].name; x++)
1751+ {
1752+ printf(" -%c, --%s%c\n", long_options[x].val, long_options[x].name,
1753+ long_options[x].has_arg ? '=' : ' ');
1754+
1755+ if ((help_message= (char *)ms_lookup_help(long_options[x].val)) != NULL)
1756+ {
1757+ printf(" %s\n", help_message);
1758+ }
1759+ }
1760+
1761+ printf(
1762+ "\nExamples:\n"
1763+ " memslap -s 127.0.0.1:11211 -S 5s\n"
1764+ " memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n"
1765+ " memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n"
1766+ " memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n"
1767+ " memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n"
1768+ " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n"
1769+ " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n");
1770+
1771+ exit(0);
1772+} /* ms_help_command */
1773+
1774+
1775+/* used to parse the time string */
1776+static int64_t ms_parse_time()
1777+{
1778+ int64_t ret= 0;
1779+ char unit= optarg[strlen(optarg) - 1];
1780+
1781+ optarg[strlen(optarg) - 1]= '\0';
1782+ ret= atoi(optarg);
1783+
1784+ switch (unit)
1785+ {
1786+ case 'd':
1787+ case 'D':
1788+ ret*= 24;
1789+
1790+ case 'h':
1791+ case 'H':
1792+ ret*= 60;
1793+
1794+ case 'm':
1795+ case 'M':
1796+ ret*= 60;
1797+
1798+ case 's':
1799+ case 'S':
1800+ break;
1801+
1802+ default:
1803+ ret= -1;
1804+ break;
1805+ } /* switch */
1806+
1807+ return ret;
1808+} /* ms_parse_time */
1809+
1810+
1811+/* used to parse the size string */
1812+static int64_t ms_parse_size()
1813+{
1814+ int64_t ret= -1;
1815+ char unit= optarg[strlen(optarg) - 1];
1816+
1817+ optarg[strlen(optarg) - 1]= '\0';
1818+ ret= strtoll(optarg, (char **)NULL, 10);
1819+
1820+ switch (unit)
1821+ {
1822+ case 'k':
1823+ case 'K':
1824+ ret*= 1024;
1825+ break;
1826+
1827+ case 'm':
1828+ case 'M':
1829+ ret*= 1024 * 1024;
1830+ break;
1831+
1832+ case 'g':
1833+ case 'G':
1834+ ret*= 1024 * 1024 * 1024;
1835+ break;
1836+
1837+ default:
1838+ ret= -1;
1839+ break;
1840+ } /* switch */
1841+
1842+ return ret;
1843+} /* ms_parse_size */
1844+
1845+
1846+/* used to parse the options of command line */
1847+static void ms_options_parse(int argc, char *argv[])
1848+{
1849+ int option_index= 0;
1850+ int option_rv;
1851+
1852+ while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:"
1853+ "t:S:F:w:e:o:n:P:p:",
1854+ long_options, &option_index)) != -1)
1855+ {
1856+ switch (option_rv)
1857+ {
1858+ case 0:
1859+ break;
1860+
1861+ case OPT_VERSION: /* --version or -V */
1862+ ms_version_command(PROGRAM_NAME);
1863+ break;
1864+
1865+ case OPT_HELP: /* --help or -h */
1866+ ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
1867+ break;
1868+
1869+ case OPT_SERVERS: /* --servers or -s */
1870+ ms_setting.srv_str= strdup(optarg);
1871+ break;
1872+
1873+ case OPT_CONCURRENCY: /* --concurrency or -c */
1874+ ms_setting.nconns= (uint32_t)strtoul(optarg, (char **) NULL, 10);
1875+ if (ms_setting.nconns <= 0)
1876+ {
1877+ fprintf(stderr, "Concurrency must be greater than 0.:-)\n");
1878+ exit(1);
1879+ }
1880+ break;
1881+
1882+ case OPT_EXECUTE_NUMBER: /* --execute_number or -x */
1883+ ms_setting.exec_num= (int)strtol(optarg, (char **) NULL, 10);
1884+ if (ms_setting.exec_num <= 0)
1885+ {
1886+ fprintf(stderr, "Execute number must be greater than 0.:-)\n");
1887+ exit(1);
1888+ }
1889+ break;
1890+
1891+ case OPT_THREAD_NUMBER: /* --threads or -T */
1892+ ms_setting.nthreads= (uint32_t)strtoul(optarg, (char **) NULL, 10);
1893+ if (ms_setting.nthreads <= 0)
1894+ {
1895+ fprintf(stderr, "Threads number must be greater than 0.:-)\n");
1896+ exit(1);
1897+ }
1898+ break;
1899+
1900+ case OPT_FIXED_LTH: /* --fixed_size or -X */
1901+ ms_setting.fixed_value_size= (size_t)strtoull(optarg, (char **) NULL, 10);
1902+ if ((ms_setting.fixed_value_size <= 0)
1903+ || (ms_setting.fixed_value_size > MAX_VALUE_SIZE))
1904+ {
1905+ fprintf(stderr, "Value size must be between 0 and 1M.:-)\n");
1906+ exit(1);
1907+ }
1908+ break;
1909+
1910+ case OPT_VERIFY: /* --verify or -v */
1911+ ms_setting.verify_percent= atof(optarg);
1912+ if ((ms_setting.verify_percent <= 0)
1913+ || (ms_setting.verify_percent > 1.0))
1914+ {
1915+ fprintf(stderr, "Data verification rate must be "
1916+ "greater than 0 and less than 1.0. :-)\n");
1917+ exit(1);
1918+ }
1919+ break;
1920+
1921+ case OPT_GETS_DIVISION: /* --division or -d */
1922+ ms_setting.mult_key_num= (int)strtol(optarg, (char **) NULL, 10);
1923+ if (ms_setting.mult_key_num <= 0)
1924+ {
1925+ fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n");
1926+ exit(1);
1927+ }
1928+ break;
1929+
1930+ case OPT_TIME: /* --time or -t */
1931+ ms_setting.run_time= (int)ms_parse_time();
1932+ if (ms_setting.run_time == -1)
1933+ {
1934+ fprintf(stderr, "Please specify the run time. :-)\n"
1935+ "'s' for second, 'm' for minute, 'h' for hour, "
1936+ "'d' for day. e.g.: --time=24h (means 24 hours).\n");
1937+ exit(1);
1938+ }
1939+
1940+ if (ms_setting.run_time == 0)
1941+ {
1942+ fprintf(stderr, "Running time can not be 0. :-)\n");
1943+ exit(1);
1944+ }
1945+ break;
1946+
1947+ case OPT_CONFIG_CMD: /* --cfg_cmd or -F */
1948+ ms_setting.cfg_file= strdup(optarg);
1949+ break;
1950+
1951+ case OPT_WINDOW_SIZE: /* --win_size or -w */
1952+ ms_setting.win_size= (size_t)ms_parse_size();
1953+ if (ms_setting.win_size == (size_t)-1)
1954+ {
1955+ fprintf(
1956+ stderr,
1957+ "Please specify the item window size. :-)\n"
1958+ "e.g.: --win_size=10k (means 10k task window size).\n");
1959+ exit(1);
1960+ }
1961+ break;
1962+
1963+ case OPT_UDP: /* --udp or -U*/
1964+ ms_setting.udp= true;
1965+ break;
1966+
1967+ case OPT_EXPIRE: /* --exp_verify or -e */
1968+ ms_setting.exp_ver_per= atof(optarg);
1969+ if ((ms_setting.exp_ver_per <= 0) || (ms_setting.exp_ver_per > 1.0))
1970+ {
1971+ fprintf(stderr, "Expire time verification rate must be "
1972+ "greater than 0 and less than 1.0. :-)\n");
1973+ exit(1);
1974+ }
1975+ break;
1976+
1977+ case OPT_OVERWRITE: /* --overwrite or -o */
1978+ ms_setting.overwrite_percent= atof(optarg);
1979+ if ((ms_setting.overwrite_percent <= 0)
1980+ || (ms_setting.overwrite_percent > 1.0))
1981+ {
1982+ fprintf(stderr, "Objects overwrite rate must be "
1983+ "greater than 0 and less than 1.0. :-)\n");
1984+ exit(1);
1985+ }
1986+ break;
1987+
1988+ case OPT_STAT_FREQ: /* --stat_freq or -S */
1989+ ms_setting.stat_freq= (int)ms_parse_time();
1990+ if (ms_setting.stat_freq == -1)
1991+ {
1992+ fprintf(stderr, "Please specify the frequency of dumping "
1993+ "statistic information. :-)\n"
1994+ "'s' for second, 'm' for minute, 'h' for hour, "
1995+ "'d' for day. e.g.: --time=24h (means 24 hours).\n");
1996+ exit(1);
1997+ }
1998+
1999+ if (ms_setting.stat_freq == 0)
2000+ {
2001+ fprintf(stderr, "The frequency of dumping statistic information "
2002+ "can not be 0. :-)\n");
2003+ exit(1);
2004+ }
2005+ break;
2006+
2007+ case OPT_SOCK_PER_CONN: /* --conn_sock or -n */
2008+ ms_setting.sock_per_conn= (uint32_t)strtoul(optarg, (char **) NULL, 10);
2009+ if (ms_setting.sock_per_conn <= 0)
2010+ {
2011+ fprintf(stderr, "Number of socks of each concurrency "
2012+ "must be greater than 0.:-)\n");
2013+ exit(1);
2014+ }
2015+ break;
2016+
2017+ case OPT_RECONNECT: /* --reconnect or -R */
2018+ ms_setting.reconnect= true;
2019+ break;
2020+
2021+ case OPT_VERBOSE: /* --verbose or -b */
2022+ ms_setting.verbose= true;
2023+ break;
2024+
2025+ case OPT_FACEBOOK_TEST: /* --facebook or -a */
2026+ ms_setting.facebook_test= true;
2027+ break;
2028+
2029+ case OPT_BINARY_PROTOCOL: /* --binary or -B */
2030+ ms_setting.binary_prot= true;
2031+ break;
2032+
2033+ case OPT_TPS: /* --tps or -P */
2034+ ms_setting.expected_tps= (int)ms_parse_size();
2035+ if (ms_setting.expected_tps == -1)
2036+ {
2037+ fprintf(stderr,
2038+ "Please specify the item expected throughput. :-)\n"
2039+ "e.g.: --tps=10k (means 10k throughput).\n");
2040+ exit(1);
2041+ }
2042+ break;
2043+
2044+ case OPT_REP_WRITE_SRV: /* --rep_write or -p */
2045+ ms_setting.rep_write_srv= (uint32_t)strtoul(optarg, (char **) NULL, 10);
2046+ if (ms_setting.rep_write_srv <= 0)
2047+ {
2048+ fprintf(stderr,
2049+ "Number of replication writing server must be greater "
2050+ "than 0.:-)\n");
2051+ exit(1);
2052+ }
2053+ break;
2054+
2055+ case '?':
2056+ /* getopt_long already printed an error message. */
2057+ exit(1);
2058+
2059+ default:
2060+ abort();
2061+ } /* switch */
2062+ }
2063+} /* ms_options_parse */
2064+
2065+
2066+static int ms_check_para()
2067+{
2068+ if (ms_setting.srv_str == NULL)
2069+ {
2070+ char *temp;
2071+
2072+ if ((temp= getenv("MEMCACHED_SERVERS")))
2073+ {
2074+ ms_setting.srv_str= strdup(temp);
2075+ }
2076+ else
2077+ {
2078+ fprintf(stderr, "No Servers provided\n\n");
2079+ return -1;
2080+ }
2081+ }
2082+
2083+ if (ms_setting.nconns % (uint32_t)ms_setting.nthreads != 0)
2084+ {
2085+ fprintf(stderr, "Concurrency must be the multiples of threads count.\n");
2086+ return -1;
2087+ }
2088+
2089+ if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0)
2090+ {
2091+ fprintf(stderr, "Window size must be the multiples of 1024.\n\n");
2092+ return -1;
2093+ }
2094+
2095+ return EXIT_SUCCESS;
2096+} /* ms_check_para */
2097+
2098+
2099+/* initialize the statistic structure */
2100+static void ms_statistic_init()
2101+{
2102+ pthread_mutex_init(&ms_statistic.stat_mutex, NULL);
2103+ ms_init_stats(&ms_statistic.get_stat, "Get");
2104+ ms_init_stats(&ms_statistic.set_stat, "Set");
2105+ ms_init_stats(&ms_statistic.total_stat, "Total");
2106+} /* ms_statistic_init */
2107+
2108+
2109+/* initialize the global state structure */
2110+static void ms_stats_init()
2111+{
2112+ memset(&ms_stats, 0, sizeof(ms_stats_t));
2113+ if (ms_setting.stat_freq > 0)
2114+ {
2115+ ms_statistic_init();
2116+ }
2117+} /* ms_stats_init */
2118+
2119+
2120+/* use to output the statistic */
2121+static void ms_print_statistics(int in_time)
2122+{
2123+ int obj_size= (int)(ms_setting.avg_key_size + ms_setting.avg_val_size);
2124+
2125+ printf("\033[1;1H\033[2J\n");
2126+ ms_dump_format_stats(&ms_statistic.get_stat, in_time,
2127+ ms_setting.stat_freq, obj_size);
2128+ ms_dump_format_stats(&ms_statistic.set_stat, in_time,
2129+ ms_setting.stat_freq, obj_size);
2130+ ms_dump_format_stats(&ms_statistic.total_stat, in_time,
2131+ ms_setting.stat_freq, obj_size);
2132+} /* ms_print_statistics */
2133+
2134+
2135+/* used to print the states of memslap */
2136+static void ms_print_memslap_stats(struct timeval *start_time,
2137+ struct timeval *end_time)
2138+{
2139+ char buf[1024];
2140+ char *pos= buf;
2141+
2142+ pos+= snprintf(pos,
2143+ sizeof(buf), "cmd_get: %lu\n",
2144+ (unsigned long) ms_stats.cmd_get);
2145+ pos+= snprintf(pos,
2146+ sizeof(buf) - (size_t)(pos -buf),
2147+ "cmd_set: %lu\n",
2148+ (unsigned long) ms_stats.cmd_set);
2149+ pos+= snprintf(pos,
2150+ sizeof(buf) - (size_t)(pos -buf),
2151+ "get_misses: %lu\n",
2152+ (unsigned long) ms_stats.get_misses);
2153+
2154+ if (ms_setting.verify_percent > 0)
2155+ {
2156+ pos+= snprintf(pos,
2157+ sizeof(buf) - (size_t)(pos -buf),
2158+ "verify_misses: %lu\n",
2159+ (unsigned long) ms_stats.vef_miss);
2160+ pos+= snprintf(pos,
2161+ sizeof(buf) - (size_t)(pos -buf),
2162+ "verify_failed: %lu\n",
2163+ (unsigned long) ms_stats.vef_failed);
2164+ }
2165+
2166+ if (ms_setting.exp_ver_per > 0)
2167+ {
2168+ pos+= snprintf(pos,
2169+ sizeof(buf) - (size_t)(pos -buf),
2170+ "expired_get: %lu\n",
2171+ (unsigned long) ms_stats.exp_get);
2172+ pos+= snprintf(pos,
2173+ sizeof(buf) - (size_t)(pos -buf),
2174+ "unexpired_unget: %lu\n",
2175+ (unsigned long) ms_stats.unexp_unget);
2176+ }
2177+
2178+ pos+= snprintf(pos,
2179+ sizeof(buf) - (size_t)(pos -buf),
2180+ "written_bytes: %lu\n",
2181+ (unsigned long) ms_stats.bytes_written);
2182+ pos+= snprintf(pos,
2183+ sizeof(buf) - (size_t)(pos -buf),
2184+ "read_bytes: %lu\n",
2185+ (unsigned long) ms_stats.bytes_read);
2186+ pos+= snprintf(pos,
2187+ sizeof(buf) - (size_t)(pos -buf),
2188+ "object_bytes: %lu\n",
2189+ (unsigned long) ms_stats.obj_bytes);
2190+
2191+ if (ms_setting.udp || ms_setting.facebook_test)
2192+ {
2193+ pos+= snprintf(pos,
2194+ sizeof(buf) - (size_t)(pos -buf),
2195+ "packet_disorder: %lu\n",
2196+ (unsigned long) ms_stats.pkt_disorder);
2197+ pos+= snprintf(pos,
2198+ sizeof(buf) - (size_t)(pos -buf),
2199+ "packet_drop: %lu\n",
2200+ (unsigned long)ms_stats.pkt_drop);
2201+ pos+= snprintf(pos,
2202+ sizeof(buf) - (size_t)(pos -buf),
2203+ "udp_timeout: %lu\n",
2204+ (unsigned long)ms_stats.udp_timeout);
2205+ }
2206+
2207+ if (ms_setting.stat_freq > 0)
2208+ {
2209+ ms_dump_stats(&ms_statistic.get_stat);
2210+ ms_dump_stats(&ms_statistic.set_stat);
2211+ ms_dump_stats(&ms_statistic.total_stat);
2212+ }
2213+
2214+ int64_t time_diff= ms_time_diff(start_time, end_time);
2215+ pos+= snprintf(pos,
2216+ sizeof(buf) - (size_t)(pos -buf),
2217+ "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n",
2218+ (double)time_diff / 1000000,
2219+ (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set),
2220+ (ms_stats.cmd_get
2221+ + ms_stats.cmd_set) / ((long double)time_diff / 1000000),
2222+ (double)(
2223+ ms_stats.bytes_written
2224+ + ms_stats.bytes_read) / 1024 / 1024
2225+ / ((double)time_diff / 1000000));
2226+ assert(pos <= buf);
2227+
2228+ fprintf(stdout, "%s", buf);
2229+ fflush(stdout);
2230+} /* ms_print_memslap_stats */
2231+
2232+
2233+/* the loop of the main thread, wait the work threads to complete */
2234+static void ms_monitor_slap_mode()
2235+{
2236+ int second= 0;
2237+ struct timeval start_time, end_time;
2238+
2239+ /* Wait all the threads complete initialization. */
2240+ pthread_mutex_lock(&ms_global.init_lock.lock);
2241+ while (ms_global.init_lock.count < ms_setting.nthreads)
2242+ {
2243+ pthread_cond_wait(&ms_global.init_lock.cond,
2244+ &ms_global.init_lock.lock);
2245+ }
2246+ pthread_mutex_unlock(&ms_global.init_lock.lock);
2247+
2248+ /* only when there is no set operation it need warm up */
2249+ if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
2250+ {
2251+ /* Wait all the connects complete warm up. */
2252+ pthread_mutex_lock(&ms_global.warmup_lock.lock);
2253+ while (ms_global.warmup_lock.count < ms_setting.nconns)
2254+ {
2255+ pthread_cond_wait(&ms_global.warmup_lock.cond, &ms_global.warmup_lock.lock);
2256+ }
2257+ pthread_mutex_unlock(&ms_global.warmup_lock.lock);
2258+ }
2259+ ms_global.finish_warmup= true;
2260+
2261+ /* running in "run time" mode, user specify run time */
2262+ if (ms_setting.run_time > 0)
2263+ {
2264+ gettimeofday(&start_time, NULL);
2265+ while (1)
2266+ {
2267+ sleep(1);
2268+ second++;
2269+
2270+ if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0)
2271+ && (ms_stats.active_conns >= ms_setting.nconns)
2272+ && (ms_stats.active_conns <= INT_MAX))
2273+ {
2274+ ms_print_statistics(second);
2275+ }
2276+
2277+ if (ms_setting.run_time <= second)
2278+ {
2279+ ms_global.time_out= true;
2280+ break;
2281+ }
2282+
2283+ /* all connections disconnect */
2284+ if ((second > 5) && (ms_stats.active_conns == 0))
2285+ {
2286+ break;
2287+ }
2288+ }
2289+ gettimeofday(&end_time, NULL);
2290+ sleep(1); /* wait all threads clean up */
2291+ }
2292+ else
2293+ {
2294+ /* running in "execute number" mode, user specify execute number */
2295+ gettimeofday(&start_time, NULL);
2296+
2297+ /*
2298+ * We loop until we know that all connects have cleaned up.
2299+ */
2300+ pthread_mutex_lock(&ms_global.run_lock.lock);
2301+ while (ms_global.run_lock.count < ms_setting.nconns)
2302+ {
2303+ pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock);
2304+ }
2305+ pthread_mutex_unlock(&ms_global.run_lock.lock);
2306+
2307+ gettimeofday(&end_time, NULL);
2308+ }
2309+
2310+ ms_print_memslap_stats(&start_time, &end_time);
2311+} /* ms_monitor_slap_mode */
2312+
2313+
2314+/* the main function */
2315+int main(int argc, char *argv[])
2316+{
2317+ srandom((unsigned int)time(NULL));
2318+ ms_global_struct_init();
2319+
2320+ /* initialization */
2321+ ms_setting_init_pre();
2322+ ms_options_parse(argc, argv);
2323+ if (ms_check_para())
2324+ {
2325+ ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
2326+ exit(1);
2327+ }
2328+ ms_setting_init_post();
2329+ ms_stats_init();
2330+ ms_thread_init();
2331+
2332+ /* waiting work thread complete its task */
2333+ ms_monitor_slap_mode();
2334+
2335+ /* clean up */
2336+ ms_thread_cleanup();
2337+ ms_global_struct_destroy();
2338+ ms_setting_cleanup();
2339+
2340+ return EXIT_SUCCESS;
2341+} /* main */
2342
2343=== added file 'clients/memcapable.cc'
2344--- clients/memcapable.cc 1970-01-01 00:00:00 +0000
2345+++ clients/memcapable.cc 2011-06-23 07:17:28 +0000
2346@@ -0,0 +1,2094 @@
2347+/* LibMemcached
2348+ * Copyright (C) 2006-2009 Brian Aker
2349+ * All rights reserved.
2350+ *
2351+ * Use and distribution licensed under the BSD license. See
2352+ * the COPYING file in the parent directory for full text.
2353+ *
2354+ * Summary:
2355+ *
2356+ */
2357+
2358+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2359+#undef NDEBUG
2360+
2361+#include "config.h"
2362+#include <pthread.h>
2363+#include <sys/types.h>
2364+#include <fcntl.h>
2365+#include <signal.h>
2366+#include <stdio.h>
2367+#include <stdlib.h>
2368+#include <errno.h>
2369+#include <assert.h>
2370+#include <string.h>
2371+#include <inttypes.h>
2372+#include <stdbool.h>
2373+#include <unistd.h>
2374+#include <ctype.h>
2375+
2376+#include <libmemcached/memcached.h>
2377+#include <libmemcached/memcached/protocol_binary.h>
2378+#include <libmemcached/byteorder.h>
2379+#include "utilities.h"
2380+
2381+#ifdef linux
2382+/* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to
2383+ * optimize the conversion functions, but the prototypes generate warnings
2384+ * from gcc. The conversion methods isn't the bottleneck for my app, so
2385+ * just remove the warnings by undef'ing the optimization ..
2386+ */
2387+#undef ntohs
2388+#undef ntohl
2389+#endif
2390+
2391+/* Should we generate coredumps when we enounter an error (-c) */
2392+static bool do_core= false;
2393+/* connection to the server */
2394+static memcached_socket_t sock;
2395+/* Should the output from test failures be verbose or quiet? */
2396+static bool verbose= false;
2397+
2398+/* The number of seconds to wait for an IO-operation */
2399+static int timeout= 2;
2400+
2401+/*
2402+ * Instead of having to cast between the different datatypes we create
2403+ * a union of all of the different types of pacages we want to send.
2404+ * A lot of the different commands use the same packet layout, so I'll
2405+ * just define the different types I need. The typedefs only contain
2406+ * the header of the message, so we need some space for keys and body
2407+ * To avoid to have to do multiple writes, lets add a chunk of memory
2408+ * to use. 1k should be more than enough for header, key and body.
2409+ */
2410+typedef union
2411+{
2412+ protocol_binary_request_no_extras plain;
2413+ protocol_binary_request_flush flush;
2414+ protocol_binary_request_incr incr;
2415+ protocol_binary_request_set set;
2416+ char bytes[1024];
2417+} command;
2418+
2419+typedef union
2420+{
2421+ protocol_binary_response_no_extras plain;
2422+ protocol_binary_response_incr incr;
2423+ protocol_binary_response_decr decr;
2424+ char bytes[1024];
2425+} response;
2426+
2427+enum test_return
2428+{
2429+ TEST_SKIP, TEST_PASS, TEST_PASS_RECONNECT, TEST_FAIL
2430+};
2431+
2432+/**
2433+ * Try to get an addrinfo struct for a given port on a given host
2434+ */
2435+static struct addrinfo *lookuphost(const char *hostname, const char *port)
2436+{
2437+ struct addrinfo *ai= 0;
2438+ struct addrinfo hints;
2439+ memset(&hints, 0, sizeof(struct addrinfo));
2440+ hints.ai_family=AF_UNSPEC;
2441+ hints.ai_protocol=IPPROTO_TCP;
2442+ hints.ai_socktype=SOCK_STREAM;
2443+
2444+ int error= getaddrinfo(hostname, port, &hints, &ai);
2445+ if (error != 0)
2446+ {
2447+ if (error != EAI_SYSTEM)
2448+ fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
2449+ else
2450+ perror("getaddrinfo()");
2451+ }
2452+
2453+ return ai;
2454+}
2455+
2456+/**
2457+ * Set the socket in nonblocking mode
2458+ * @return -1 if failure, the socket otherwise
2459+ */
2460+static memcached_socket_t set_noblock(void)
2461+{
2462+#ifdef WIN32
2463+ u_long arg = 1;
2464+ if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR)
2465+ {
2466+ perror("Failed to set nonblocking io");
2467+ closesocket(sock);
2468+ return INVALID_SOCKET;
2469+ }
2470+#else
2471+ int flags= fcntl(sock, F_GETFL, 0);
2472+ if (flags == -1)
2473+ {
2474+ perror("Failed to get socket flags");
2475+ closesocket(sock);
2476+ return INVALID_SOCKET;
2477+ }
2478+
2479+ if ((flags & O_NONBLOCK) != O_NONBLOCK)
2480+ {
2481+ if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
2482+ {
2483+ perror("Failed to set socket to nonblocking mode");
2484+ closesocket(sock);
2485+ return INVALID_SOCKET;
2486+ }
2487+ }
2488+#endif
2489+ return sock;
2490+}
2491+
2492+/**
2493+ * Try to open a connection to the server
2494+ * @param hostname the name of the server to connect to
2495+ * @param port the port number (or service) to connect to
2496+ * @return positive integer if success, -1 otherwise
2497+ */
2498+static memcached_socket_t connect_server(const char *hostname, const char *port)
2499+{
2500+ struct addrinfo *ai= lookuphost(hostname, port);
2501+ sock= INVALID_SOCKET;
2502+ if (ai != NULL)
2503+ {
2504+ if ((sock= socket(ai->ai_family, ai->ai_socktype,
2505+ ai->ai_protocol)) != INVALID_SOCKET)
2506+ {
2507+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR)
2508+ {
2509+ fprintf(stderr, "Failed to connect socket: %s\n",
2510+ strerror(get_socket_errno()));
2511+ closesocket(sock);
2512+ sock= INVALID_SOCKET;
2513+ }
2514+ else
2515+ {
2516+ sock= set_noblock();
2517+ }
2518+ }
2519+ else
2520+ fprintf(stderr, "Failed to create socket: %s\n",
2521+ strerror(get_socket_errno()));
2522+
2523+ freeaddrinfo(ai);
2524+ }
2525+
2526+ return sock;
2527+}
2528+
2529+static ssize_t timeout_io_op(memcached_socket_t fd, short direction, void *buf, size_t len)
2530+{
2531+ ssize_t ret;
2532+
2533+ if (direction == POLLOUT)
2534+ {
2535+ ret= send(fd, buf, len, 0);
2536+ }
2537+ else
2538+ {
2539+ ret= recv(fd, buf, len, 0);
2540+ }
2541+
2542+ if (ret == SOCKET_ERROR && get_socket_errno() == EWOULDBLOCK)
2543+ {
2544+ struct pollfd fds;
2545+ memset(&fds, 0, sizeof(struct pollfd));
2546+ fds.events= direction;
2547+ fds.fd= fd;
2548+
2549+ int err= poll(&fds, 1, timeout * 1000);
2550+ if (err == 1)
2551+ {
2552+ if (direction == POLLOUT)
2553+ {
2554+ ret= send(fd, buf, len, 0);
2555+ }
2556+ else
2557+ {
2558+ ret= recv(fd, buf, len, 0);
2559+ }
2560+ }
2561+ else if (err == 0)
2562+ {
2563+ errno= ETIMEDOUT;
2564+ }
2565+ else
2566+ {
2567+ perror("Failed to poll");
2568+ return -1;
2569+ }
2570+ }
2571+
2572+ return ret;
2573+}
2574+
2575+/**
2576+ * Ensure that an expression is true. If it isn't print out a message similar
2577+ * to assert() and create a coredump if the user wants that. If not an error
2578+ * message is returned.
2579+ *
2580+ */
2581+static enum test_return ensure(bool val, const char *expression, const char *file, int line)
2582+{
2583+ if (!val)
2584+ {
2585+ if (verbose)
2586+ fprintf(stderr, "\n%s:%d: %s", file, line, expression);
2587+
2588+ if (do_core)
2589+ abort();
2590+
2591+ return TEST_FAIL;
2592+ }
2593+
2594+ return TEST_PASS;
2595+}
2596+
2597+#define verify(expression) do { if (ensure(expression, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
2598+#define execute(expression) do { if (ensure(expression == TEST_PASS, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
2599+
2600+/**
2601+ * Send a chunk of memory over the socket (retry if the call is iterrupted
2602+ */
2603+static enum test_return retry_write(const void* buf, size_t len)
2604+{
2605+ size_t offset= 0;
2606+ const char* ptr= static_cast<const char *>(buf);
2607+
2608+ do
2609+ {
2610+ size_t num_bytes= len - offset;
2611+ ssize_t nw= timeout_io_op(sock, POLLOUT, (void*)(ptr + offset), num_bytes);
2612+ if (nw == -1)
2613+ verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
2614+ else
2615+ offset+= (size_t)nw;
2616+ } while (offset < len);
2617+
2618+ return TEST_PASS;
2619+}
2620+
2621+/**
2622+ * Resend a packet to the server (All fields in the command header should
2623+ * be in network byte order)
2624+ */
2625+static enum test_return resend_packet(command *cmd)
2626+{
2627+ size_t length= sizeof (protocol_binary_request_no_extras) +
2628+ ntohl(cmd->plain.message.header.request.bodylen);
2629+
2630+ execute(retry_write(cmd, length));
2631+ return TEST_PASS;
2632+}
2633+
2634+/**
2635+ * Send a command to the server. The command header needs to be updated
2636+ * to network byte order
2637+ */
2638+static enum test_return send_packet(command *cmd)
2639+{
2640+ /* Fix the byteorder of the header */
2641+ cmd->plain.message.header.request.keylen=
2642+ ntohs(cmd->plain.message.header.request.keylen);
2643+ cmd->plain.message.header.request.bodylen=
2644+ ntohl(cmd->plain.message.header.request.bodylen);
2645+ cmd->plain.message.header.request.cas=
2646+ memcached_ntohll(cmd->plain.message.header.request.cas);
2647+
2648+ execute(resend_packet(cmd));
2649+ return TEST_PASS;
2650+}
2651+
2652+/**
2653+ * Read a fixed length chunk of data from the server
2654+ */
2655+static enum test_return retry_read(void *buf, size_t len)
2656+{
2657+ size_t offset= 0;
2658+ do
2659+ {
2660+ ssize_t nr= timeout_io_op(sock, POLLIN, ((char*) buf) + offset, len - offset);
2661+ switch (nr) {
2662+ case -1 :
2663+ fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno));
2664+ verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
2665+ break;
2666+ case 0:
2667+ return TEST_FAIL;
2668+ default:
2669+ offset+= (size_t)nr;
2670+ }
2671+ } while (offset < len);
2672+
2673+ return TEST_PASS;
2674+}
2675+
2676+/**
2677+ * Receive a response from the server and conver the fields in the header
2678+ * to local byte order
2679+ */
2680+static enum test_return recv_packet(response *rsp)
2681+{
2682+ execute(retry_read(rsp, sizeof(protocol_binary_response_no_extras)));
2683+
2684+ /* Fix the byte order in the packet header */
2685+ rsp->plain.message.header.response.keylen=
2686+ ntohs(rsp->plain.message.header.response.keylen);
2687+ rsp->plain.message.header.response.status=
2688+ ntohs(rsp->plain.message.header.response.status);
2689+ rsp->plain.message.header.response.bodylen=
2690+ ntohl(rsp->plain.message.header.response.bodylen);
2691+ rsp->plain.message.header.response.cas=
2692+ memcached_ntohll(rsp->plain.message.header.response.cas);
2693+
2694+ size_t bodysz= rsp->plain.message.header.response.bodylen;
2695+ if (bodysz > 0)
2696+ execute(retry_read(rsp->bytes + sizeof (protocol_binary_response_no_extras), bodysz));
2697+
2698+ return TEST_PASS;
2699+}
2700+
2701+/**
2702+ * Create a storage command (add, set, replace etc)
2703+ *
2704+ * @param cmd destination buffer
2705+ * @param cc the storage command to create
2706+ * @param key the key to store
2707+ * @param keylen the length of the key
2708+ * @param dta the data to store with the key
2709+ * @param dtalen the length of the data to store with the key
2710+ * @param flags the flags to store along with the key
2711+ * @param exptime the expiry time for the key
2712+ */
2713+static void storage_command(command *cmd,
2714+ uint8_t cc,
2715+ const void* key,
2716+ size_t keylen,
2717+ const void* dta,
2718+ size_t dtalen,
2719+ uint32_t flags,
2720+ uint32_t exptime)
2721+{
2722+ /* all of the storage commands use the same command layout */
2723+ protocol_binary_request_set *request= &cmd->set;
2724+
2725+ memset(request, 0, sizeof (*request));
2726+ request->message.header.request.magic= PROTOCOL_BINARY_REQ;
2727+ request->message.header.request.opcode= cc;
2728+ request->message.header.request.keylen= (uint16_t)keylen;
2729+ request->message.header.request.extlen= 8;
2730+ request->message.header.request.bodylen= (uint32_t)(keylen + 8 + dtalen);
2731+ request->message.header.request.opaque= 0xdeadbeef;
2732+ request->message.body.flags= flags;
2733+ request->message.body.expiration= exptime;
2734+
2735+ off_t key_offset= sizeof (protocol_binary_request_no_extras) + 8;
2736+ memcpy(cmd->bytes + key_offset, key, keylen);
2737+ if (dta != NULL)
2738+ memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
2739+}
2740+
2741+/**
2742+ * Create a basic command to send to the server
2743+ * @param cmd destination buffer
2744+ * @param cc the command to create
2745+ * @param key the key to store
2746+ * @param keylen the length of the key
2747+ * @param dta the data to store with the key
2748+ * @param dtalen the length of the data to store with the key
2749+ */
2750+static void raw_command(command *cmd,
2751+ uint8_t cc,
2752+ const void* key,
2753+ size_t keylen,
2754+ const void* dta,
2755+ size_t dtalen)
2756+{
2757+ /* all of the storage commands use the same command layout */
2758+ memset(cmd, 0, sizeof (*cmd));
2759+ cmd->plain.message.header.request.magic= PROTOCOL_BINARY_REQ;
2760+ cmd->plain.message.header.request.opcode= cc;
2761+ cmd->plain.message.header.request.keylen= (uint16_t)keylen;
2762+ cmd->plain.message.header.request.bodylen= (uint32_t)(keylen + dtalen);
2763+ cmd->plain.message.header.request.opaque= 0xdeadbeef;
2764+
2765+ off_t key_offset= sizeof (protocol_binary_request_no_extras);
2766+
2767+ if (key != NULL)
2768+ memcpy(cmd->bytes + key_offset, key, keylen);
2769+
2770+ if (dta != NULL)
2771+ memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
2772+}
2773+
2774+/**
2775+ * Create the flush command
2776+ * @param cmd destination buffer
2777+ * @param cc the command to create (FLUSH/FLUSHQ)
2778+ * @param exptime when to flush
2779+ * @param use_extra to force using of the extra field?
2780+ */
2781+static void flush_command(command *cmd,
2782+ uint8_t cc, uint32_t exptime, bool use_extra)
2783+{
2784+ memset(cmd, 0, sizeof (cmd->flush));
2785+ cmd->flush.message.header.request.magic= PROTOCOL_BINARY_REQ;
2786+ cmd->flush.message.header.request.opcode= cc;
2787+ cmd->flush.message.header.request.opaque= 0xdeadbeef;
2788+
2789+ if (exptime != 0 || use_extra)
2790+ {
2791+ cmd->flush.message.header.request.extlen= 4;
2792+ cmd->flush.message.body.expiration= htonl(exptime);
2793+ cmd->flush.message.header.request.bodylen= 4;
2794+ }
2795+}
2796+
2797+/**
2798+ * Create a incr/decr command
2799+ * @param cc the cmd to create (FLUSH/FLUSHQ)
2800+ * @param key the key to operate on
2801+ * @param keylen the number of bytes in the key
2802+ * @param delta the number to add/subtract
2803+ * @param initial the initial value if the key doesn't exist
2804+ * @param exptime when the key should expire if it isn't set
2805+ */
2806+static void arithmetic_command(command *cmd,
2807+ uint8_t cc,
2808+ const void* key,
2809+ size_t keylen,
2810+ uint64_t delta,
2811+ uint64_t initial,
2812+ uint32_t exptime)
2813+{
2814+ memset(cmd, 0, sizeof (cmd->incr));
2815+ cmd->incr.message.header.request.magic= PROTOCOL_BINARY_REQ;
2816+ cmd->incr.message.header.request.opcode= cc;
2817+ cmd->incr.message.header.request.keylen= (uint16_t)keylen;
2818+ cmd->incr.message.header.request.extlen= 20;
2819+ cmd->incr.message.header.request.bodylen= (uint32_t)(keylen + 20);
2820+ cmd->incr.message.header.request.opaque= 0xdeadbeef;
2821+ cmd->incr.message.body.delta= memcached_htonll(delta);
2822+ cmd->incr.message.body.initial= memcached_htonll(initial);
2823+ cmd->incr.message.body.expiration= htonl(exptime);
2824+
2825+ off_t key_offset= sizeof (protocol_binary_request_no_extras) + 20;
2826+ memcpy(cmd->bytes + key_offset, key, keylen);
2827+}
2828+
2829+/**
2830+ * Validate the response header from the server
2831+ * @param rsp the response to check
2832+ * @param cc the expected command
2833+ * @param status the expected status
2834+ */
2835+static enum test_return do_validate_response_header(response *rsp,
2836+ uint8_t cc, uint16_t status)
2837+{
2838+ verify(rsp->plain.message.header.response.magic == PROTOCOL_BINARY_RES);
2839+ verify(rsp->plain.message.header.response.opcode == cc);
2840+ verify(rsp->plain.message.header.response.datatype == PROTOCOL_BINARY_RAW_BYTES);
2841+ verify(rsp->plain.message.header.response.status == status);
2842+ verify(rsp->plain.message.header.response.opaque == 0xdeadbeef);
2843+
2844+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
2845+ {
2846+ switch (cc) {
2847+ case PROTOCOL_BINARY_CMD_ADDQ:
2848+ case PROTOCOL_BINARY_CMD_APPENDQ:
2849+ case PROTOCOL_BINARY_CMD_DECREMENTQ:
2850+ case PROTOCOL_BINARY_CMD_DELETEQ:
2851+ case PROTOCOL_BINARY_CMD_FLUSHQ:
2852+ case PROTOCOL_BINARY_CMD_INCREMENTQ:
2853+ case PROTOCOL_BINARY_CMD_PREPENDQ:
2854+ case PROTOCOL_BINARY_CMD_QUITQ:
2855+ case PROTOCOL_BINARY_CMD_REPLACEQ:
2856+ case PROTOCOL_BINARY_CMD_SETQ:
2857+ verify("Quiet command shouldn't return on success" == NULL);
2858+ default:
2859+ break;
2860+ }
2861+
2862+ switch (cc) {
2863+ case PROTOCOL_BINARY_CMD_ADD:
2864+ case PROTOCOL_BINARY_CMD_REPLACE:
2865+ case PROTOCOL_BINARY_CMD_SET:
2866+ case PROTOCOL_BINARY_CMD_APPEND:
2867+ case PROTOCOL_BINARY_CMD_PREPEND:
2868+ verify(rsp->plain.message.header.response.keylen == 0);
2869+ verify(rsp->plain.message.header.response.extlen == 0);
2870+ verify(rsp->plain.message.header.response.bodylen == 0);
2871+ verify(rsp->plain.message.header.response.cas != 0);
2872+ break;
2873+ case PROTOCOL_BINARY_CMD_FLUSH:
2874+ case PROTOCOL_BINARY_CMD_NOOP:
2875+ case PROTOCOL_BINARY_CMD_QUIT:
2876+ case PROTOCOL_BINARY_CMD_DELETE:
2877+ verify(rsp->plain.message.header.response.keylen == 0);
2878+ verify(rsp->plain.message.header.response.extlen == 0);
2879+ verify(rsp->plain.message.header.response.bodylen == 0);
2880+ verify(rsp->plain.message.header.response.cas == 0);
2881+ break;
2882+
2883+ case PROTOCOL_BINARY_CMD_DECREMENT:
2884+ case PROTOCOL_BINARY_CMD_INCREMENT:
2885+ verify(rsp->plain.message.header.response.keylen == 0);
2886+ verify(rsp->plain.message.header.response.extlen == 0);
2887+ verify(rsp->plain.message.header.response.bodylen == 8);
2888+ verify(rsp->plain.message.header.response.cas != 0);
2889+ break;
2890+
2891+ case PROTOCOL_BINARY_CMD_STAT:
2892+ verify(rsp->plain.message.header.response.extlen == 0);
2893+ /* key and value exists in all packets except in the terminating */
2894+ verify(rsp->plain.message.header.response.cas == 0);
2895+ break;
2896+
2897+ case PROTOCOL_BINARY_CMD_VERSION:
2898+ verify(rsp->plain.message.header.response.keylen == 0);
2899+ verify(rsp->plain.message.header.response.extlen == 0);
2900+ verify(rsp->plain.message.header.response.bodylen != 0);
2901+ verify(rsp->plain.message.header.response.cas == 0);
2902+ break;
2903+
2904+ case PROTOCOL_BINARY_CMD_GET:
2905+ case PROTOCOL_BINARY_CMD_GETQ:
2906+ verify(rsp->plain.message.header.response.keylen == 0);
2907+ verify(rsp->plain.message.header.response.extlen == 4);
2908+ verify(rsp->plain.message.header.response.cas != 0);
2909+ break;
2910+
2911+ case PROTOCOL_BINARY_CMD_GETK:
2912+ case PROTOCOL_BINARY_CMD_GETKQ:
2913+ verify(rsp->plain.message.header.response.keylen != 0);
2914+ verify(rsp->plain.message.header.response.extlen == 4);
2915+ verify(rsp->plain.message.header.response.cas != 0);
2916+ break;
2917+
2918+ default:
2919+ /* Undefined command code */
2920+ break;
2921+ }
2922+ }
2923+ else
2924+ {
2925+ verify(rsp->plain.message.header.response.cas == 0);
2926+ verify(rsp->plain.message.header.response.extlen == 0);
2927+ if (cc != PROTOCOL_BINARY_CMD_GETK)
2928+ {
2929+ verify(rsp->plain.message.header.response.keylen == 0);
2930+ }
2931+ }
2932+
2933+ return TEST_PASS;
2934+}
2935+
2936+/* We call verify(validate_response_header), but that macro
2937+ * expects a boolean expression, and the function returns
2938+ * an enum.... Let's just create a macro to avoid cluttering
2939+ * the code with all of the == TEST_PASS ;-)
2940+ */
2941+#define validate_response_header(a,b,c) \
2942+ do_validate_response_header(a,b,c) == TEST_PASS
2943+
2944+
2945+static enum test_return send_binary_noop(void)
2946+{
2947+ command cmd;
2948+ raw_command(&cmd, PROTOCOL_BINARY_CMD_NOOP, NULL, 0, NULL, 0);
2949+ execute(send_packet(&cmd));
2950+ return TEST_PASS;
2951+}
2952+
2953+static enum test_return receive_binary_noop(void)
2954+{
2955+ response rsp;
2956+ execute(recv_packet(&rsp));
2957+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_NOOP,
2958+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
2959+ return TEST_PASS;
2960+}
2961+
2962+static enum test_return test_binary_noop(void)
2963+{
2964+ execute(send_binary_noop());
2965+ execute(receive_binary_noop());
2966+ return TEST_PASS;
2967+}
2968+
2969+static enum test_return test_binary_quit_impl(uint8_t cc)
2970+{
2971+ command cmd;
2972+ response rsp;
2973+ raw_command(&cmd, cc, NULL, 0, NULL, 0);
2974+
2975+ execute(send_packet(&cmd));
2976+ if (cc == PROTOCOL_BINARY_CMD_QUIT)
2977+ {
2978+ execute(recv_packet(&rsp));
2979+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_QUIT,
2980+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
2981+ }
2982+
2983+ /* Socket should be closed now, read should return EXIT_SUCCESS */
2984+ verify(timeout_io_op(sock, POLLIN, rsp.bytes, sizeof(rsp.bytes)) == 0);
2985+
2986+ return TEST_PASS_RECONNECT;
2987+}
2988+
2989+static enum test_return test_binary_quit(void)
2990+{
2991+ return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUIT);
2992+}
2993+
2994+static enum test_return test_binary_quitq(void)
2995+{
2996+ return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUITQ);
2997+}
2998+
2999+static enum test_return test_binary_set_impl(const char* key, uint8_t cc)
3000+{
3001+ command cmd;
3002+ response rsp;
3003+
3004+ uint64_t value= 0xdeadbeefdeadcafe;
3005+ storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
3006+
3007+ /* set should always work */
3008+ for (int ii= 0; ii < 10; ii++)
3009+ {
3010+ if (ii == 0)
3011+ execute(send_packet(&cmd));
3012+ else
3013+ execute(resend_packet(&cmd));
3014+
3015+ if (cc == PROTOCOL_BINARY_CMD_SET)
3016+ {
3017+ execute(recv_packet(&rsp));
3018+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3019+ }
3020+ else
3021+ execute(test_binary_noop());
3022+ }
3023+
3024+ /*
3025+ * We need to get the current CAS id, and at this time we haven't
3026+ * verified that we have a working get
3027+ */
3028+ if (cc == PROTOCOL_BINARY_CMD_SETQ)
3029+ {
3030+ cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SET;
3031+ execute(resend_packet(&cmd));
3032+ execute(recv_packet(&rsp));
3033+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
3034+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
3035+ cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
3036+ }
3037+
3038+ /* try to set with the correct CAS value */
3039+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
3040+ execute(resend_packet(&cmd));
3041+ if (cc == PROTOCOL_BINARY_CMD_SET)
3042+ {
3043+ execute(recv_packet(&rsp));
3044+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3045+ }
3046+ else
3047+ execute(test_binary_noop());
3048+
3049+ /* try to set with an incorrect CAS value */
3050+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
3051+ execute(resend_packet(&cmd));
3052+ execute(send_binary_noop());
3053+ execute(recv_packet(&rsp));
3054+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
3055+ execute(receive_binary_noop());
3056+
3057+ return TEST_PASS;
3058+}
3059+
3060+static enum test_return test_binary_set(void)
3061+{
3062+ return test_binary_set_impl("test_binary_set", PROTOCOL_BINARY_CMD_SET);
3063+}
3064+
3065+static enum test_return test_binary_setq(void)
3066+{
3067+ return test_binary_set_impl("test_binary_setq", PROTOCOL_BINARY_CMD_SETQ);
3068+}
3069+
3070+static enum test_return test_binary_add_impl(const char* key, uint8_t cc)
3071+{
3072+ command cmd;
3073+ response rsp;
3074+ uint64_t value= 0xdeadbeefdeadcafe;
3075+ storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
3076+
3077+ /* first add should work, rest of them should fail (even with cas
3078+ as wildcard */
3079+ for (int ii=0; ii < 10; ii++)
3080+ {
3081+ if (ii == 0)
3082+ execute(send_packet(&cmd));
3083+ else
3084+ execute(resend_packet(&cmd));
3085+
3086+ if (cc == PROTOCOL_BINARY_CMD_ADD || ii > 0)
3087+ {
3088+ uint16_t expected_result;
3089+ if (ii == 0)
3090+ expected_result= PROTOCOL_BINARY_RESPONSE_SUCCESS;
3091+ else
3092+ expected_result= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS;
3093+
3094+ execute(send_binary_noop());
3095+ execute(recv_packet(&rsp));
3096+ execute(receive_binary_noop());
3097+ verify(validate_response_header(&rsp, cc, expected_result));
3098+ }
3099+ else
3100+ execute(test_binary_noop());
3101+ }
3102+
3103+ return TEST_PASS;
3104+}
3105+
3106+static enum test_return test_binary_add(void)
3107+{
3108+ return test_binary_add_impl("test_binary_add", PROTOCOL_BINARY_CMD_ADD);
3109+}
3110+
3111+static enum test_return test_binary_addq(void)
3112+{
3113+ return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ);
3114+}
3115+
3116+static enum test_return binary_set_item(const char *key, const char *value)
3117+{
3118+ command cmd;
3119+ response rsp;
3120+ storage_command(&cmd, PROTOCOL_BINARY_CMD_SET, key, strlen(key),
3121+ value, strlen(value), 0, 0);
3122+ execute(send_packet(&cmd));
3123+ execute(recv_packet(&rsp));
3124+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
3125+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
3126+ return TEST_PASS;
3127+}
3128+
3129+static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
3130+{
3131+ command cmd;
3132+ response rsp;
3133+ uint64_t value= 0xdeadbeefdeadcafe;
3134+ storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
3135+
3136+ /* first replace should fail, successive should succeed (when the
3137+ item is added! */
3138+ for (int ii= 0; ii < 10; ii++)
3139+ {
3140+ if (ii == 0)
3141+ execute(send_packet(&cmd));
3142+ else
3143+ execute(resend_packet(&cmd));
3144+
3145+ if (cc == PROTOCOL_BINARY_CMD_REPLACE || ii == 0)
3146+ {
3147+ uint16_t expected_result;
3148+ if (ii == 0)
3149+ expected_result=PROTOCOL_BINARY_RESPONSE_KEY_ENOENT;
3150+ else
3151+ expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS;
3152+
3153+ execute(send_binary_noop());
3154+ execute(recv_packet(&rsp));
3155+ execute(receive_binary_noop());
3156+ verify(validate_response_header(&rsp, cc, expected_result));
3157+
3158+ if (ii == 0)
3159+ execute(binary_set_item(key, key));
3160+ }
3161+ else
3162+ execute(test_binary_noop());
3163+ }
3164+
3165+ /* verify that replace with CAS value works! */
3166+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
3167+ execute(resend_packet(&cmd));
3168+
3169+ if (cc == PROTOCOL_BINARY_CMD_REPLACE)
3170+ {
3171+ execute(recv_packet(&rsp));
3172+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3173+ }
3174+ else
3175+ execute(test_binary_noop());
3176+
3177+ /* try to set with an incorrect CAS value */
3178+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
3179+ execute(resend_packet(&cmd));
3180+ execute(send_binary_noop());
3181+ execute(recv_packet(&rsp));
3182+ execute(receive_binary_noop());
3183+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
3184+
3185+ return TEST_PASS;
3186+}
3187+
3188+static enum test_return test_binary_replace(void)
3189+{
3190+ return test_binary_replace_impl("test_binary_replace", PROTOCOL_BINARY_CMD_REPLACE);
3191+}
3192+
3193+static enum test_return test_binary_replaceq(void)
3194+{
3195+ return test_binary_replace_impl("test_binary_replaceq", PROTOCOL_BINARY_CMD_REPLACEQ);
3196+}
3197+
3198+static enum test_return test_binary_delete_impl(const char *key, uint8_t cc)
3199+{
3200+ command cmd;
3201+ response rsp;
3202+ raw_command(&cmd, cc, key, strlen(key), NULL, 0);
3203+
3204+ /* The delete shouldn't work the first time, because the item isn't there */
3205+ execute(send_packet(&cmd));
3206+ execute(send_binary_noop());
3207+ execute(recv_packet(&rsp));
3208+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
3209+ execute(receive_binary_noop());
3210+ execute(binary_set_item(key, key));
3211+
3212+ /* The item should be present now, resend*/
3213+ execute(resend_packet(&cmd));
3214+ if (cc == PROTOCOL_BINARY_CMD_DELETE)
3215+ {
3216+ execute(recv_packet(&rsp));
3217+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3218+ }
3219+
3220+ execute(test_binary_noop());
3221+
3222+ return TEST_PASS;
3223+}
3224+
3225+static enum test_return test_binary_delete(void)
3226+{
3227+ return test_binary_delete_impl("test_binary_delete", PROTOCOL_BINARY_CMD_DELETE);
3228+}
3229+
3230+static enum test_return test_binary_deleteq(void)
3231+{
3232+ return test_binary_delete_impl("test_binary_deleteq", PROTOCOL_BINARY_CMD_DELETEQ);
3233+}
3234+
3235+static enum test_return test_binary_get_impl(const char *key, uint8_t cc)
3236+{
3237+ command cmd;
3238+ response rsp;
3239+
3240+ raw_command(&cmd, cc, key, strlen(key), NULL, 0);
3241+ execute(send_packet(&cmd));
3242+ execute(send_binary_noop());
3243+
3244+ if (cc == PROTOCOL_BINARY_CMD_GET || cc == PROTOCOL_BINARY_CMD_GETK)
3245+ {
3246+ execute(recv_packet(&rsp));
3247+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
3248+ }
3249+
3250+ execute(receive_binary_noop());
3251+
3252+ execute(binary_set_item(key, key));
3253+ execute(resend_packet(&cmd));
3254+ execute(send_binary_noop());
3255+
3256+ execute(recv_packet(&rsp));
3257+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3258+ execute(receive_binary_noop());
3259+
3260+ return TEST_PASS;
3261+}
3262+
3263+static enum test_return test_binary_get(void)
3264+{
3265+ return test_binary_get_impl("test_binary_get", PROTOCOL_BINARY_CMD_GET);
3266+}
3267+
3268+static enum test_return test_binary_getk(void)
3269+{
3270+ return test_binary_get_impl("test_binary_getk", PROTOCOL_BINARY_CMD_GETK);
3271+}
3272+
3273+static enum test_return test_binary_getq(void)
3274+{
3275+ return test_binary_get_impl("test_binary_getq", PROTOCOL_BINARY_CMD_GETQ);
3276+}
3277+
3278+static enum test_return test_binary_getkq(void)
3279+{
3280+ return test_binary_get_impl("test_binary_getkq", PROTOCOL_BINARY_CMD_GETKQ);
3281+}
3282+
3283+static enum test_return test_binary_incr_impl(const char* key, uint8_t cc)
3284+{
3285+ command cmd;
3286+ response rsp;
3287+ arithmetic_command(&cmd, cc, key, strlen(key), 1, 0, 0);
3288+
3289+ uint64_t ii;
3290+ for (ii= 0; ii < 10; ++ii)
3291+ {
3292+ if (ii == 0)
3293+ execute(send_packet(&cmd));
3294+ else
3295+ execute(resend_packet(&cmd));
3296+
3297+ if (cc == PROTOCOL_BINARY_CMD_INCREMENT)
3298+ {
3299+ execute(recv_packet(&rsp));
3300+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3301+ verify(memcached_ntohll(rsp.incr.message.body.value) == ii);
3302+ }
3303+ else
3304+ execute(test_binary_noop());
3305+ }
3306+
3307+ /* @todo add incorrect CAS */
3308+ return TEST_PASS;
3309+}
3310+
3311+static enum test_return test_binary_incr(void)
3312+{
3313+ return test_binary_incr_impl("test_binary_incr", PROTOCOL_BINARY_CMD_INCREMENT);
3314+}
3315+
3316+static enum test_return test_binary_incrq(void)
3317+{
3318+ return test_binary_incr_impl("test_binary_incrq", PROTOCOL_BINARY_CMD_INCREMENTQ);
3319+}
3320+
3321+static enum test_return test_binary_decr_impl(const char* key, uint8_t cc)
3322+{
3323+ command cmd;
3324+ response rsp;
3325+ arithmetic_command(&cmd, cc, key, strlen(key), 1, 9, 0);
3326+
3327+ int ii;
3328+ for (ii= 9; ii > -1; --ii)
3329+ {
3330+ if (ii == 9)
3331+ execute(send_packet(&cmd));
3332+ else
3333+ execute(resend_packet(&cmd));
3334+
3335+ if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
3336+ {
3337+ execute(recv_packet(&rsp));
3338+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3339+ verify(memcached_ntohll(rsp.decr.message.body.value) == (uint64_t)ii);
3340+ }
3341+ else
3342+ execute(test_binary_noop());
3343+ }
3344+
3345+ /* decr 0 should not wrap */
3346+ execute(resend_packet(&cmd));
3347+ if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
3348+ {
3349+ execute(recv_packet(&rsp));
3350+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3351+ verify(memcached_ntohll(rsp.decr.message.body.value) == 0);
3352+ }
3353+ else
3354+ {
3355+ /* @todo get the value and verify! */
3356+
3357+ }
3358+
3359+ /* @todo add incorrect cas */
3360+ execute(test_binary_noop());
3361+ return TEST_PASS;
3362+}
3363+
3364+static enum test_return test_binary_decr(void)
3365+{
3366+ return test_binary_decr_impl("test_binary_decr",
3367+ PROTOCOL_BINARY_CMD_DECREMENT);
3368+}
3369+
3370+static enum test_return test_binary_decrq(void)
3371+{
3372+ return test_binary_decr_impl("test_binary_decrq",
3373+ PROTOCOL_BINARY_CMD_DECREMENTQ);
3374+}
3375+
3376+static enum test_return test_binary_version(void)
3377+{
3378+ command cmd;
3379+ response rsp;
3380+ raw_command(&cmd, PROTOCOL_BINARY_CMD_VERSION, NULL, 0, NULL, 0);
3381+
3382+ execute(send_packet(&cmd));
3383+ execute(recv_packet(&rsp));
3384+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_VERSION,
3385+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
3386+
3387+ return TEST_PASS;
3388+}
3389+
3390+static enum test_return test_binary_flush_impl(const char *key, uint8_t cc)
3391+{
3392+ command cmd;
3393+ response rsp;
3394+
3395+ for (int ii= 0; ii < 2; ++ii)
3396+ {
3397+ execute(binary_set_item(key, key));
3398+ flush_command(&cmd, cc, 0, ii == 0);
3399+ execute(send_packet(&cmd));
3400+
3401+ if (cc == PROTOCOL_BINARY_CMD_FLUSH)
3402+ {
3403+ execute(recv_packet(&rsp));
3404+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3405+ }
3406+ else
3407+ execute(test_binary_noop());
3408+
3409+ raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
3410+ execute(send_packet(&cmd));
3411+ execute(recv_packet(&rsp));
3412+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
3413+ PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
3414+ }
3415+
3416+ return TEST_PASS;
3417+}
3418+
3419+static enum test_return test_binary_flush(void)
3420+{
3421+ return test_binary_flush_impl("test_binary_flush", PROTOCOL_BINARY_CMD_FLUSH);
3422+}
3423+
3424+static enum test_return test_binary_flushq(void)
3425+{
3426+ return test_binary_flush_impl("test_binary_flushq", PROTOCOL_BINARY_CMD_FLUSHQ);
3427+}
3428+
3429+static enum test_return test_binary_concat_impl(const char *key, uint8_t cc)
3430+{
3431+ command cmd;
3432+ response rsp;
3433+ const char *value;
3434+
3435+ if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
3436+ value="hello";
3437+ else
3438+ value=" world";
3439+
3440+ execute(binary_set_item(key, value));
3441+
3442+ if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
3443+ value=" world";
3444+ else
3445+ value="hello";
3446+
3447+ raw_command(&cmd, cc, key, strlen(key), value, strlen(value));
3448+ execute(send_packet(&cmd));
3449+ if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_PREPEND)
3450+ {
3451+ execute(recv_packet(&rsp));
3452+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
3453+ }
3454+ else
3455+ execute(test_binary_noop());
3456+
3457+ raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
3458+ execute(send_packet(&cmd));
3459+ execute(recv_packet(&rsp));
3460+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
3461+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
3462+ verify(rsp.plain.message.header.response.bodylen - 4 == 11);
3463+ verify(memcmp(rsp.bytes + 28, "hello world", 11) == 0);
3464+
3465+ return TEST_PASS;
3466+}
3467+
3468+static enum test_return test_binary_append(void)
3469+{
3470+ return test_binary_concat_impl("test_binary_append", PROTOCOL_BINARY_CMD_APPEND);
3471+}
3472+
3473+static enum test_return test_binary_prepend(void)
3474+{
3475+ return test_binary_concat_impl("test_binary_prepend", PROTOCOL_BINARY_CMD_PREPEND);
3476+}
3477+
3478+static enum test_return test_binary_appendq(void)
3479+{
3480+ return test_binary_concat_impl("test_binary_appendq", PROTOCOL_BINARY_CMD_APPENDQ);
3481+}
3482+
3483+static enum test_return test_binary_prependq(void)
3484+{
3485+ return test_binary_concat_impl("test_binary_prependq", PROTOCOL_BINARY_CMD_PREPENDQ);
3486+}
3487+
3488+static enum test_return test_binary_stat(void)
3489+{
3490+ command cmd;
3491+ response rsp;
3492+
3493+ raw_command(&cmd, PROTOCOL_BINARY_CMD_STAT, NULL, 0, NULL, 0);
3494+ execute(send_packet(&cmd));
3495+
3496+ do
3497+ {
3498+ execute(recv_packet(&rsp));
3499+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_STAT,
3500+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
3501+ } while (rsp.plain.message.header.response.keylen != 0);
3502+
3503+ return TEST_PASS;
3504+}
3505+
3506+static enum test_return send_string(const char *cmd)
3507+{
3508+ execute(retry_write(cmd, strlen(cmd)));
3509+ return TEST_PASS;
3510+}
3511+
3512+static enum test_return receive_line(char *buffer, size_t size)
3513+{
3514+ size_t offset= 0;
3515+ while (offset < size)
3516+ {
3517+ execute(retry_read(buffer + offset, 1));
3518+ if (buffer[offset] == '\n')
3519+ {
3520+ if (offset + 1 < size)
3521+ {
3522+ buffer[offset + 1]= '\0';
3523+ return TEST_PASS;
3524+ }
3525+ else
3526+ return TEST_FAIL;
3527+ }
3528+ ++offset;
3529+ }
3530+
3531+ return TEST_FAIL;
3532+}
3533+
3534+static enum test_return receive_response(const char *msg) {
3535+ char buffer[80];
3536+ execute(receive_line(buffer, sizeof(buffer)));
3537+ if (strcmp(msg, buffer) != 0) {
3538+ fprintf(stderr, "[%s]\n", buffer);
3539+ }
3540+ verify(strcmp(msg, buffer) == 0);
3541+ return TEST_PASS;
3542+}
3543+
3544+static enum test_return receive_error_response(void)
3545+{
3546+ char buffer[80];
3547+ execute(receive_line(buffer, sizeof(buffer)));
3548+ verify(strncmp(buffer, "ERROR", 5) == 0 ||
3549+ strncmp(buffer, "CLIENT_ERROR", 12) == 0 ||
3550+ strncmp(buffer, "SERVER_ERROR", 12) == 0);
3551+ return TEST_PASS;
3552+}
3553+
3554+static enum test_return test_ascii_quit(void)
3555+{
3556+ /* Verify that quit handles unknown options */
3557+ execute(send_string("quit foo bar\r\n"));
3558+ execute(receive_error_response());
3559+
3560+ /* quit doesn't support noreply */
3561+ execute(send_string("quit noreply\r\n"));
3562+ execute(receive_error_response());
3563+
3564+ /* Verify that quit works */
3565+ execute(send_string("quit\r\n"));
3566+
3567+ /* Socket should be closed now, read should return EXIT_SUCCESS */
3568+ char buffer[80];
3569+ verify(timeout_io_op(sock, POLLIN, buffer, sizeof(buffer)) == 0);
3570+ return TEST_PASS_RECONNECT;
3571+
3572+}
3573+
3574+static enum test_return test_ascii_version(void)
3575+{
3576+ /* Verify that version command handles unknown options */
3577+ execute(send_string("version foo bar\r\n"));
3578+ execute(receive_error_response());
3579+
3580+ /* version doesn't support noreply */
3581+ execute(send_string("version noreply\r\n"));
3582+ execute(receive_error_response());
3583+
3584+ /* Verify that verify works */
3585+ execute(send_string("version\r\n"));
3586+ char buffer[256];
3587+ execute(receive_line(buffer, sizeof(buffer)));
3588+ verify(strncmp(buffer, "VERSION ", 8) == 0);
3589+
3590+ return TEST_PASS;
3591+}
3592+
3593+static enum test_return test_ascii_verbosity(void)
3594+{
3595+ /* This command does not adhere to the spec! */
3596+ execute(send_string("verbosity foo bar my\r\n"));
3597+ execute(receive_error_response());
3598+
3599+ execute(send_string("verbosity noreply\r\n"));
3600+ execute(receive_error_response());
3601+
3602+ execute(send_string("verbosity 0 noreply\r\n"));
3603+ execute(test_ascii_version());
3604+
3605+ execute(send_string("verbosity\r\n"));
3606+ execute(receive_error_response());
3607+
3608+ execute(send_string("verbosity 1\r\n"));
3609+ execute(receive_response("OK\r\n"));
3610+
3611+ execute(send_string("verbosity 0\r\n"));
3612+ execute(receive_response("OK\r\n"));
3613+
3614+ return TEST_PASS;
3615+}
3616+
3617+
3618+
3619+static enum test_return test_ascii_set_impl(const char* key, bool noreply)
3620+{
3621+ /* @todo add tests for bogus format! */
3622+ char buffer[1024];
3623+ snprintf(buffer, sizeof(buffer), "set %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
3624+ execute(send_string(buffer));
3625+
3626+ if (!noreply)
3627+ execute(receive_response("STORED\r\n"));
3628+
3629+ return test_ascii_version();
3630+}
3631+
3632+static enum test_return test_ascii_set(void)
3633+{
3634+ return test_ascii_set_impl("test_ascii_set", false);
3635+}
3636+
3637+static enum test_return test_ascii_set_noreply(void)
3638+{
3639+ return test_ascii_set_impl("test_ascii_set_noreply", true);
3640+}
3641+
3642+static enum test_return test_ascii_add_impl(const char* key, bool noreply)
3643+{
3644+ /* @todo add tests for bogus format! */
3645+ char buffer[1024];
3646+ snprintf(buffer, sizeof(buffer), "add %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
3647+ execute(send_string(buffer));
3648+
3649+ if (!noreply)
3650+ execute(receive_response("STORED\r\n"));
3651+
3652+ execute(send_string(buffer));
3653+
3654+ if (!noreply)
3655+ execute(receive_response("NOT_STORED\r\n"));
3656+
3657+ return test_ascii_version();
3658+}
3659+
3660+static enum test_return test_ascii_add(void)
3661+{
3662+ return test_ascii_add_impl("test_ascii_add", false);
3663+}
3664+
3665+static enum test_return test_ascii_add_noreply(void)
3666+{
3667+ return test_ascii_add_impl("test_ascii_add_noreply", true);
3668+}
3669+
3670+static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_t *ndata)
3671+{
3672+ char buffer[1024];
3673+
3674+ execute(receive_line(buffer, sizeof(buffer)));
3675+ verify(strncmp(buffer, "VALUE ", 6) == 0);
3676+ char *end= strchr(buffer + 6, ' ');
3677+ verify(end != NULL);
3678+ *end= '\0';
3679+ *key= strdup(buffer + 6);
3680+ verify(*key != NULL);
3681+ char *ptr= end + 1;
3682+
3683+ unsigned long val= strtoul(ptr, &end, 10); /* flags */
3684+ verify(ptr != end);
3685+ verify(val == 0);
3686+ verify(end != NULL);
3687+ *ndata = (ssize_t)strtoul(end, &end, 10); /* size */
3688+ verify(ptr != end);
3689+ verify(end != NULL);
3690+ while (*end != '\n' && isspace(*end))
3691+ ++end;
3692+ verify(*end == '\n');
3693+
3694+ *value= static_cast<char*>(malloc((size_t)*ndata));
3695+ verify(*value != NULL);
3696+
3697+ execute(retry_read(*value, (size_t)*ndata));
3698+
3699+ execute(retry_read(buffer, 2));
3700+ verify(memcmp(buffer, "\r\n", 2) == 0);
3701+
3702+ return TEST_PASS;
3703+}
3704+
3705+static enum test_return ascii_get_value(const char *key, const char *value)
3706+{
3707+
3708+ char buffer[1024];
3709+ size_t datasize= strlen(value);
3710+
3711+ verify(datasize < sizeof(buffer));
3712+ execute(receive_line(buffer, sizeof(buffer)));
3713+ verify(strncmp(buffer, "VALUE ", 6) == 0);
3714+ verify(strncmp(buffer + 6, key, strlen(key)) == 0);
3715+ char *ptr= buffer + 6 + strlen(key) + 1;
3716+ char *end;
3717+
3718+ unsigned long val= strtoul(ptr, &end, 10); /* flags */
3719+ verify(ptr != end);
3720+ verify(val == 0);
3721+ verify(end != NULL);
3722+ val= strtoul(end, &end, 10); /* size */
3723+ verify(ptr != end);
3724+ verify(val == datasize);
3725+ verify(end != NULL);
3726+ while (*end != '\n' && isspace(*end))
3727+ ++end;
3728+ verify(*end == '\n');
3729+
3730+ execute(retry_read(buffer, datasize));
3731+ verify(memcmp(buffer, value, datasize) == 0);
3732+
3733+ execute(retry_read(buffer, 2));
3734+ verify(memcmp(buffer, "\r\n", 2) == 0);
3735+
3736+ return TEST_PASS;
3737+}
3738+
3739+static enum test_return ascii_get_item(const char *key, const char *value,
3740+ bool exist)
3741+{
3742+ char buffer[1024];
3743+ size_t datasize= 0;
3744+ if (value != NULL)
3745+ datasize= strlen(value);
3746+
3747+ verify(datasize < sizeof(buffer));
3748+ snprintf(buffer, sizeof(buffer), "get %s\r\n", key);
3749+ execute(send_string(buffer));
3750+
3751+ if (exist)
3752+ execute(ascii_get_value(key, value));
3753+
3754+ execute(retry_read(buffer, 5));
3755+ verify(memcmp(buffer, "END\r\n", 5) == 0);
3756+
3757+ return TEST_PASS;
3758+}
3759+
3760+static enum test_return ascii_gets_value(const char *key, const char *value,
3761+ unsigned long *cas)
3762+{
3763+
3764+ char buffer[1024];
3765+ size_t datasize= strlen(value);
3766+
3767+ verify(datasize < sizeof(buffer));
3768+ execute(receive_line(buffer, sizeof(buffer)));
3769+ verify(strncmp(buffer, "VALUE ", 6) == 0);
3770+ verify(strncmp(buffer + 6, key, strlen(key)) == 0);
3771+ char *ptr= buffer + 6 + strlen(key) + 1;
3772+ char *end;
3773+
3774+ unsigned long val= strtoul(ptr, &end, 10); /* flags */
3775+ verify(ptr != end);
3776+ verify(val == 0);
3777+ verify(end != NULL);
3778+ val= strtoul(end, &end, 10); /* size */
3779+ verify(ptr != end);
3780+ verify(val == datasize);
3781+ verify(end != NULL);
3782+ *cas= strtoul(end, &end, 10); /* cas */
3783+ verify(ptr != end);
3784+ verify(val == datasize);
3785+ verify(end != NULL);
3786+
3787+ while (*end != '\n' && isspace(*end))
3788+ ++end;
3789+ verify(*end == '\n');
3790+
3791+ execute(retry_read(buffer, datasize));
3792+ verify(memcmp(buffer, value, datasize) == 0);
3793+
3794+ execute(retry_read(buffer, 2));
3795+ verify(memcmp(buffer, "\r\n", 2) == 0);
3796+
3797+ return TEST_PASS;
3798+}
3799+
3800+static enum test_return ascii_gets_item(const char *key, const char *value,
3801+ bool exist, unsigned long *cas)
3802+{
3803+ char buffer[1024];
3804+ size_t datasize= 0;
3805+ if (value != NULL)
3806+ datasize= strlen(value);
3807+
3808+ verify(datasize < sizeof(buffer));
3809+ snprintf(buffer, sizeof(buffer), "gets %s\r\n", key);
3810+ execute(send_string(buffer));
3811+
3812+ if (exist)
3813+ execute(ascii_gets_value(key, value, cas));
3814+
3815+ execute(retry_read(buffer, 5));
3816+ verify(memcmp(buffer, "END\r\n", 5) == 0);
3817+
3818+ return TEST_PASS;
3819+}
3820+
3821+static enum test_return ascii_set_item(const char *key, const char *value)
3822+{
3823+ char buffer[300];
3824+ size_t len= strlen(value);
3825+ snprintf(buffer, sizeof(buffer), "set %s 0 0 %u\r\n", key, (unsigned int)len);
3826+ execute(send_string(buffer));
3827+ execute(retry_write(value, len));
3828+ execute(send_string("\r\n"));
3829+ execute(receive_response("STORED\r\n"));
3830+ return TEST_PASS;
3831+}
3832+
3833+static enum test_return test_ascii_replace_impl(const char* key, bool noreply)
3834+{
3835+ char buffer[1024];
3836+ snprintf(buffer, sizeof(buffer), "replace %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
3837+ execute(send_string(buffer));
3838+
3839+ if (noreply)
3840+ execute(test_ascii_version());
3841+ else
3842+ execute(receive_response("NOT_STORED\r\n"));
3843+
3844+ execute(ascii_set_item(key, "value"));
3845+ execute(ascii_get_item(key, "value", true));
3846+
3847+
3848+ execute(send_string(buffer));
3849+
3850+ if (noreply)
3851+ execute(test_ascii_version());
3852+ else
3853+ execute(receive_response("STORED\r\n"));
3854+
3855+ return test_ascii_version();
3856+}
3857+
3858+static enum test_return test_ascii_replace(void)
3859+{
3860+ return test_ascii_replace_impl("test_ascii_replace", false);
3861+}
3862+
3863+static enum test_return test_ascii_replace_noreply(void)
3864+{
3865+ return test_ascii_replace_impl("test_ascii_replace_noreply", true);
3866+}
3867+
3868+static enum test_return test_ascii_cas_impl(const char* key, bool noreply)
3869+{
3870+ char buffer[1024];
3871+ unsigned long cas;
3872+
3873+ execute(ascii_set_item(key, "value"));
3874+ execute(ascii_gets_item(key, "value", true, &cas));
3875+
3876+ snprintf(buffer, sizeof(buffer), "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, noreply ? " noreply" : "");
3877+ execute(send_string(buffer));
3878+
3879+ if (noreply)
3880+ execute(test_ascii_version());
3881+ else
3882+ execute(receive_response("STORED\r\n"));
3883+
3884+ /* reexecute the same command should fail due to illegal cas */
3885+ execute(send_string(buffer));
3886+
3887+ if (noreply)
3888+ execute(test_ascii_version());
3889+ else
3890+ execute(receive_response("EXISTS\r\n"));
3891+
3892+ return test_ascii_version();
3893+}
3894+
3895+static enum test_return test_ascii_cas(void)
3896+{
3897+ return test_ascii_cas_impl("test_ascii_cas", false);
3898+}
3899+
3900+static enum test_return test_ascii_cas_noreply(void)
3901+{
3902+ return test_ascii_cas_impl("test_ascii_cas_noreply", true);
3903+}
3904+
3905+static enum test_return test_ascii_delete_impl(const char *key, bool noreply)
3906+{
3907+ execute(ascii_set_item(key, "value"));
3908+
3909+ execute(send_string("delete\r\n"));
3910+ execute(receive_error_response());
3911+ /* BUG: the server accepts delete a b */
3912+ execute(send_string("delete a b c d e\r\n"));
3913+ execute(receive_error_response());
3914+
3915+ char buffer[1024];
3916+ snprintf(buffer, sizeof(buffer), "delete %s%s\r\n", key, noreply ? " noreply" : "");
3917+ execute(send_string(buffer));
3918+
3919+ if (noreply)
3920+ execute(test_ascii_version());
3921+ else
3922+ execute(receive_response("DELETED\r\n"));
3923+
3924+ execute(ascii_get_item(key, "value", false));
3925+ execute(send_string(buffer));
3926+ if (noreply)
3927+ execute(test_ascii_version());
3928+ else
3929+ execute(receive_response("NOT_FOUND\r\n"));
3930+
3931+ return TEST_PASS;
3932+}
3933+
3934+static enum test_return test_ascii_delete(void)
3935+{
3936+ return test_ascii_delete_impl("test_ascii_delete", false);
3937+}
3938+
3939+static enum test_return test_ascii_delete_noreply(void)
3940+{
3941+ return test_ascii_delete_impl("test_ascii_delete_noreply", true);
3942+}
3943+
3944+static enum test_return test_ascii_get(void)
3945+{
3946+ execute(ascii_set_item("test_ascii_get", "value"));
3947+
3948+ execute(send_string("get\r\n"));
3949+ execute(receive_error_response());
3950+ execute(ascii_get_item("test_ascii_get", "value", true));
3951+ execute(ascii_get_item("test_ascii_get_notfound", "value", false));
3952+
3953+ return TEST_PASS;
3954+}
3955+
3956+static enum test_return test_ascii_gets(void)
3957+{
3958+ execute(ascii_set_item("test_ascii_gets", "value"));
3959+
3960+ execute(send_string("gets\r\n"));
3961+ execute(receive_error_response());
3962+ unsigned long cas;
3963+ execute(ascii_gets_item("test_ascii_gets", "value", true, &cas));
3964+ execute(ascii_gets_item("test_ascii_gets_notfound", "value", false, &cas));
3965+
3966+ return TEST_PASS;
3967+}
3968+
3969+static enum test_return test_ascii_mget(void)
3970+{
3971+ const uint32_t nkeys= 5;
3972+ const char * const keys[]= {
3973+ "test_ascii_mget1",
3974+ "test_ascii_mget2",
3975+ /* test_ascii_mget_3 does not exist :) */
3976+ "test_ascii_mget4",
3977+ "test_ascii_mget5",
3978+ "test_ascii_mget6"
3979+ };
3980+
3981+ for (uint32_t x= 0; x < nkeys; ++x)
3982+ execute(ascii_set_item(keys[x], "value"));
3983+
3984+ /* Ask for a key that doesn't exist as well */
3985+ execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 "
3986+ "test_ascii_mget4 test_ascii_mget5 "
3987+ "test_ascii_mget6\r\n"));
3988+
3989+ char *returned[nkeys];
3990+
3991+ for (uint32_t x= 0; x < nkeys; ++x)
3992+ {
3993+ ssize_t nbytes = 0;
3994+ char *v= NULL;
3995+ execute(ascii_get_unknown_value(&returned[x], &v, &nbytes));
3996+ verify(nbytes == 5);
3997+ verify(memcmp(v, "value", 5) == 0);
3998+ free(v);
3999+ }
4000+
4001+ char buffer[5];
4002+ execute(retry_read(buffer, 5));
4003+ verify(memcmp(buffer, "END\r\n", 5) == 0);
4004+
4005+ /* verify that we got all the keys we expected */
4006+ for (uint32_t x= 0; x < nkeys; ++x)
4007+ {
4008+ bool found= false;
4009+ for (uint32_t y= 0; y < nkeys; ++y)
4010+ {
4011+ if (strcmp(keys[x], returned[y]) == 0)
4012+ {
4013+ found = true;
4014+ break;
4015+ }
4016+ }
4017+ verify(found);
4018+ }
4019+
4020+ for (uint32_t x= 0; x < nkeys; ++x)
4021+ free(returned[x]);
4022+
4023+ return TEST_PASS;
4024+}
4025+
4026+static enum test_return test_ascii_incr_impl(const char* key, bool noreply)
4027+{
4028+ char cmd[300];
4029+ snprintf(cmd, sizeof(cmd), "incr %s 1%s\r\n", key, noreply ? " noreply" : "");
4030+
4031+ execute(ascii_set_item(key, "0"));
4032+ for (int x= 1; x < 11; ++x)
4033+ {
4034+ execute(send_string(cmd));
4035+
4036+ if (noreply)
4037+ execute(test_ascii_version());
4038+ else
4039+ {
4040+ char buffer[80];
4041+ execute(receive_line(buffer, sizeof(buffer)));
4042+ int val= atoi(buffer);
4043+ verify(val == x);
4044+ }
4045+ }
4046+
4047+ execute(ascii_get_item(key, "10", true));
4048+
4049+ return TEST_PASS;
4050+}
4051+
4052+static enum test_return test_ascii_incr(void)
4053+{
4054+ return test_ascii_incr_impl("test_ascii_incr", false);
4055+}
4056+
4057+static enum test_return test_ascii_incr_noreply(void)
4058+{
4059+ return test_ascii_incr_impl("test_ascii_incr_noreply", true);
4060+}
4061+
4062+static enum test_return test_ascii_decr_impl(const char* key, bool noreply)
4063+{
4064+ char cmd[300];
4065+ snprintf(cmd, sizeof(cmd), "decr %s 1%s\r\n", key, noreply ? " noreply" : "");
4066+
4067+ execute(ascii_set_item(key, "9"));
4068+ for (int x= 8; x > -1; --x)
4069+ {
4070+ execute(send_string(cmd));
4071+
4072+ if (noreply)
4073+ execute(test_ascii_version());
4074+ else
4075+ {
4076+ char buffer[80];
4077+ execute(receive_line(buffer, sizeof(buffer)));
4078+ int val= atoi(buffer);
4079+ verify(val == x);
4080+ }
4081+ }
4082+
4083+ execute(ascii_get_item(key, "0", true));
4084+
4085+ /* verify that it doesn't wrap */
4086+ execute(send_string(cmd));
4087+ if (noreply)
4088+ execute(test_ascii_version());
4089+ else
4090+ {
4091+ char buffer[80];
4092+ execute(receive_line(buffer, sizeof(buffer)));
4093+ }
4094+ execute(ascii_get_item(key, "0", true));
4095+
4096+ return TEST_PASS;
4097+}
4098+
4099+static enum test_return test_ascii_decr(void)
4100+{
4101+ return test_ascii_decr_impl("test_ascii_decr", false);
4102+}
4103+
4104+static enum test_return test_ascii_decr_noreply(void)
4105+{
4106+ return test_ascii_decr_impl("test_ascii_decr_noreply", true);
4107+}
4108+
4109+
4110+static enum test_return test_ascii_flush_impl(const char *key, bool noreply)
4111+{
4112+#if 0
4113+ /* Verify that the flush_all command handles unknown options */
4114+ /* Bug in the current memcached server! */
4115+ execute(send_string("flush_all foo bar\r\n"));
4116+ execute(receive_error_response());
4117+#endif
4118+
4119+ execute(ascii_set_item(key, key));
4120+ execute(ascii_get_item(key, key, true));
4121+
4122+ if (noreply)
4123+ {
4124+ execute(send_string("flush_all noreply\r\n"));
4125+ execute(test_ascii_version());
4126+ }
4127+ else
4128+ {
4129+ execute(send_string("flush_all\r\n"));
4130+ execute(receive_response("OK\r\n"));
4131+ }
4132+
4133+ execute(ascii_get_item(key, key, false));
4134+
4135+ return TEST_PASS;
4136+}
4137+
4138+static enum test_return test_ascii_flush(void)
4139+{
4140+ return test_ascii_flush_impl("test_ascii_flush", false);
4141+}
4142+
4143+static enum test_return test_ascii_flush_noreply(void)
4144+{
4145+ return test_ascii_flush_impl("test_ascii_flush_noreply", true);
4146+}
4147+
4148+static enum test_return test_ascii_concat_impl(const char *key,
4149+ bool append,
4150+ bool noreply)
4151+{
4152+ const char *value;
4153+
4154+ if (append)
4155+ value="hello";
4156+ else
4157+ value=" world";
4158+
4159+ execute(ascii_set_item(key, value));
4160+
4161+ if (append)
4162+ value=" world";
4163+ else
4164+ value="hello";
4165+
4166+ char cmd[400];
4167+ snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n",
4168+ append ? "append" : "prepend",
4169+ key, (unsigned int)strlen(value), noreply ? " noreply" : "",
4170+ value);
4171+ execute(send_string(cmd));
4172+
4173+ if (noreply)
4174+ execute(test_ascii_version());
4175+ else
4176+ execute(receive_response("STORED\r\n"));
4177+
4178+ execute(ascii_get_item(key, "hello world", true));
4179+
4180+ snprintf(cmd, sizeof(cmd), "%s %s_notfound 0 0 %u%s\r\n%s\r\n",
4181+ append ? "append" : "prepend",
4182+ key, (unsigned int)strlen(value), noreply ? " noreply" : "",
4183+ value);
4184+ execute(send_string(cmd));
4185+
4186+ if (noreply)
4187+ execute(test_ascii_version());
4188+ else
4189+ execute(receive_response("NOT_STORED\r\n"));
4190+
4191+ return TEST_PASS;
4192+}
4193+
4194+static enum test_return test_ascii_append(void)
4195+{
4196+ return test_ascii_concat_impl("test_ascii_append", true, false);
4197+}
4198+
4199+static enum test_return test_ascii_prepend(void)
4200+{
4201+ return test_ascii_concat_impl("test_ascii_prepend", false, false);
4202+}
4203+
4204+static enum test_return test_ascii_append_noreply(void)
4205+{
4206+ return test_ascii_concat_impl("test_ascii_append_noreply", true, true);
4207+}
4208+
4209+static enum test_return test_ascii_prepend_noreply(void)
4210+{
4211+ return test_ascii_concat_impl("test_ascii_prepend_noreply", false, true);
4212+}
4213+
4214+static enum test_return test_ascii_stat(void)
4215+{
4216+ execute(send_string("stats noreply\r\n"));
4217+ execute(receive_error_response());
4218+ execute(send_string("stats\r\n"));
4219+ char buffer[1024];
4220+ do {
4221+ execute(receive_line(buffer, sizeof(buffer)));
4222+ } while (strcmp(buffer, "END\r\n") != 0);
4223+
4224+ return TEST_PASS_RECONNECT;
4225+}
4226+
4227+typedef enum test_return(*TEST_FUNC)(void);
4228+
4229+struct testcase
4230+{
4231+ const char *description;
4232+ TEST_FUNC function;
4233+};
4234+
4235+struct testcase testcases[]= {
4236+ { "ascii quit", test_ascii_quit },
4237+ { "ascii version", test_ascii_version },
4238+ { "ascii verbosity", test_ascii_verbosity },
4239+ { "ascii set", test_ascii_set },
4240+ { "ascii set noreply", test_ascii_set_noreply },
4241+ { "ascii get", test_ascii_get },
4242+ { "ascii gets", test_ascii_gets },
4243+ { "ascii mget", test_ascii_mget },
4244+ { "ascii flush", test_ascii_flush },
4245+ { "ascii flush noreply", test_ascii_flush_noreply },
4246+ { "ascii add", test_ascii_add },
4247+ { "ascii add noreply", test_ascii_add_noreply },
4248+ { "ascii replace", test_ascii_replace },
4249+ { "ascii replace noreply", test_ascii_replace_noreply },
4250+ { "ascii cas", test_ascii_cas },
4251+ { "ascii cas noreply", test_ascii_cas_noreply },
4252+ { "ascii delete", test_ascii_delete },
4253+ { "ascii delete noreply", test_ascii_delete_noreply },
4254+ { "ascii incr", test_ascii_incr },
4255+ { "ascii incr noreply", test_ascii_incr_noreply },
4256+ { "ascii decr", test_ascii_decr },
4257+ { "ascii decr noreply", test_ascii_decr_noreply },
4258+ { "ascii append", test_ascii_append },
4259+ { "ascii append noreply", test_ascii_append_noreply },
4260+ { "ascii prepend", test_ascii_prepend },
4261+ { "ascii prepend noreply", test_ascii_prepend_noreply },
4262+ { "ascii stat", test_ascii_stat },
4263+ { "binary noop", test_binary_noop },
4264+ { "binary quit", test_binary_quit },
4265+ { "binary quitq", test_binary_quitq },
4266+ { "binary set", test_binary_set },
4267+ { "binary setq", test_binary_setq },
4268+ { "binary flush", test_binary_flush },
4269+ { "binary flushq", test_binary_flushq },
4270+ { "binary add", test_binary_add },
4271+ { "binary addq", test_binary_addq },
4272+ { "binary replace", test_binary_replace },
4273+ { "binary replaceq", test_binary_replaceq },
4274+ { "binary delete", test_binary_delete },
4275+ { "binary deleteq", test_binary_deleteq },
4276+ { "binary get", test_binary_get },
4277+ { "binary getq", test_binary_getq },
4278+ { "binary getk", test_binary_getk },
4279+ { "binary getkq", test_binary_getkq },
4280+ { "binary incr", test_binary_incr },
4281+ { "binary incrq", test_binary_incrq },
4282+ { "binary decr", test_binary_decr },
4283+ { "binary decrq", test_binary_decrq },
4284+ { "binary version", test_binary_version },
4285+ { "binary append", test_binary_append },
4286+ { "binary appendq", test_binary_appendq },
4287+ { "binary prepend", test_binary_prepend },
4288+ { "binary prependq", test_binary_prependq },
4289+ { "binary stat", test_binary_stat },
4290+ { NULL, NULL}
4291+};
4292+
4293+const int ascii_tests = 1;
4294+const int binary_tests = 2;
4295+
4296+struct test_type_st
4297+{
4298+ bool ascii;
4299+ bool binary;
4300+};
4301+
4302+int main(int argc, char **argv)
4303+{
4304+ static const char * const status_msg[]= {"[skip]", "[pass]", "[pass]", "[FAIL]"};
4305+ struct test_type_st tests= { true, true };
4306+ int total= 0;
4307+ int failed= 0;
4308+ const char *hostname= "localhost";
4309+ const char *port= "11211";
4310+ int cmd;
4311+ bool prompt= false;
4312+ const char *testname= NULL;
4313+
4314+
4315+
4316+ while ((cmd= getopt(argc, argv, "t:vch:p:PT:?ab")) != EOF)
4317+ {
4318+ switch (cmd) {
4319+ case 'a':
4320+ tests.ascii= true;
4321+ tests.binary= false;
4322+ break;
4323+ case 'b':
4324+ tests.ascii= false;
4325+ tests.binary= true;
4326+ break;
4327+ case 't':
4328+ timeout= atoi(optarg);
4329+ if (timeout == 0)
4330+ {
4331+ fprintf(stderr, "Invalid timeout. Please specify a number for -t\n");
4332+ return EXIT_FAILURE;
4333+ }
4334+ break;
4335+ case 'v': verbose= true;
4336+ break;
4337+ case 'c': do_core= true;
4338+ break;
4339+ case 'h': hostname= optarg;
4340+ break;
4341+ case 'p': port= optarg;
4342+ break;
4343+ case 'P': prompt= true;
4344+ break;
4345+ case 'T': testname= optarg;
4346+ break;
4347+ default:
4348+ fprintf(stderr, "Usage: %s [-h hostname] [-p port] [-c] [-v] [-t n] [-P] [-T testname]'\n"
4349+ "\t-c\tGenerate coredump if a test fails\n"
4350+ "\t-v\tVerbose test output (print out the assertion)\n"
4351+ "\t-t n\tSet the timeout for io-operations to n seconds\n"
4352+ "\t-P\tPrompt the user before starting a test.\n"
4353+ "\t\t\t\"skip\" will skip the test\n"
4354+ "\t\t\t\"quit\" will terminate memcapable\n"
4355+ "\t\t\tEverything else will start the test\n"
4356+ "\t-T n\tJust run the test named n\n"
4357+ "\t-a\tOnly test the ascii protocol\n"
4358+ "\t-b\tOnly test the binary protocol\n",
4359+ argv[0]);
4360+ return EXIT_FAILURE;
4361+ }
4362+ }
4363+
4364+ initialize_sockets();
4365+ sock= connect_server(hostname, port);
4366+ if (sock == INVALID_SOCKET)
4367+ {
4368+ fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
4369+ hostname, port, strerror(get_socket_errno()));
4370+ return EXIT_FAILURE;
4371+ }
4372+
4373+ for (int ii= 0; testcases[ii].description != NULL; ++ii)
4374+ {
4375+ if (testname != NULL && strcmp(testcases[ii].description, testname) != 0)
4376+ continue;
4377+
4378+ if ((testcases[ii].description[0] == 'a' && (tests.ascii) == 0) ||
4379+ (testcases[ii].description[0] == 'b' && (tests.binary) == 0))
4380+ {
4381+ continue;
4382+ }
4383+ ++total;
4384+ fprintf(stdout, "%-40s", testcases[ii].description);
4385+ fflush(stdout);
4386+
4387+ if (prompt)
4388+ {
4389+ fprintf(stdout, "\nPress <return> when you are ready? ");
4390+ char buffer[80] = {0};
4391+ if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
4392+ if (strncmp(buffer, "skip", 4) == 0)
4393+ {
4394+ fprintf(stdout, "%-40s%s\n", testcases[ii].description,
4395+ status_msg[TEST_SKIP]);
4396+ fflush(stdout);
4397+ continue;
4398+ }
4399+ if (strncmp(buffer, "quit", 4) == 0)
4400+ exit(0);
4401+ }
4402+
4403+ fprintf(stdout, "%-40s", testcases[ii].description);
4404+ fflush(stdout);
4405+ }
4406+
4407+ bool reconnect= false;
4408+ enum test_return ret= testcases[ii].function();
4409+ if (ret == TEST_FAIL)
4410+ {
4411+ reconnect= true;
4412+ ++failed;
4413+ if (verbose)
4414+ fprintf(stderr, "\n");
4415+ }
4416+ else if (ret == TEST_PASS_RECONNECT)
4417+ reconnect= true;
4418+
4419+ fprintf(stderr, "%s\n", status_msg[ret]);
4420+ if (reconnect)
4421+ {
4422+ closesocket(sock);
4423+ if ((sock= connect_server(hostname, port)) == INVALID_SOCKET)
4424+ {
4425+ fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
4426+ hostname, port, strerror(get_socket_errno()));
4427+ fprintf(stderr, "%d of %d tests failed\n", failed, total);
4428+ return EXIT_FAILURE;
4429+ }
4430+ }
4431+ }
4432+
4433+ closesocket(sock);
4434+ if (failed == 0)
4435+ fprintf(stdout, "All tests passed\n");
4436+ else
4437+ fprintf(stderr, "%d of %d tests failed\n", failed, total);
4438+
4439+ return (failed == 0) ? 0 : 1;
4440+}
4441
4442=== added file 'clients/memcat.cc'
4443--- clients/memcat.cc 1970-01-01 00:00:00 +0000
4444+++ clients/memcat.cc 2011-06-23 07:17:28 +0000
4445@@ -0,0 +1,242 @@
4446+/* LibMemcached
4447+ * Copyright (C) 2006-2009 Brian Aker
4448+ * All rights reserved.
4449+ *
4450+ * Use and distribution licensed under the BSD license. See
4451+ * the COPYING file in the parent directory for full text.
4452+ *
4453+ * Summary:
4454+ *
4455+ */
4456+
4457+#include "config.h"
4458+
4459+#include <stdio.h>
4460+#include <inttypes.h>
4461+#include <string.h>
4462+#include <unistd.h>
4463+#include <getopt.h>
4464+#include <libmemcached/memcached.h>
4465+
4466+#include "utilities.h"
4467+
4468+#define PROGRAM_NAME "memcat"
4469+#define PROGRAM_DESCRIPTION "Cat a set of key values to stdout."
4470+
4471+
4472+/* Prototypes */
4473+void options_parse(int argc, char *argv[]);
4474+
4475+static int opt_binary= 0;
4476+static int opt_verbose= 0;
4477+static int opt_displayflag= 0;
4478+static char *opt_servers= NULL;
4479+static char *opt_hash= NULL;
4480+static char *opt_username;
4481+static char *opt_passwd;
4482+static char *opt_file;
4483+
4484+int main(int argc, char *argv[])
4485+{
4486+ memcached_st *memc;
4487+ char *string;
4488+ size_t string_length;
4489+ uint32_t flags;
4490+ memcached_return_t rc;
4491+ memcached_server_st *servers;
4492+
4493+ int return_code= 0;
4494+
4495+ options_parse(argc, argv);
4496+ initialize_sockets();
4497+
4498+ if (!opt_servers)
4499+ {
4500+ char *temp;
4501+
4502+ if ((temp= getenv("MEMCACHED_SERVERS")))
4503+ opt_servers= strdup(temp);
4504+ else
4505+ {
4506+ fprintf(stderr, "No Servers provided\n");
4507+ exit(1);
4508+ }
4509+ }
4510+
4511+ memc= memcached_create(NULL);
4512+ process_hash_option(memc, opt_hash);
4513+
4514+ servers= memcached_servers_parse(opt_servers);
4515+
4516+ memcached_server_push(memc, servers);
4517+ memcached_server_list_free(servers);
4518+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
4519+ (uint64_t)opt_binary);
4520+
4521+ if (!initialize_sasl(memc, opt_username, opt_passwd))
4522+ {
4523+ memcached_free(memc);
4524+ return EXIT_FAILURE;
4525+ }
4526+
4527+ while (optind < argc)
4528+ {
4529+ string= memcached_get(memc, argv[optind], strlen(argv[optind]),
4530+ &string_length, &flags, &rc);
4531+ if (rc == MEMCACHED_SUCCESS)
4532+ {
4533+ if (opt_displayflag)
4534+ {
4535+ if (opt_verbose)
4536+ printf("key: %s\nflags: ", argv[optind]);
4537+ printf("%x\n", flags);
4538+ }
4539+ else
4540+ {
4541+ if (opt_verbose)
4542+ {
4543+ printf("key: %s\nflags: %x\nlength: %lu\nvalue: ",
4544+ argv[optind], flags, (unsigned long)string_length);
4545+ }
4546+
4547+ if (opt_file)
4548+ {
4549+ FILE *fp;
4550+ size_t written;
4551+
4552+ fp= fopen(opt_file, "w");
4553+ if (!fp)
4554+ {
4555+ perror("fopen");
4556+ return_code= -1;
4557+ break;
4558+ }
4559+
4560+ written= fwrite(string, 1, string_length, fp);
4561+ if (written != string_length)
4562+ {
4563+ fprintf(stderr, "error writing file (written %lu, should be %lu)\n", (unsigned long)written, (unsigned long)string_length);
4564+ return_code= -1;
4565+ break;
4566+ }
4567+
4568+ if (fclose(fp))
4569+ {
4570+ fprintf(stderr, "error closing file\n");
4571+ return_code= -1;
4572+ break;
4573+ }
4574+ }
4575+ else
4576+ {
4577+ printf("%.*s\n", (int)string_length, string);
4578+ }
4579+ free(string);
4580+ }
4581+ }
4582+ else if (rc != MEMCACHED_NOTFOUND)
4583+ {
4584+ fprintf(stderr, "memcat: %s: memcache error %s",
4585+ argv[optind], memcached_strerror(memc, rc));
4586+ if (memcached_last_error_errno(memc))
4587+ {
4588+ fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
4589+ }
4590+ fprintf(stderr, "\n");
4591+
4592+ return_code= -1;
4593+ break;
4594+ }
4595+ else // Unknown Issue
4596+ {
4597+ fprintf(stderr, "memcat: %s not found\n", argv[optind]);
4598+ return_code= -1;
4599+ }
4600+ optind++;
4601+ }
4602+
4603+ memcached_free(memc);
4604+
4605+ if (opt_servers)
4606+ free(opt_servers);
4607+ if (opt_hash)
4608+ free(opt_hash);
4609+
4610+ shutdown_sasl();
4611+
4612+ return return_code;
4613+}
4614+
4615+
4616+void options_parse(int argc, char *argv[])
4617+{
4618+ int option_index= 0;
4619+ int option_rv;
4620+
4621+ memcached_programs_help_st help_options[]=
4622+ {
4623+ {0},
4624+ };
4625+
4626+ static struct option long_options[]=
4627+ {
4628+ {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
4629+ {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
4630+ {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
4631+ {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
4632+ {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
4633+ {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
4634+ {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
4635+ {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
4636+ {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
4637+ {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
4638+ {(OPTIONSTRING)"file", required_argument, NULL, OPT_FILE},
4639+ {0, 0, 0, 0},
4640+ };
4641+
4642+ while (1)
4643+ {
4644+ option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
4645+ if (option_rv == -1) break;
4646+ switch (option_rv)
4647+ {
4648+ case 0:
4649+ break;
4650+ case OPT_BINARY:
4651+ opt_binary = 1;
4652+ break;
4653+ case OPT_VERBOSE: /* --verbose or -v */
4654+ opt_verbose = OPT_VERBOSE;
4655+ break;
4656+ case OPT_DEBUG: /* --debug or -d */
4657+ opt_verbose = OPT_DEBUG;
4658+ break;
4659+ case OPT_VERSION: /* --version or -V */
4660+ version_command(PROGRAM_NAME);
4661+ break;
4662+ case OPT_HELP: /* --help or -h */
4663+ help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
4664+ break;
4665+ case OPT_SERVERS: /* --servers or -s */
4666+ opt_servers= strdup(optarg);
4667+ break;
4668+ case OPT_HASH:
4669+ opt_hash= strdup(optarg);
4670+ break;
4671+ case OPT_USERNAME:
4672+ opt_username= optarg;
4673+ break;
4674+ case OPT_PASSWD:
4675+ opt_passwd= optarg;
4676+ break;
4677+ case OPT_FILE:
4678+ opt_file= optarg;
4679+ break;
4680+ case '?':
4681+ /* getopt_long already printed an error message. */
4682+ exit(1);
4683+ default:
4684+ abort();
4685+ }
4686+ }
4687+}
4688
4689=== added file 'clients/memcp.cc'
4690--- clients/memcp.cc 1970-01-01 00:00:00 +0000
4691+++ clients/memcp.cc 2011-06-23 07:17:28 +0000
4692@@ -0,0 +1,317 @@
4693+/* LibMemcached
4694+ * Copyright (C) 2006-2009 Brian Aker
4695+ * All rights reserved.
4696+ *
4697+ * Use and distribution licensed under the BSD license. See
4698+ * the COPYING file in the parent directory for full text.
4699+ *
4700+ * Summary:
4701+ *
4702+ */
4703+
4704+#include "config.h"
4705+
4706+#include <stdio.h>
4707+#include <stdlib.h>
4708+#include <inttypes.h>
4709+#include <unistd.h>
4710+#include <getopt.h>
4711+#include <sys/types.h>
4712+#include <sys/stat.h>
4713+#include <sys/types.h>
4714+#include <fcntl.h>
4715+#include <errno.h>
4716+#include <strings.h>
4717+#include <string.h>
4718+#include <sys/types.h>
4719+#include <stdlib.h>
4720+#include <limits.h>
4721+
4722+
4723+#include <libmemcached/memcached.h>
4724+
4725+#include "client_options.h"
4726+#include "utilities.h"
4727+
4728+#define PROGRAM_NAME "memcp"
4729+#define PROGRAM_DESCRIPTION "Copy a set of files to a memcached cluster."
4730+
4731+/* Prototypes */
4732+static void options_parse(int argc, char *argv[]);
4733+
4734+static int opt_binary=0;
4735+static int opt_verbose= 0;
4736+static char *opt_servers= NULL;
4737+static char *opt_hash= NULL;
4738+static int opt_method= OPT_SET;
4739+static uint32_t opt_flags= 0;
4740+static time_t opt_expires= 0;
4741+static char *opt_username;
4742+static char *opt_passwd;
4743+
4744+static long strtol_wrapper(const char *nptr, int base, bool *error)
4745+{
4746+ long val;
4747+ char *endptr;
4748+
4749+ errno= 0; /* To distinguish success/failure after call */
4750+ val= strtol(nptr, &endptr, base);
4751+
4752+ /* Check for various possible errors */
4753+
4754+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
4755+ || (errno != 0 && val == 0))
4756+ {
4757+ *error= true;
4758+ return EXIT_SUCCESS;
4759+ }
4760+
4761+ if (endptr == nptr)
4762+ {
4763+ *error= true;
4764+ return EXIT_SUCCESS;
4765+ }
4766+
4767+ *error= false;
4768+ return val;
4769+}
4770+
4771+int main(int argc, char *argv[])
4772+{
4773+ memcached_st *memc;
4774+ memcached_return_t rc;
4775+ memcached_server_st *servers;
4776+
4777+ int return_code= 0;
4778+
4779+ options_parse(argc, argv);
4780+ initialize_sockets();
4781+
4782+ memc= memcached_create(NULL);
4783+ process_hash_option(memc, opt_hash);
4784+
4785+ if (!opt_servers)
4786+ {
4787+ char *temp;
4788+
4789+ if ((temp= getenv("MEMCACHED_SERVERS")))
4790+ {
4791+ opt_servers= strdup(temp);
4792+ }
4793+ else
4794+ {
4795+ fprintf(stderr, "No Servers provided\n");
4796+ exit(1);
4797+ }
4798+ }
4799+
4800+ if (opt_servers)
4801+ servers= memcached_servers_parse(opt_servers);
4802+ else
4803+ servers= memcached_servers_parse(argv[--argc]);
4804+
4805+ memcached_server_push(memc, servers);
4806+ memcached_server_list_free(servers);
4807+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
4808+ (uint64_t)opt_binary);
4809+ if (!initialize_sasl(memc, opt_username, opt_passwd))
4810+ {
4811+ memcached_free(memc);
4812+ return EXIT_FAILURE;
4813+ }
4814+
4815+ while (optind < argc)
4816+ {
4817+ struct stat sbuf;
4818+ int fd;
4819+ char *ptr;
4820+ ssize_t read_length;
4821+ char *file_buffer_ptr;
4822+
4823+ fd= open(argv[optind], O_RDONLY);
4824+ if (fd < 0)
4825+ {
4826+ fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno));
4827+ optind++;
4828+ continue;
4829+ }
4830+
4831+ (void)fstat(fd, &sbuf);
4832+
4833+ ptr= rindex(argv[optind], '/');
4834+ if (ptr)
4835+ ptr++;
4836+ else
4837+ ptr= argv[optind];
4838+
4839+ if (opt_verbose)
4840+ {
4841+ static const char *opstr[] = { "set", "add", "replace" };
4842+ printf("op: %s\nsource file: %s\nlength: %lu\n"
4843+ "key: %s\nflags: %x\nexpires: %lu\n",
4844+ opstr[opt_method - OPT_SET], argv[optind], (unsigned long)sbuf.st_size,
4845+ ptr, opt_flags, (unsigned long)opt_expires);
4846+ }
4847+
4848+ if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
4849+ {
4850+ fprintf(stderr, "malloc: %s\n", strerror(errno));
4851+ exit(1);
4852+ }
4853+
4854+ if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
4855+ {
4856+ fprintf(stderr, "read: %s\n", strerror(errno));
4857+ exit(1);
4858+ }
4859+
4860+ if (read_length != sbuf.st_size)
4861+ {
4862+ fprintf(stderr, "Failure reading from file\n");
4863+ exit(1);
4864+ }
4865+
4866+ if (opt_method == OPT_ADD)
4867+ rc= memcached_add(memc, ptr, strlen(ptr),
4868+ file_buffer_ptr, (size_t)sbuf.st_size,
4869+ opt_expires, opt_flags);
4870+ else if (opt_method == OPT_REPLACE)
4871+ rc= memcached_replace(memc, ptr, strlen(ptr),
4872+ file_buffer_ptr, (size_t)sbuf.st_size,
4873+ opt_expires, opt_flags);
4874+ else
4875+ rc= memcached_set(memc, ptr, strlen(ptr),
4876+ file_buffer_ptr, (size_t)sbuf.st_size,
4877+ opt_expires, opt_flags);
4878+
4879+ if (rc != MEMCACHED_SUCCESS)
4880+ {
4881+ fprintf(stderr, "memcp: %s: memcache error %s",
4882+ ptr, memcached_strerror(memc, rc));
4883+ if (memcached_last_error_errno(memc))
4884+ fprintf(stderr, " system error %s", strerror(memcached_last_error_errno(memc)));
4885+ fprintf(stderr, "\n");
4886+
4887+ return_code= -1;
4888+ }
4889+
4890+ free(file_buffer_ptr);
4891+ close(fd);
4892+ optind++;
4893+ }
4894+
4895+ memcached_free(memc);
4896+
4897+ if (opt_servers)
4898+ free(opt_servers);
4899+ if (opt_hash)
4900+ free(opt_hash);
4901+ shutdown_sasl();
4902+
4903+ return return_code;
4904+}
4905+
4906+static void options_parse(int argc, char *argv[])
4907+{
4908+ int option_index= 0;
4909+ int option_rv;
4910+
4911+ memcached_programs_help_st help_options[]=
4912+ {
4913+ {0},
4914+ };
4915+
4916+ static struct option long_options[]=
4917+ {
4918+ {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
4919+ {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
4920+ {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
4921+ {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
4922+ {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
4923+ {(OPTIONSTRING)"flag", required_argument, NULL, OPT_FLAG},
4924+ {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
4925+ {(OPTIONSTRING)"set", no_argument, NULL, OPT_SET},
4926+ {(OPTIONSTRING)"add", no_argument, NULL, OPT_ADD},
4927+ {(OPTIONSTRING)"replace", no_argument, NULL, OPT_REPLACE},
4928+ {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
4929+ {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
4930+ {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
4931+ {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
4932+ {0, 0, 0, 0},
4933+ };
4934+
4935+ while (1)
4936+ {
4937+ option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
4938+
4939+ if (option_rv == -1) break;
4940+
4941+ switch (option_rv)
4942+ {
4943+ case 0:
4944+ break;
4945+ case OPT_BINARY:
4946+ opt_binary = 1;
4947+ break;
4948+ case OPT_VERBOSE: /* --verbose or -v */
4949+ opt_verbose = OPT_VERBOSE;
4950+ break;
4951+ case OPT_DEBUG: /* --debug or -d */
4952+ opt_verbose = OPT_DEBUG;
4953+ break;
4954+ case OPT_VERSION: /* --version or -V */
4955+ version_command(PROGRAM_NAME);
4956+ break;
4957+ case OPT_HELP: /* --help or -h */
4958+ help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
4959+ break;
4960+ case OPT_SERVERS: /* --servers or -s */
4961+ opt_servers= strdup(optarg);
4962+ break;
4963+ case OPT_FLAG: /* --flag */
4964+ {
4965+ bool strtol_error;
4966+ opt_flags= (uint32_t)strtol_wrapper(optarg, 16, &strtol_error);
4967+ if (strtol_error == true)
4968+ {
4969+ fprintf(stderr, "Bad value passed via --flag\n");
4970+ exit(1);
4971+ }
4972+ break;
4973+ }
4974+ case OPT_EXPIRE: /* --expire */
4975+ {
4976+ bool strtol_error;
4977+ opt_expires= (time_t)strtol_wrapper(optarg, 16, &strtol_error);
4978+ if (strtol_error == true)
4979+ {
4980+ fprintf(stderr, "Bad value passed via --flag\n");
4981+ exit(1);
4982+ }
4983+ }
4984+ case OPT_SET:
4985+ opt_method= OPT_SET;
4986+ break;
4987+ case OPT_REPLACE:
4988+ opt_method= OPT_REPLACE;
4989+ break;
4990+ case OPT_ADD:
4991+ opt_method= OPT_ADD;
4992+ break;
4993+ case OPT_HASH:
4994+ opt_hash= strdup(optarg);
4995+ break;
4996+ case OPT_USERNAME:
4997+ opt_username= optarg;
4998+ break;
4999+ case OPT_PASSWD:
5000+ opt_passwd= optarg;
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: