Merge lp:~avsej/libmemcached/touch-command into lp:~tangent-org/libmemcached/trunk
- touch-command
- Merge into 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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Libmemcached-developers | Pending | ||
Review via email:
|
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 : | # |
- 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.
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. developers (libmemcached- developers) /code.launchpad .net/~avsej/ libmemcached/ touch-command/ +merge/ 65623 /code.launchpad .net/~avsej/ libmemcached/ touch-command/ +merge/ 65623 developers is requested to review the proposed merge of lp:~avsej/libmemcached/touch-command into lp:libmemcached. 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/libmemcac hedPlus. la$ +^tests/...
>
> Requested reviews:
> Libmemcached-
>
> For more details, see:
> https:/
>
> 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:/
> Your team 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/